mirror of
https://github.com/whyour/qinglong.git
synced 2026-09-20 16:07:11 +08:00
107 lines
3.5 KiB
JavaScript
107 lines
3.5 KiB
JavaScript
const assert = require('node:assert/strict');
|
|
const fs = require('node:fs');
|
|
const os = require('node:os');
|
|
const path = require('node:path');
|
|
const { test } = require('node:test');
|
|
|
|
const {
|
|
FileLocalCredentialAdministrationDelivery,
|
|
LocalCredentialAdministrationDeliveryError,
|
|
} = require('@qinglong/local-owner-console/credential-administration-delivery');
|
|
|
|
const MUTATION_ID = '81000000-0000-4000-8000-000000000001';
|
|
const RECOVERY_MUTATION_ID = '81000000-0000-4000-8000-000000000002';
|
|
const SECRET = Buffer.alloc(32, 81).toString('base64url');
|
|
|
|
function fixture(t) {
|
|
const root = fs.mkdtempSync(
|
|
path.join(fs.realpathSync(os.tmpdir()), 'ql3-managed-credential-'),
|
|
);
|
|
fs.chmodSync(root, 0o700);
|
|
t.after(() => fs.rmSync(root, { recursive: true, force: true }));
|
|
return root;
|
|
}
|
|
|
|
function record(overrides = {}) {
|
|
return {
|
|
schemaVersion: 1,
|
|
kind: 'qinglong3-local-managed-credential-delivery',
|
|
mutationId: MUTATION_ID,
|
|
requestId: 'managed-credential-issue',
|
|
projectId: 'default',
|
|
subject: { type: 'agent', id: 'agent-planner' },
|
|
credentialId: 'agent-planner-primary',
|
|
secret: SECRET,
|
|
notBeforeAtMs: 1_000,
|
|
expiresAtMs: 61_000,
|
|
...overrides,
|
|
};
|
|
}
|
|
|
|
test('stages, replays, publishes and acknowledges one private credential', (t) => {
|
|
const directory = fixture(t);
|
|
const delivery = new FileLocalCredentialAdministrationDelivery(directory);
|
|
const first = delivery.prepare(record());
|
|
const digest = delivery.digest(first);
|
|
|
|
const replay = delivery.prepare(
|
|
record({
|
|
secret: Buffer.alloc(32, 82).toString('base64url'),
|
|
notBeforeAtMs: 11_000,
|
|
expiresAtMs: 71_000,
|
|
}),
|
|
);
|
|
assert.equal(replay.secret, SECRET);
|
|
assert.equal(replay.notBeforeAtMs, 1_000);
|
|
assert.equal(delivery.digest(replay), digest);
|
|
|
|
const published = delivery.publish(replay, digest);
|
|
assert.equal(
|
|
path.basename(published.path),
|
|
`managed-credential-${MUTATION_ID}.ready.json`,
|
|
);
|
|
assert.equal(fs.statSync(published.path).mode & 0o777, 0o600);
|
|
assert.equal(delivery.inspect(MUTATION_ID).deliveryDigest, digest);
|
|
const presentation = JSON.parse(fs.readFileSync(published.path, 'utf8'));
|
|
assert.equal(
|
|
presentation.kind,
|
|
'qinglong3-local-identity-credential-presentation',
|
|
);
|
|
assert.match(presentation.token, /^ql3c_agent-planner-primary_/);
|
|
|
|
assert.equal(delivery.removeAcknowledged(MUTATION_ID, digest), 'removed');
|
|
assert.equal(delivery.removeAcknowledged(MUTATION_ID, digest), 'absent');
|
|
|
|
const recovery = delivery.prepare(
|
|
record({
|
|
mutationId: RECOVERY_MUTATION_ID,
|
|
requestId: 'managed-credential-cleanup-recovery',
|
|
}),
|
|
);
|
|
const recoveryDigest = delivery.digest(recovery);
|
|
const recoveryReady = delivery.publish(recovery, recoveryDigest);
|
|
fs.unlinkSync(recoveryReady.path);
|
|
assert.equal(
|
|
delivery.removeAcknowledged(RECOVERY_MUTATION_ID, recoveryDigest),
|
|
'removed',
|
|
);
|
|
});
|
|
|
|
test('rejects semantic replay drift and a symlinked delivery directory', (t) => {
|
|
const directory = fixture(t);
|
|
const delivery = new FileLocalCredentialAdministrationDelivery(directory);
|
|
delivery.prepare(record());
|
|
assert.throws(
|
|
() => delivery.prepare(record({ expiresAtMs: 62_000 })),
|
|
LocalCredentialAdministrationDeliveryError,
|
|
);
|
|
|
|
const link = `${directory}-link`;
|
|
fs.symlinkSync(directory, link);
|
|
t.after(() => fs.rmSync(link, { force: true }));
|
|
assert.throws(
|
|
() => new FileLocalCredentialAdministrationDelivery(link),
|
|
LocalCredentialAdministrationDeliveryError,
|
|
);
|
|
});
|