| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117 |
- import fs from 'node:fs';
- import path from 'node:path';
- import crypto from 'node:crypto';
- import { fileURLToPath } from 'node:url';
- import { request, invoke, appId, functionsUrl } from '../server/scripts/platform-client.mjs';
- import { sealCredential, sha256 } from './lib/workshop-credential-envelope.mjs';
- const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
- const INPUT = path.join(ROOT, 'docs/workshop-auth-recovery-20261108/receipts/r1-return');
- const OUTPUT = path.join(ROOT, 'artifacts/ksf-workshop-auth-envelope-20261108-r2/package');
- const must = (value, code) => { if (!value) throw Object.assign(new Error(code), { code }); };
- const json = file => JSON.parse(fs.readFileSync(file, 'utf8'));
- async function main() {
- must(process.argv.length === 2, 'USAGE');
- must(!fs.existsSync(OUTPUT), 'OUTPUT_EXISTS_KEEP_FROZEN_PACKAGE');
- const validation = json(path.join(INPUT, 'validation.json'));
- must(validation.ok && validation.originalFilesVerified === 5
- && validation.archiveSha256 === '4a55e70cab2a7a25be5131ea9a7a3da3bab2f06ad9aaaf07cd670121a4f48782', 'RETURN_NOT_VERIFIED');
- const original = path.join(INPUT, 'files');
- const incoming = json(path.join(INPUT, 'manifest.json'));
- for (const file of incoming.files) {
- must(!path.isAbsolute(file.path) && !file.path.split(/[\\/]/).includes('..'), 'BAD_RETURN_PATH');
- const bytes = fs.readFileSync(path.join(original, file.path));
- must(bytes.length === file.bytes && sha256(bytes) === file.sha256, 'RETURN_CHANGED');
- }
- const meta = json(path.join(original, 'public-recipient/recipient.json'));
- const receipt = json(path.join(original, 'agent-auth-receipt.json'));
- must(receipt.contract?.code === 'CREDENTIAL_EXPIRED_OR_MISMATCH'
- && receipt.skillStateUnchanged && receipt.businessRecordWrites === 0, 'UNEXPECTED_RETURN');
- must(meta.host === '043bb9231c09' && meta.publicKeySha256 === '1dbefc093985a077fdd7f7433bb024e93e69bf69e89ae8f7e25f749819025bae'
- && meta.keyDirectory === '/opt/data/ksf-key-receive-20261031-6R6BjG'
- && meta.privateKeyExported === false && meta.tokenExported === false, 'RECIPIENT_CHANGED');
- const pem = fs.readFileSync(path.join(original, 'public-recipient/recipient-public.pem'));
- const key = crypto.createPublicKey(pem);
- must(sha256(pem) === meta.exportedPublicPemSha256
- && sha256(key.export({ type: 'spki', format: 'der' })) === meta.publicKeySha256, 'PUBLIC_KEY_MISMATCH');
- const decryptor = fs.readFileSync(path.join(original, 'public-recipient/decrypt-module.mjs'));
- must(sha256(decryptor) === meta.decryptModuleSha256, 'DECRYPTOR_CHANGED');
- const wrapper = fs.readFileSync(path.join(ROOT, 'skills/ksf-workshop-runtime/scripts/ksf-secure.mjs'));
- must(sha256(wrapper) === receipt.wrapperSha256, 'WRAPPER_CHANGED');
- // Read the existing restricted configuration only into this process. Never package it.
- const env = {};
- for (const line of fs.readFileSync('F:/文档/康师傅数字人受限连接.env', 'utf8').split(/\r?\n/)) {
- const match = line.match(/^(KSF_SERVICE_TOKEN|KSF_FUNCTIONS_URL|KSF_PARSE_APP_ID)=(.*)$/);
- if (match) env[match[1]] = match[2].trim();
- }
- try {
- must(env.KSF_SERVICE_TOKEN && env.KSF_FUNCTIONS_URL === functionsUrl && env.KSF_PARSE_APP_ID === appId, 'CONFIG_MISMATCH');
- const current = await request('GET', '/classes/KsfServiceCredential/MqKRUv9JQc');
- const prior = json(path.join(ROOT, 'work/workshop-auth-recovery-20261108-r1/server-renewal-receipt.json'));
- const expiresAt = typeof current.expiresAt === 'string' ? current.expiresAt : current.expiresAt?.iso;
- must(current.objectId === prior.after.objectId && current.tokenHash === sha256(env.KSF_SERVICE_TOKEN)
- && current.enabled === true && expiresAt === prior.after.expiresAt
- && JSON.stringify(current.scopes) === JSON.stringify(prior.after.scopes)
- && JSON.stringify(current.projectIds) === JSON.stringify(prior.after.projectIds), 'SERVER_CREDENTIAL_CHANGED');
- const headers = { 'X-Parse-Application-Id': appId, 'X-Ksf-Service-Token': env.KSF_SERVICE_TOKEN, 'Content-Type': 'application/json' };
- const contract = await invoke('ksfGetIngestContract', { requestId: 'auth-envelope-20261108-r2-contract' }, headers);
- must(contract.http === 200 && contract.body.result?.ok === true
- && contract.body.result.data?.allowedClasses?.length > 0, 'RESTRICTED_CONTRACT_FAILED');
- const schema = await invoke('ksfGetDataDictionary', { summary: true, requestId: 'auth-envelope-20261108-r2-schema' }, headers);
- const dictionary = schema.body.result?.data;
- must(schema.http === 200 && schema.body.result?.ok === true && dictionary?.readOnly === true
- && dictionary.databaseWrites === 0 && dictionary.rowValuesReturned === false, 'RESTRICTED_SCHEMA_FAILED');
- const envelope = sealCredential({ publicKey: pem, host: meta.host, directory: meta.keyDirectory,
- credentialId: current.objectId, expiresAt, env });
- const envelopeBytes = Buffer.from(JSON.stringify(envelope, null, 2) + '\n');
- const release = {
- schema: 'ksf.workshop.encrypted-authorization-release.v1', preparedAt: new Date().toISOString(),
- host: meta.host, containerNameForOperator: 'agent-node-u17879018108', uid: 10000,
- skillDirectory: '/opt/data/skills/ksf-workshop-runtime', keyDirectory: meta.keyDirectory,
- publicKeySha256: meta.publicKeySha256, decryptModule: meta.decryptModule, decryptModuleSha256: meta.decryptModuleSha256,
- wrapperSha256: receipt.wrapperSha256, credentialId: current.objectId, expiresAt,
- expectedBindingSha256: meta.bindingSha256, oldEnvelopeFile: meta.envelopeFile, oldEnvelopeSha256: meta.envelopeSha256,
- installDirectory: '/opt/data/ksf-workshop-auth-envelope-20261108-r2',
- installEnvelope: '/opt/data/ksf-workshop-auth-envelope-20261108-r2/credential-envelope.json',
- envelopeSha256: sha256(envelopeBytes), originalReturnArchiveSha256: validation.archiveSha256,
- serverAuthorizationRestored: true, agentEncryptedEntryVerified: false, actualBusinessWriteVerified: false,
- formalReportSubmitted: false, serverAuthorizationRecordWrites: 0, businessRecordWrites: 0, paidCalls: 0,
- };
- const recheck = { checkedAt: new Date().toISOString(), readOnly: true,
- serverAuthorizationRestored: true, credentialId: current.objectId, expiresAt,
- originalTokenIdentityAndScopesPreserved: true, serverAuthorizationRecordWrites: 0, businessRecordWrites: 0, paidCalls: 0,
- contract: { http: contract.http, ok: true, allowedClassCount: contract.body.result.data.allowedClasses.length },
- schemaProbe: { http: schema.http, ok: true, readOnly: true, databaseWrites: 0, rowValuesReturned: false,
- tableCount: dictionary.tableCount, fieldCount: dictionary.fieldCount } };
- fs.mkdirSync(OUTPUT, { recursive: true });
- const write = (name, bytes) => {
- must(!Buffer.from(bytes).includes(Buffer.from(env.KSF_SERVICE_TOKEN)), 'PLAINTEXT_CREDENTIAL_IN_PACKAGE');
- const file = path.join(OUTPUT, name); fs.mkdirSync(path.dirname(file), { recursive: true });
- fs.writeFileSync(file, bytes, { flag: 'wx' });
- };
- write('credential-envelope.json', envelopeBytes);
- write('RELEASE.json', JSON.stringify(release, null, 2) + '\n');
- write('server-recheck.json', JSON.stringify(recheck, null, 2) + '\n');
- write('return-validation.json', JSON.stringify(validation, null, 2) + '\n');
- write('restore-workshop-credential-binding.mjs', fs.readFileSync(path.join(ROOT, 'scripts/restore-workshop-credential-binding.mjs')));
- write('lib/workshop-credential-envelope.mjs', fs.readFileSync(path.join(ROOT, 'scripts/lib/workshop-credential-envelope.mjs')));
- write('public-recipient/decrypt-module.mjs', decryptor);
- write('public-recipient/recipient.json', fs.readFileSync(path.join(original, 'public-recipient/recipient.json')));
- write('public-recipient/recipient-public.pem', pem);
- write('tests/credential-envelope.test.mjs', fs.readFileSync(path.join(ROOT, 'test/workshop-credential-envelope.test.mjs'), 'utf8')
- .replace("'../scripts/lib/workshop-credential-envelope.mjs'", "'../lib/workshop-credential-envelope.mjs'")
- .replace("'../scripts/restore-workshop-credential-binding.mjs'", "'../restore-workshop-credential-binding.mjs'")
- .replace("'../docs/workshop-auth-recovery-20261108/receipts/r1-return/files/public-recipient/decrypt-module.mjs'", "'../public-recipient/decrypt-module.mjs'"));
- write('运维001-原密钥重封安装复验-r2.md', fs.readFileSync(path.join(ROOT, 'docs/workshop-auth-recovery-20261108/运维001-原密钥重封安装复验-r2.md')));
- console.log(JSON.stringify({ prepared: true, directory: OUTPUT, expiresAt, serverReadOnlyRechecked: true,
- plaintextCredentialPackaged: false, agentEncryptedEntryVerified: false, remoteInstallationPending: true }));
- } finally { delete env.KSF_SERVICE_TOKEN; }
- }
- main().catch(error => {
- console.error(JSON.stringify({ ok: false, code: /^[A-Z][A-Z0-9_]+$/.test(error.code || '') ? error.code : 'PACKAGE_PREPARATION_STOPPED',
- message: '准备停止;不输出凭据、配置、原始服务器报文或异常。' }));
- process.exitCode = 1;
- });
|