| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119 |
- import fs from 'node:fs';
- import path from 'node:path';
- import crypto from 'node:crypto';
- import { fileURLToPath } from 'node:url';
- import { sealCredential, sha256 } from './lib/workshop-credential-envelope.mjs';
- import { request, invoke, appId, functionsUrl } from '../server/scripts/platform-client.mjs';
- const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
- const LONGTERM = process.argv[2] === '--longterm';
- const RECEIVED = path.join(ROOT, 'work/workshop-auth-envelope-recovery-20261108-r2/received');
- const RELEASE_NAME = LONGTERM ? '20261108-r3-longterm' : '20261108-r2';
- const PACKAGE = path.join(ROOT, 'artifacts/ksf-workshop-auth-envelope-renewal-' + RELEASE_NAME + '/package');
- const must = (condition, code) => { if (!condition) throw Object.assign(new Error(code), { code }); };
- const readJson = file => JSON.parse(fs.readFileSync(file, 'utf8'));
- const EXPECTED_SCOPES = ['source:write', 'ingest:write', 'data:read', 'report:ingest', 'report:publish', 'noise:write', 'noise:read'];
- async function main() {
- must(process.argv.length <= 3 && (!process.argv[2] || LONGTERM), 'USAGE');
- const manifest = readJson(path.join(RECEIVED, 'manifest.json'));
- const tar = fs.readFileSync(path.join(RECEIVED, 'wg-auth-return-5files.tar.gz'));
- must(tar.length === 5527 && sha256(tar) === 'c6e54d85bfec49a9a35def804d24d7e056b71e41239f4bb5c55fce7554dfbaad', 'RETURN_ARCHIVE_MISMATCH');
- for (const item of manifest.files) {
- must(!item.path.includes('..') && !path.isAbsolute(item.path), 'UNSAFE_RETURN_PATH');
- const bytes = fs.readFileSync(path.join(RECEIVED, 'files', item.path));
- must(bytes.length === item.bytes && sha256(bytes) === item.sha256, 'RETURN_MEMBER_MISMATCH');
- }
- const recipient = readJson(path.join(RECEIVED, 'files/public-recipient/recipient.json'));
- const publicPem = fs.readFileSync(path.join(RECEIVED, 'files/public-recipient/recipient-public.pem'));
- const publicKey = crypto.createPublicKey(publicPem);
- must(recipient.host === '043bb9231c09' && recipient.publicKeySha256 === '1dbefc093985a077fdd7f7433bb024e93e69bf69e89ae8f7e25f749819025bae'
- && sha256(publicKey.export({ type: 'spki', format: 'der' })) === recipient.publicKeySha256, 'RECIPIENT_MISMATCH');
- must(recipient.bindingSha256 === 'e2c8455e31525d292d84cb85ea9e2a61434b596788d13ef731b2fd4703ff6758'
- && recipient.decryptModuleSha256 === '43e462c21053c2829402e218b05aaa4438aed9552f561d54582675e687a63f79', 'BINDING_EVIDENCE_MISMATCH');
- let baseline = { expectedBindingSha256: recipient.bindingSha256,
- oldEnvelopeFile: recipient.envelopeFile, oldEnvelopeSha256: recipient.envelopeSha256 };
- if (LONGTERM) {
- const installedReceiptBytes = fs.readFileSync(path.join(ROOT, 'docs/workshop-auth-recovery-20261108-r2/receipts/agent-auth-receipt-r2.json'));
- must(sha256(installedReceiptBytes) === '1c5b466c538e7e62dbda56d2d6df50f89238308a1c64de3aae8f39f48bdc99cd', 'INSTALLED_RECEIPT_MISMATCH');
- const installedReceipt = JSON.parse(installedReceiptBytes);
- const previousRelease = readJson(path.join(ROOT, 'artifacts/ksf-workshop-auth-envelope-renewal-20261108-r2/package/RELEASE.json'));
- must(installedReceipt.ok === true && installedReceipt.agentEncryptedEntryVerified === true && installedReceipt.host === recipient.host
- && installedReceipt.bindingSha256 === 'f4dac8ab49032481bcf0ab8115e126bb2563df8ac0e8aeb64ac8a23473347e29', 'PREVIOUS_INSTALL_NOT_VERIFIED');
- baseline = { expectedBindingSha256: installedReceipt.bindingSha256,
- oldEnvelopeFile: previousRelease.installEnvelope, oldEnvelopeSha256: previousRelease.envelopeSha256 };
- }
- const env = {};
- for (const line of fs.readFileSync('F:/文档/康师傅数字人受限连接.env', 'utf8').split(/\r?\n/)) {
- const m = line.match(/^(KSF_SERVICE_TOKEN|KSF_FUNCTIONS_URL|KSF_PARSE_APP_ID)=(.*)$/);
- if (m) env[m[1]] = m[2].trim();
- }
- must(env.KSF_SERVICE_TOKEN && env.KSF_FUNCTIONS_URL === functionsUrl && env.KSF_PARSE_APP_ID === appId, 'SERVICE_CONFIG_MISMATCH');
- const result = await request('GET', '/classes/KsfServiceCredential?' + new URLSearchParams({ where: JSON.stringify({ tokenHash: sha256(env.KSF_SERVICE_TOKEN) }), limit: '2' }));
- must(result.results?.length === 1, 'CREDENTIAL_IDENTITY_MISMATCH');
- const credential = result.results[0], expiresAt = credential.expiresAt?.iso || credential.expiresAt;
- must(credential.objectId === 'MqKRUv9JQc' && credential.enabled === true && Date.parse(expiresAt) > Date.now(), 'CREDENTIAL_NOT_ACTIVE');
- must(JSON.stringify(credential.scopes) === JSON.stringify(EXPECTED_SCOPES) && JSON.stringify(credential.projectIds) === '["*"]', 'CREDENTIAL_SCOPE_CHANGED');
- must(expiresAt === (LONGTERM ? '9999-12-31T00:00:00.000Z' : '2026-11-15T01:48:23.854Z'), 'UNEXPECTED_SERVER_EXPIRY');
- const live = await invoke('ksfGetIngestContract', { requestId: 'auth-envelope-package-20261108-r2' }, {
- 'Content-Type': 'application/json', 'X-Parse-Application-Id': appId, 'X-Ksf-Service-Token': env.KSF_SERVICE_TOKEN,
- });
- must(live.http === 200 && live.body.result?.ok === true, 'RESTRICTED_SERVICE_RECHECK_FAILED');
- fs.mkdirSync(PACKAGE, { recursive: true });
- const envelopePath = path.join(PACKAGE, 'credential-envelope.json');
- let envelope;
- if (fs.existsSync(envelopePath)) {
- envelope = readJson(envelopePath);
- must(envelope.header?.recipientHost === recipient.host && envelope.header?.expiresAt === expiresAt
- && envelope.header?.publicKeySha256 === recipient.publicKeySha256, 'EXISTING_PACKAGE_CONFLICT');
- } else {
- envelope = sealCredential({ publicKey: publicPem, host: recipient.host, directory: recipient.keyDirectory,
- credentialId: credential.objectId, expiresAt, env });
- fs.writeFileSync(envelopePath, JSON.stringify(envelope, null, 2) + '\n', { flag: 'wx', mode: 0o600 });
- }
- const wrapperSha256 = sha256(fs.readFileSync(path.join(ROOT, 'skills/ksf-workshop-runtime/scripts/ksf-secure.mjs')));
- must(wrapperSha256 === manifest.originalExecution.wrapperSha256, 'WRAPPER_BASELINE_MISMATCH');
- const release = {
- schema: 'ksf.workshop.encrypted-authorization-release.v1', release: RELEASE_NAME, builtAt: new Date().toISOString(),
- host: recipient.host, executionUid: 10000, containerNameObserved: manifest.instance.container,
- skillDirectory: '/opt/data/skills/ksf-workshop-runtime', wrapperSha256,
- ...baseline,
- keyDirectory: recipient.keyDirectory, publicKeySha256: recipient.publicKeySha256,
- decryptModule: recipient.decryptModule, decryptModuleSha256: recipient.decryptModuleSha256,
- credentialId: credential.objectId, expiresAt, envelopeSha256: sha256(fs.readFileSync(envelopePath)),
- installDirectory: '/opt/data/ksf-workshop-auth-envelope-' + RELEASE_NAME,
- installEnvelope: '/opt/data/ksf-workshop-auth-envelope-' + RELEASE_NAME + '/credential-envelope.json',
- bindingFieldsToChange: ['envelopeFile', 'envelopeSha256'],
- restrictedServiceProbe: { checkedAt: new Date().toISOString(), http: live.http, ok: true,
- allowedClassCount: live.body.result.data?.allowedClasses?.length },
- serviceIdentityPreserved: true, tokenPreserved: true, scopesPreserved: true, privateKeyIncluded: false,
- plaintextCredentialIncluded: false, businessRecordWrites: 0, serverAuthorizationRecordWritesDuringPackaging: 0, paidCalls: 0,
- agentEncryptedEntryVerified: false, actualBusinessWriteVerified: false,
- authorizationMode: LONGTERM ? 'long-term-with-explicit-expiry' : 'seven-day-renewal', revocable: true,
- };
- fs.writeFileSync(path.join(PACKAGE, 'RELEASE.json'), JSON.stringify(release, null, 2) + '\n');
- fs.copyFileSync(path.join(ROOT, 'scripts/restore-workshop-credential-binding.mjs'), path.join(PACKAGE, 'restore-workshop-credential-binding.mjs'));
- fs.copyFileSync(path.join(ROOT, LONGTERM ? 'docs/workshop-longterm-authorization-20261108-r3/发给运维001-长期授权.md'
- : 'docs/workshop-auth-recovery-20261108-r2/发给运维001-加密授权更新.md'), path.join(PACKAGE, 'README.md'));
- const verification = readJson(path.join(ROOT, 'work/workshop-auth-envelope-recovery-20261108-r2/'
- + (LONGTERM ? 'local-verification-longterm.json' : 'local-verification.json')));
- must(verification.ok === true && verification.cryptoTestsPassed === (LONGTERM ? 9 : 8), 'LOCAL_VERIFICATION_REQUIRED');
- fs.writeFileSync(path.join(PACKAGE, 'local-verification.json'), JSON.stringify(verification, null, 2) + '\n');
- const files = fs.readdirSync(PACKAGE).filter(name => name !== 'FILES.sha256').sort();
- const lines = [];
- for (const name of files) {
- const bytes = fs.readFileSync(path.join(PACKAGE, name));
- must(!bytes.includes(Buffer.from(env.KSF_SERVICE_TOKEN)) && !bytes.includes(Buffer.from('-----BEGIN PRIVATE KEY-----')), 'PACKAGE_CONTAINS_PLAINTEXT_SECRET');
- lines.push(sha256(bytes) + ' ' + name);
- }
- fs.writeFileSync(path.join(PACKAGE, 'FILES.sha256'), lines.join('\n') + '\n');
- delete env.KSF_SERVICE_TOKEN;
- console.log(JSON.stringify({ ok: true, packageDirectory: PACKAGE, files: files.length, envelopeSha256: release.envelopeSha256,
- credentialExpiresAt: expiresAt, publicRecipientVerified: true, plaintextSecretScanPassed: true, businessRecordWrites: 0, paidCalls: 0 }, null, 2));
- }
- main().catch(error => {
- console.error(JSON.stringify({ ok: false, code: /^[A-Z][A-Z0-9_]+$/.test(error.code || '') ? error.code : 'ENCRYPTED_RENEWAL_PACKAGE_STOPPED',
- message: '封装停止;未输出令牌、管理配置或原始异常。' }));
- process.exitCode = 1;
- });
|