mirror of
https://github.com/whyour/qinglong.git
synced 2026-09-22 19:29:13 +08:00
feat(ql3): prove security administration custody live
This commit is contained in:
@@ -0,0 +1,175 @@
|
||||
const assert = require('node:assert/strict');
|
||||
const { test } = require('node:test');
|
||||
|
||||
const {
|
||||
FIXTURE,
|
||||
LIMITATIONS,
|
||||
validateSecurityAdministrationKubernetesLiveReport,
|
||||
} = require('../../scripts/ql3-security-administration-kubernetes-live-audit.cjs');
|
||||
|
||||
const digest = (value) => `sha256:${value.repeat(64)}`;
|
||||
|
||||
function report() {
|
||||
return {
|
||||
schemaVersion: 1,
|
||||
fixture: FIXTURE,
|
||||
observedAt: '2026-08-25T04:00:00.000Z',
|
||||
platform: {
|
||||
distribution: 'k3s',
|
||||
kubernetesVersion: 'v1.34.3+k3s1',
|
||||
architecture: 'amd64',
|
||||
kubernetesImageId: digest('1'),
|
||||
administrationImageId: digest('2'),
|
||||
cniName: 'flannel',
|
||||
cniDistributionBinding: 'rancher/k3s:v1.34.3-k3s1',
|
||||
controlPlaneNodes: 1,
|
||||
workerNodes: 2,
|
||||
readyNodes: 3,
|
||||
},
|
||||
database: {
|
||||
operator: 'cloudnative-pg',
|
||||
operatorVersion: '1.30.0',
|
||||
postgresVersionNumber: 180004,
|
||||
postgresImageId: digest('3'),
|
||||
instances: 3,
|
||||
readyInstances: 3,
|
||||
administrationRole: 'ql3_admin',
|
||||
roleConnectionLimit: 4,
|
||||
commandConnectionLimit: 1,
|
||||
migrationCount: 71,
|
||||
controlCoreCapability: 70,
|
||||
tlsVerified: true,
|
||||
leastPrivilege: true,
|
||||
},
|
||||
ceremony: {
|
||||
operations: [
|
||||
'identity.register',
|
||||
'audit.list',
|
||||
'credential.issue',
|
||||
'credential.issue.replay',
|
||||
'credential.rotate',
|
||||
'credential.revoke',
|
||||
],
|
||||
completedJobs: 6,
|
||||
failedJobs: 1,
|
||||
callerDriven: true,
|
||||
backoffLimit: 0,
|
||||
activeDeadlineSeconds: 300,
|
||||
ttlSecondsAfterFinished: 600,
|
||||
serviceAccount: 'ql3-security-administration',
|
||||
serviceAccountTokenMounted: false,
|
||||
rbacGranted: false,
|
||||
responseLossReplayObserved: true,
|
||||
sensitiveMaterialReported: false,
|
||||
},
|
||||
inputBoundary: {
|
||||
immutableSecret: true,
|
||||
projectedMode0440: true,
|
||||
memoryBackedPrivateStage: true,
|
||||
targetDirectoryMode0700: true,
|
||||
targetFilesMode0600: true,
|
||||
kubeletAtomicWriterProjectionAccepted: true,
|
||||
worldReadableProjectionRejected: true,
|
||||
mainContainerNotStartedAfterStageFailure: true,
|
||||
},
|
||||
deliveryCustody: {
|
||||
persistentVolumeClaim: true,
|
||||
accessMode: 'ReadWriteOnce',
|
||||
fixtureRootProvisioned: true,
|
||||
fixtureRootMode: '2770',
|
||||
fixtureProvisionerRanAsRoot: true,
|
||||
privateDirectoryMode: '0700',
|
||||
fileMode: '0600',
|
||||
fileCount: 2,
|
||||
issueDigest: digest('4'),
|
||||
rotationDigest: digest('5'),
|
||||
distinctRotationMaterial: true,
|
||||
persistentAcrossJobs: true,
|
||||
noReplaceReplayPreserved: true,
|
||||
deliverySchemaValidated: true,
|
||||
bearerFormatValidatedInPod: true,
|
||||
sensitiveMaterialReported: false,
|
||||
},
|
||||
isolation: {
|
||||
dnsAndDatabaseEgressAllowed: true,
|
||||
kubernetesApiEgressDenied: true,
|
||||
publicInternetEgressDenied: true,
|
||||
secretReadRbacDenied: true,
|
||||
jobMutationRbacDenied: true,
|
||||
},
|
||||
durability: {
|
||||
identityVersion: 1,
|
||||
identityStatus: 'active',
|
||||
credentialVersion: 3,
|
||||
credentialState: 'revoked',
|
||||
identityMutationCount: 1,
|
||||
credentialMutationCount: 3,
|
||||
issueMutationCount: 1,
|
||||
credentialVersionCount: 3,
|
||||
allowedAuditCount: 4,
|
||||
},
|
||||
cleanup: {
|
||||
jobsDeleted: true,
|
||||
inputSecretsDeleted: true,
|
||||
evidenceJobsDeleted: true,
|
||||
storageProvisionJobDeleted: true,
|
||||
deliveryVolumeClaimDeleted: true,
|
||||
},
|
||||
gates: {
|
||||
realThreeNodeKubernetes: true,
|
||||
realCloudNativePg: true,
|
||||
realKubeletSecretProjection: true,
|
||||
realAdministrationProductCommands: true,
|
||||
realPersistentCredentialCustody: true,
|
||||
responseLossReplay: true,
|
||||
failedInputStageClosed: true,
|
||||
leastPrivilege: true,
|
||||
contentFreeEvidence: true,
|
||||
passed: true,
|
||||
},
|
||||
limitations: [...LIMITATIONS],
|
||||
};
|
||||
}
|
||||
|
||||
test('accepts the exact content-free Security Administration live report', () => {
|
||||
const result = validateSecurityAdministrationKubernetesLiveReport(report());
|
||||
assert.equal(result.compatible, true);
|
||||
assert.deepEqual(result.findings, []);
|
||||
});
|
||||
|
||||
test('rejects widened authority, false custody and replay duplication', () => {
|
||||
const candidate = report();
|
||||
candidate.ceremony.serviceAccountTokenMounted = true;
|
||||
candidate.deliveryCustody.noReplaceReplayPreserved = false;
|
||||
candidate.durability.issueMutationCount = 2;
|
||||
candidate.gates.passed = false;
|
||||
const codes = validateSecurityAdministrationKubernetesLiveReport(
|
||||
candidate,
|
||||
).findings.map((finding) => finding.code);
|
||||
assert.ok(
|
||||
codes.includes('QL3_SECURITY_ADMINISTRATION_KUBERNETES_LIVE_CEREMONY'),
|
||||
);
|
||||
assert.ok(
|
||||
codes.includes('QL3_SECURITY_ADMINISTRATION_KUBERNETES_LIVE_DELIVERY'),
|
||||
);
|
||||
assert.ok(
|
||||
codes.includes('QL3_SECURITY_ADMINISTRATION_KUBERNETES_LIVE_DURABILITY'),
|
||||
);
|
||||
assert.ok(codes.includes('QL3_SECURITY_ADMINISTRATION_KUBERNETES_LIVE_GATES'));
|
||||
});
|
||||
|
||||
test('rejects any credential or assertion material in evidence', () => {
|
||||
const candidate = report();
|
||||
candidate.deliveryCustody.proof = {
|
||||
token: 'ql3c_example_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
|
||||
};
|
||||
const result = validateSecurityAdministrationKubernetesLiveReport(candidate);
|
||||
assert.equal(result.compatible, false);
|
||||
assert.ok(
|
||||
result.findings.some(
|
||||
(finding) =>
|
||||
finding.code ===
|
||||
'QL3_SECURITY_ADMINISTRATION_KUBERNETES_LIVE_MATERIAL_EXPOSURE',
|
||||
),
|
||||
);
|
||||
});
|
||||
Reference in New Issue
Block a user