Files
qinglong/scripts/ql3-cert-manager-selection-audit.cjs

228 lines
7.6 KiB
JavaScript

#!/usr/bin/env node
'use strict';
const fs = require('node:fs');
const path = require('node:path');
const SELECTION_DIRECTORY =
'deploy/kubernetes/ql3-cluster/operators/cert-manager';
const BARMAN_LOCK =
'deploy/kubernetes/ql3-cluster/operators/barman-cloud/plugin-lock.json';
const RELEASE_BLOCKERS = Object.freeze([
'live-cert-manager-api-and-plugin-mtls-rotation-evidence',
]);
const RELEASE_MANIFEST_SHA256 =
'7ee74ba06845213e96d8ceaff3d20dd51e682765c1418eddda4e8780ba082261';
const IMAGES = Object.freeze([
Object.freeze({
name: 'controller',
manifestReference: 'quay.io/jetstack/cert-manager-controller:v1.20.3',
image:
'quay.io/jetstack/cert-manager-controller:v1.20.3@sha256:6c13d61e0348a5bc3477f8ea9a928624300b30d19b1c72a7d2b90372fc713db4',
platforms: Object.freeze({
'linux/amd64':
'sha256:1e4af57beb469cc3bb0fb48b9201caea2723819b9ffd3c3ea98568f55b4dd38b',
'linux/arm64':
'sha256:af62a025ae4f8fd03209b5e0760868296bad5a9370aab0c91ad3b5476bcb282d',
}),
}),
Object.freeze({
name: 'cainjector',
manifestReference: 'quay.io/jetstack/cert-manager-cainjector:v1.20.3',
image:
'quay.io/jetstack/cert-manager-cainjector:v1.20.3@sha256:06ad347fe0dc2eb84cc355c26f6752e05e87dceb6447f5cd29b963dd66dfd8bd',
platforms: Object.freeze({
'linux/amd64':
'sha256:a2b12d27950d1603d2c8168c3ccd95d07b93ce6ec4b530316196a31db592a9c0',
'linux/arm64':
'sha256:3c052c134ad1b93122b957f4d214aaa9d85a37b5ff15acc5b4d86f50e3ed822e',
}),
}),
Object.freeze({
name: 'webhook',
manifestReference: 'quay.io/jetstack/cert-manager-webhook:v1.20.3',
image:
'quay.io/jetstack/cert-manager-webhook:v1.20.3@sha256:a61e817632cebed3bb59a189327e786fa3fdd7597167d994a1848d98fd55848f',
platforms: Object.freeze({
'linux/amd64':
'sha256:953a97df613f7da7eda8ce4b1c8d8e6b50963db0800fab595d040db6eb5cb060',
'linux/arm64':
'sha256:7c510875e038f79f7fba707b5f86d8736777a4dfefcd42179b08844ee75e685b',
}),
}),
]);
function finding(code, detail) {
return Object.freeze({ code, detail });
}
function exactJson(actual, expected) {
return JSON.stringify(actual) === JSON.stringify(expected);
}
function auditCertManagerSelection(options = {}) {
const root = path.resolve(options.root ?? path.join(__dirname, '..'));
const readFile = options.readFile ?? fs.readFileSync;
const readDirectory = options.readDirectory ?? fs.readdirSync;
const findings = [];
try {
const directory = path.join(root, SELECTION_DIRECTORY);
const entries = [...readDirectory(directory)].sort();
if (!exactJson(entries, ['selection-lock.json'])) {
findings.push(
finding(
'QL3_CERT_MANAGER_INSTALLER_UNVERIFIED',
'the selection directory must remain a lock-only input; installers are fetched and digest verified at deployment time',
),
);
}
const selection = JSON.parse(
readFile(path.join(directory, 'selection-lock.json'), 'utf8'),
);
if (
selection?.schemaVersion !== 1 ||
selection?.observedAt !== '2026-08-03' ||
selection?.certManager?.version !== '1.20.3' ||
selection?.certManager?.releaseManifest !==
'https://github.com/cert-manager/cert-manager/releases/download/v1.20.3/cert-manager.yaml' ||
selection?.certManager?.status !== 'supply-chain-verified'
) {
findings.push(
finding(
'QL3_CERT_MANAGER_SELECTION',
'cert-manager must remain fixed to the reviewed v1.20.3 selection until a new Kubernetes compatibility review',
),
);
}
if (
selection?.compatibility?.reviewedKubernetes !== '1.32.8' ||
selection?.compatibility?.supportedKubernetesMin !== '1.32' ||
selection?.compatibility?.supportedKubernetesMax !== '1.35' ||
selection?.compatibility?.newerMinorRejected !==
'1.21.0 requires Kubernetes 1.33 or newer'
) {
findings.push(
finding(
'QL3_CERT_MANAGER_KUBERNETES_COMPATIBILITY',
'the certificate controller selection must stay compatible with the locked Kubernetes 1.32.8 live gate',
),
);
}
if (
selection?.certManager?.releaseManifestSha256 !==
RELEASE_MANIFEST_SHA256 ||
!exactJson(selection?.certManager?.images, IMAGES) ||
selection?.releaseReady !== false ||
!exactJson(selection?.releaseBlockers, RELEASE_BLOCKERS)
) {
findings.push(
finding(
'QL3_CERT_MANAGER_PREMATURE_RELEASE',
'the exact release SHA and OCI platform digests must stay locked while live API and rotation evidence remains an explicit release blocker',
),
);
}
if (
selection?.scope?.profile !== 'cluster-only' ||
selection?.scope?.installNamespace !== 'cert-manager' ||
selection?.scope?.consumerNamespace !== 'cnpg-system' ||
selection?.scope?.requiredBy !== 'barman-cloud.cloudnative-pg.io@0.13.0'
) {
findings.push(
finding(
'QL3_CERT_MANAGER_SCOPE',
'cert-manager must remain cluster-only and separate from the Barman plugin namespace',
),
);
}
const pluginTls = selection?.pluginTls;
const certificates = pluginTls?.certificates;
if (
!exactJson(pluginTls?.issuer, {
apiVersion: 'cert-manager.io/v1',
kind: 'Issuer',
name: 'selfsigned-issuer',
namespace: 'cnpg-system',
type: 'SelfSigned',
}) ||
!exactJson(certificates, [
{
name: 'barman-cloud-client',
secretName: 'barman-cloud-client-tls',
commonName: 'barman-cloud-client',
usages: ['client auth'],
duration: '2160h',
renewBefore: '360h',
},
{
name: 'barman-cloud-server',
secretName: 'barman-cloud-server-tls',
commonName: 'barman-cloud',
dnsNames: ['barman-cloud'],
usages: ['server auth'],
duration: '2160h',
renewBefore: '360h',
},
])
) {
findings.push(
finding(
'QL3_CERT_MANAGER_PLUGIN_TLS',
'the Barman client/server certificate identities, usages and rotation window must match the reviewed release contract',
),
);
}
const barman = JSON.parse(readFile(path.join(root, BARMAN_LOCK), 'utf8'));
if (
!exactJson(barman?.certificateAuthority, {
mode: 'cert-manager',
version: '1.20.3',
selectionLock:
'deploy/kubernetes/ql3-cluster/operators/cert-manager/selection-lock.json',
releaseManifestUses: 'cert-manager.io/v1',
requiredSecrets: ['barman-cloud-client-tls', 'barman-cloud-server-tls'],
status: 'supply-chain-verified',
})
) {
findings.push(
finding(
'QL3_CERT_MANAGER_BARMAN_BINDING',
'the Barman candidate must bind the exact supply-chain-verified certificate authority without claiming live readiness',
),
);
}
} catch (error) {
findings.push(
finding(
'QL3_CERT_MANAGER_SELECTION_AUDIT_UNAVAILABLE',
error instanceof Error ? error.message : 'unknown audit failure',
),
);
}
return Object.freeze({
schemaVersion: 1,
certManagerVersion: '1.20.3',
kubernetesVersion: '1.32.8',
releaseReady: false,
releaseBlockers: RELEASE_BLOCKERS,
findings: Object.freeze(findings),
compatible: findings.length === 0,
});
}
if (require.main === module) {
const report = auditCertManagerSelection();
process.stdout.write(`${JSON.stringify(report)}\n`);
if (!report.compatible) process.exitCode = 1;
}
module.exports = {
auditCertManagerSelection,
};