mirror of
https://github.com/whyour/qinglong.git
synced 2026-09-22 02:27:44 +08:00
feat(ql3): establish 3.0 incubation baseline
This commit is contained in:
@@ -0,0 +1,338 @@
|
||||
const assert = require('node:assert/strict');
|
||||
const { randomUUID } = require('node:crypto');
|
||||
const fs = require('node:fs');
|
||||
const os = require('node:os');
|
||||
const path = require('node:path');
|
||||
const { test } = require('node:test');
|
||||
const {
|
||||
WorkerCredentialDeliveryConflictError,
|
||||
WorkerCredentialDeliveryUnavailableError,
|
||||
workerCredentialDeliveryTokenDigest,
|
||||
} = require('@qinglong/runtime-core/worker-credential-delivery');
|
||||
const {
|
||||
formatWorkerCredentialToken,
|
||||
} = require('@qinglong/runtime-core/worker-credential-token');
|
||||
const {
|
||||
MAX_WORKER_CREDENTIAL_FILE_STAGES,
|
||||
WorkerCredentialFileDeliveryAdapter,
|
||||
} = require('@qinglong/cluster-admin/worker-credential-file-delivery');
|
||||
const {
|
||||
createRecoverableWorkerCredentialIssuer,
|
||||
} = require('../dist/worker-credential/workerCredentialDelivery');
|
||||
|
||||
const DELIVERY_ID = '123e4567-e89b-42d3-a456-426614174901';
|
||||
const CREDENTIAL_ID = 'worker_generation_2';
|
||||
const PREVIOUS_CREDENTIAL_ID = 'worker_generation_1';
|
||||
const PEPPER = Buffer.alloc(32, 7).toString('base64url');
|
||||
|
||||
function fixture(t) {
|
||||
const root = fs.mkdtempSync(path.join(os.tmpdir(), 'ql3-worker-delivery-'));
|
||||
const stages = path.join(root, 'stages');
|
||||
const target = path.join(root, 'target');
|
||||
fs.mkdirSync(stages, { mode: 0o700 });
|
||||
fs.mkdirSync(target, { mode: 0o700 });
|
||||
const targetTokenFile = path.join(target, 'credential.token');
|
||||
t.after(() => fs.rmSync(root, { recursive: true, force: true }));
|
||||
const adapter = new WorkerCredentialFileDeliveryAdapter({
|
||||
stageDirectory: stages,
|
||||
targetTokenFile,
|
||||
});
|
||||
return { root, stages, target, targetTokenFile, adapter };
|
||||
}
|
||||
|
||||
function token(credentialId, fill) {
|
||||
return Buffer.from(formatWorkerCredentialToken(
|
||||
credentialId,
|
||||
Buffer.alloc(32, fill).toString('base64url'),
|
||||
));
|
||||
}
|
||||
|
||||
function intent(adapter, value, overrides = {}) {
|
||||
return {
|
||||
deliveryId: DELIVERY_ID,
|
||||
workerId: 'edge-router-1',
|
||||
credentialId: CREDENTIAL_ID,
|
||||
credentialVersion: 1,
|
||||
previousCredentialId: PREVIOUS_CREDENTIAL_ID,
|
||||
secretDigest: 'a'.repeat(64),
|
||||
tokenDigest: workerCredentialDeliveryTokenDigest(value),
|
||||
deploymentTargetDigest: adapter.deploymentTargetDigest,
|
||||
deploymentGeneration: 'secret-generation-2',
|
||||
stagedAtMs: 1_000,
|
||||
...overrides,
|
||||
};
|
||||
}
|
||||
|
||||
function committed(candidate, overrides = {}) {
|
||||
return {
|
||||
...candidate,
|
||||
version: 1,
|
||||
state: 'credential_committed',
|
||||
credentialCommittedAtMs: 1_000,
|
||||
publishedAtMs: null,
|
||||
publicationDigest: null,
|
||||
observedAtMs: null,
|
||||
observedSessionId: null,
|
||||
observedSessionVersion: null,
|
||||
previousRevokedAtMs: null,
|
||||
...overrides,
|
||||
};
|
||||
}
|
||||
|
||||
function deliveryAuthority() {
|
||||
let resolved = null;
|
||||
return {
|
||||
port: {
|
||||
async resolveMutation() { return resolved; },
|
||||
async append() { throw new Error('raw append is forbidden'); },
|
||||
async resolveDelivery() { return resolved?.delivery ?? null; },
|
||||
async resolveDelivered() { return resolved; },
|
||||
async commitDelivered(command) {
|
||||
resolved = {
|
||||
credential: command.credential.credential,
|
||||
mutation: command.credential.mutation,
|
||||
audit: command.credential.audit,
|
||||
delivery: command.delivery,
|
||||
};
|
||||
return {
|
||||
status: 'created',
|
||||
credential: resolved.credential,
|
||||
mutation: resolved.mutation,
|
||||
};
|
||||
},
|
||||
async markPublished(command) {
|
||||
resolved = {
|
||||
...resolved,
|
||||
delivery: {
|
||||
...resolved.delivery,
|
||||
version: 2,
|
||||
state: 'published',
|
||||
publishedAtMs: command.publishedAtMs,
|
||||
publicationDigest: command.publicationDigest,
|
||||
},
|
||||
};
|
||||
return resolved.delivery;
|
||||
},
|
||||
async listRecoveryPage() { throw new Error('not used'); },
|
||||
async revokePreviousDelivered() { throw new Error('not used'); },
|
||||
async authorizeStageDiscard() { throw new Error('not used'); },
|
||||
async markStageDiscarded() { throw new Error('not used'); },
|
||||
async listStageDiscardRecoveryPage() { throw new Error('not used'); },
|
||||
},
|
||||
current: () => resolved,
|
||||
};
|
||||
}
|
||||
|
||||
test('stages one private no-replace secret and inspects only its intent', async (t) => {
|
||||
const { adapter, stages } = fixture(t);
|
||||
const material = token(CREDENTIAL_ID, 2);
|
||||
const candidate = intent(adapter, material);
|
||||
await adapter.stage(candidate, material);
|
||||
material.fill(0);
|
||||
assert.deepEqual(await adapter.inspect(DELIVERY_ID), candidate);
|
||||
const stagePath = path.join(stages, `${DELIVERY_ID}.stage`);
|
||||
assert.equal(fs.statSync(stagePath).mode & 0o777, 0o600);
|
||||
assert.deepEqual(fs.readdirSync(stages), [`${DELIVERY_ID}.stage`]);
|
||||
|
||||
const replay = token(CREDENTIAL_ID, 2);
|
||||
await adapter.stage(candidate, replay);
|
||||
await assert.rejects(
|
||||
adapter.stage({ ...candidate, deploymentGeneration: 'other-generation' }, replay),
|
||||
WorkerCredentialDeliveryConflictError,
|
||||
);
|
||||
replay.fill(0);
|
||||
assert.equal((await adapter.inspect(DELIVERY_ID)).deploymentGeneration,
|
||||
'secret-generation-2');
|
||||
});
|
||||
|
||||
test('atomically replaces only the expected previous credential and replays publication', async (t) => {
|
||||
const { adapter, targetTokenFile, stages, target } = fixture(t);
|
||||
const previous = token(PREVIOUS_CREDENTIAL_ID, 1);
|
||||
fs.writeFileSync(targetTokenFile, previous, { mode: 0o600 });
|
||||
previous.fill(0);
|
||||
const material = token(CREDENTIAL_ID, 2);
|
||||
const candidate = intent(adapter, material);
|
||||
await adapter.stage(candidate, material);
|
||||
const publication = await adapter.publish(committed(candidate));
|
||||
assert.match(publication.publicationDigest, /^[0-9a-f]{64}$/);
|
||||
assert.deepEqual(fs.readFileSync(targetTokenFile), material);
|
||||
assert.equal(fs.statSync(targetTokenFile).mode & 0o777, 0o600);
|
||||
assert.deepEqual(fs.readdirSync(target), ['credential.token']);
|
||||
assert.deepEqual(fs.readdirSync(stages), [`${DELIVERY_ID}.stage`]);
|
||||
|
||||
const restarted = new WorkerCredentialFileDeliveryAdapter({
|
||||
stageDirectory: stages,
|
||||
targetTokenFile,
|
||||
});
|
||||
assert.deepEqual(
|
||||
await restarted.publish(committed(candidate)),
|
||||
publication,
|
||||
);
|
||||
material.fill(0);
|
||||
});
|
||||
|
||||
test('completes stage-before-commit issuance through the concrete file adapter', async (t) => {
|
||||
const { adapter, targetTokenFile } = fixture(t);
|
||||
const authority = deliveryAuthority();
|
||||
const generated = Buffer.alloc(32, 9);
|
||||
const service = createRecoverableWorkerCredentialIssuer(
|
||||
authority.port,
|
||||
adapter,
|
||||
PEPPER,
|
||||
{ now: () => 1_000, randomBytes: () => generated },
|
||||
);
|
||||
const result = await service.issue({
|
||||
mutationId: DELIVERY_ID,
|
||||
requestId: 'request-file-delivery-1',
|
||||
expectedCurrentVersion: 0,
|
||||
credentialId: CREDENTIAL_ID,
|
||||
workerId: 'edge-router-1',
|
||||
principal: {
|
||||
subject: { type: 'user', id: 'usr_admin' },
|
||||
authenticationId: 'session:admin:1',
|
||||
authenticatedAtMs: 900,
|
||||
expiresAtMs: 2_000,
|
||||
assurance: 'multi_factor',
|
||||
},
|
||||
notBeforeAtMs: 1_000,
|
||||
expiresAtMs: 2_000,
|
||||
previousCredentialId: null,
|
||||
deploymentTargetDigest: adapter.deploymentTargetDigest,
|
||||
deploymentGeneration: 'secret-generation-2',
|
||||
});
|
||||
assert.equal(result.status, 'published');
|
||||
assert.equal(result.delivery.state, 'published');
|
||||
assert.match(fs.readFileSync(targetTokenFile, 'ascii'),
|
||||
/^ql3w_worker_generation_2_[A-Za-z0-9_-]{43}$/);
|
||||
assert.equal(JSON.stringify(authority.current()).includes('ql3w_'), false);
|
||||
assert.equal(generated.every((byte) => byte === 0), true);
|
||||
});
|
||||
|
||||
test('fails closed instead of overwriting an unexpected target generation', async (t) => {
|
||||
const { adapter, targetTokenFile } = fixture(t);
|
||||
const unexpected = token('worker_generation_other', 3);
|
||||
fs.writeFileSync(targetTokenFile, unexpected, { mode: 0o600 });
|
||||
const material = token(CREDENTIAL_ID, 2);
|
||||
const candidate = intent(adapter, material);
|
||||
await adapter.stage(candidate, material);
|
||||
await assert.rejects(
|
||||
adapter.publish(committed(candidate)),
|
||||
WorkerCredentialDeliveryConflictError,
|
||||
);
|
||||
assert.deepEqual(fs.readFileSync(targetTokenFile), unexpected);
|
||||
unexpected.fill(0);
|
||||
material.fill(0);
|
||||
});
|
||||
|
||||
test('discards only an unpublished exact orphan stage', async (t) => {
|
||||
const { adapter, targetTokenFile } = fixture(t);
|
||||
const material = token(CREDENTIAL_ID, 2);
|
||||
const candidate = intent(adapter, material);
|
||||
await adapter.stage(candidate, material);
|
||||
await adapter.discard(candidate);
|
||||
assert.equal(await adapter.inspect(DELIVERY_ID), null);
|
||||
await adapter.discard(candidate);
|
||||
|
||||
await adapter.stage(candidate, material);
|
||||
fs.writeFileSync(targetTokenFile, material, { mode: 0o600 });
|
||||
await assert.rejects(
|
||||
adapter.discard(candidate),
|
||||
WorkerCredentialDeliveryConflictError,
|
||||
);
|
||||
assert.deepEqual(await adapter.inspect(DELIVERY_ID), candidate);
|
||||
material.fill(0);
|
||||
});
|
||||
|
||||
test('uses a durable target lock and leaves the old token untouched on contention', async (t) => {
|
||||
const { adapter, target, targetTokenFile } = fixture(t);
|
||||
const previous = token(PREVIOUS_CREDENTIAL_ID, 1);
|
||||
fs.writeFileSync(targetTokenFile, previous, { mode: 0o600 });
|
||||
fs.writeFileSync(
|
||||
path.join(target, '.ql3-worker-credential-delivery.lock'),
|
||||
`${JSON.stringify({ deliveryId: randomUUID() })}\n`,
|
||||
{ mode: 0o600 },
|
||||
);
|
||||
const material = token(CREDENTIAL_ID, 2);
|
||||
const candidate = intent(adapter, material);
|
||||
await adapter.stage(candidate, material);
|
||||
await assert.rejects(
|
||||
adapter.publish(committed(candidate)),
|
||||
WorkerCredentialDeliveryUnavailableError,
|
||||
);
|
||||
assert.deepEqual(fs.readFileSync(targetTokenFile), previous);
|
||||
previous.fill(0);
|
||||
material.fill(0);
|
||||
});
|
||||
|
||||
test('lists only bounded ordered low-sensitive stage intents', async (t) => {
|
||||
const { adapter, stages } = fixture(t);
|
||||
const firstToken = token(CREDENTIAL_ID, 2);
|
||||
const secondToken = token(CREDENTIAL_ID, 3);
|
||||
const first = intent(adapter, firstToken);
|
||||
const second = intent(adapter, secondToken, {
|
||||
deliveryId: '123e4567-e89b-42d3-a456-426614174902',
|
||||
tokenDigest: workerCredentialDeliveryTokenDigest(secondToken),
|
||||
deploymentGeneration: 'secret-generation-3',
|
||||
});
|
||||
await adapter.stage(second, secondToken);
|
||||
await adapter.stage(first, firstToken);
|
||||
assert.deepEqual(await adapter.listStaged({ limit: 1 }), {
|
||||
stages: [first],
|
||||
truncated: true,
|
||||
nextCursor: first.deliveryId,
|
||||
});
|
||||
assert.deepEqual(await adapter.listStaged({
|
||||
afterDeliveryId: first.deliveryId,
|
||||
limit: 1,
|
||||
}), {
|
||||
stages: [second],
|
||||
truncated: false,
|
||||
});
|
||||
fs.writeFileSync(
|
||||
path.join(stages, `.${DELIVERY_ID}.${randomUUID()}.tmp`),
|
||||
'uncertain',
|
||||
{ mode: 0o600 },
|
||||
);
|
||||
await assert.rejects(
|
||||
adapter.listStaged(),
|
||||
WorkerCredentialDeliveryUnavailableError,
|
||||
);
|
||||
firstToken.fill(0);
|
||||
secondToken.fill(0);
|
||||
});
|
||||
|
||||
test('enforces stage capacity, dedicated roots and live POSIX permissions', async (t) => {
|
||||
const { adapter, stages, target, targetTokenFile } = fixture(t);
|
||||
const material = token(CREDENTIAL_ID, 2);
|
||||
const candidate = intent(adapter, material);
|
||||
for (let index = 0; index < MAX_WORKER_CREDENTIAL_FILE_STAGES; index += 1) {
|
||||
fs.writeFileSync(
|
||||
path.join(stages, `${randomUUID()}.stage`),
|
||||
'bounded',
|
||||
{ mode: 0o600 },
|
||||
);
|
||||
}
|
||||
await assert.rejects(
|
||||
adapter.stage(candidate, material),
|
||||
WorkerCredentialDeliveryUnavailableError,
|
||||
);
|
||||
fs.rmSync(stages, { recursive: true });
|
||||
fs.mkdirSync(stages, { mode: 0o700 });
|
||||
const changed = new WorkerCredentialFileDeliveryAdapter({
|
||||
stageDirectory: stages,
|
||||
targetTokenFile,
|
||||
});
|
||||
const changedCandidate = intent(changed, material);
|
||||
await changed.stage(changedCandidate, material);
|
||||
fs.chmodSync(target, 0o755);
|
||||
await assert.rejects(
|
||||
changed.publish(committed(changedCandidate)),
|
||||
WorkerCredentialDeliveryUnavailableError,
|
||||
);
|
||||
fs.chmodSync(target, 0o700);
|
||||
assert.throws(() => new WorkerCredentialFileDeliveryAdapter({
|
||||
stageDirectory: target,
|
||||
targetTokenFile,
|
||||
}));
|
||||
material.fill(0);
|
||||
});
|
||||
Reference in New Issue
Block a user