mirror of
https://github.com/whyour/qinglong.git
synced 2026-09-20 16:07:11 +08:00
134 lines
4.7 KiB
TypeScript
134 lines
4.7 KiB
TypeScript
import type {
|
|
OpenPostgresDatabase,
|
|
PostgresDatabaseResource,
|
|
} from '@qinglong/runtime-core';
|
|
import { assertApiCredentialPepper } from '@qinglong/runtime-core/api-credential-token';
|
|
import { createSingletonApiCredentialPepperKeyring } from '@qinglong/runtime-core/api-credential-pepper-keyring';
|
|
import { LEGACY_API_CREDENTIAL_PEPPER_KEY_ID } from '@qinglong/runtime-core/api-credential';
|
|
import { assertWorkerCredentialPepper } from '@qinglong/runtime-core/worker-credential-token';
|
|
import type { SecurityAuditQueryRepository } from '@qinglong/runtime-core/security-audit-query';
|
|
import {
|
|
PostgresApiCredentialAdministrationRepository,
|
|
PostgresIdentityAdministrationRepository,
|
|
PostgresSecurityAuditQueryRepository,
|
|
PostgresWorkerCredentialAdministrationRepository,
|
|
assertPostgresAdminSchemaReady,
|
|
type PostgresSchemaReadinessReport,
|
|
} from '@qinglong/cluster-postgres/admin';
|
|
import {
|
|
createClusterAdministrationService,
|
|
type ClusterAdministrationOptions,
|
|
type ClusterAdministrationService,
|
|
} from '../security-administration/clusterAdministration';
|
|
import {
|
|
createWorkerCredentialAdministrationService,
|
|
type WorkerCredentialAdministrationService,
|
|
} from '../worker-credential/workerCredentialAdministration';
|
|
|
|
export interface ClusterAdminBootstrapOptions
|
|
extends ClusterAdministrationOptions {
|
|
readonly openDatabase: OpenPostgresDatabase;
|
|
readonly apiCredentialPepper: string;
|
|
readonly workerCredentialPepper: string;
|
|
}
|
|
|
|
export interface ClusterAdminRuntime {
|
|
readonly evidence: PostgresSchemaReadinessReport;
|
|
readonly administration: ClusterAdministrationService;
|
|
readonly audit: SecurityAuditQueryRepository;
|
|
readonly workerCredentials: WorkerCredentialAdministrationService;
|
|
close(): Promise<void>;
|
|
}
|
|
|
|
export async function bootstrapClusterAdmin(
|
|
options: ClusterAdminBootstrapOptions,
|
|
): Promise<ClusterAdminRuntime> {
|
|
if (!options || typeof options !== 'object' || Array.isArray(options)) {
|
|
throw new TypeError('Cluster admin bootstrap options are invalid');
|
|
}
|
|
if (typeof options.openDatabase !== 'function') {
|
|
throw new TypeError('Cluster admin database opener is invalid');
|
|
}
|
|
const optionKeys = new Set([
|
|
'openDatabase',
|
|
'apiCredentialPepper',
|
|
'workerCredentialPepper',
|
|
'now',
|
|
'randomBytes',
|
|
]);
|
|
if (Object.keys(options).some((key) => !optionKeys.has(key))) {
|
|
throw new TypeError('Cluster admin bootstrap options shape is invalid');
|
|
}
|
|
if (options.now !== undefined && typeof options.now !== 'function') {
|
|
throw new TypeError('Cluster admin clock is invalid');
|
|
}
|
|
if (
|
|
options.randomBytes !== undefined &&
|
|
typeof options.randomBytes !== 'function'
|
|
) {
|
|
throw new TypeError('Cluster admin random source is invalid');
|
|
}
|
|
try {
|
|
assertApiCredentialPepper(options.apiCredentialPepper);
|
|
} catch {
|
|
throw new TypeError('Cluster admin API credential pepper is invalid');
|
|
}
|
|
try {
|
|
assertWorkerCredentialPepper(options.workerCredentialPepper);
|
|
} catch {
|
|
throw new TypeError('Cluster admin Worker credential pepper is invalid');
|
|
}
|
|
let database: PostgresDatabaseResource | undefined;
|
|
let closePromise: Promise<void> | undefined;
|
|
const close = (): Promise<void> => {
|
|
if (!database) return Promise.resolve();
|
|
closePromise ??= database.close();
|
|
return closePromise;
|
|
};
|
|
try {
|
|
database = await options.openDatabase();
|
|
const evidence = await assertPostgresAdminSchemaReady(database.pool);
|
|
const identities = new PostgresIdentityAdministrationRepository(
|
|
database.pool,
|
|
);
|
|
const credentials = new PostgresApiCredentialAdministrationRepository(
|
|
database.pool,
|
|
);
|
|
return Object.freeze({
|
|
evidence,
|
|
administration: createClusterAdministrationService(
|
|
identities,
|
|
credentials,
|
|
createSingletonApiCredentialPepperKeyring(
|
|
options.apiCredentialPepper,
|
|
LEGACY_API_CREDENTIAL_PEPPER_KEY_ID,
|
|
).keys[0]!,
|
|
{
|
|
...(options.now ? { now: options.now } : {}),
|
|
...(options.randomBytes ? { randomBytes: options.randomBytes } : {}),
|
|
},
|
|
),
|
|
audit: new PostgresSecurityAuditQueryRepository(database.pool),
|
|
workerCredentials: createWorkerCredentialAdministrationService(
|
|
new PostgresWorkerCredentialAdministrationRepository(database.pool),
|
|
options.workerCredentialPepper,
|
|
{
|
|
...(options.now ? { now: options.now } : {}),
|
|
...(options.randomBytes ? { randomBytes: options.randomBytes } : {}),
|
|
},
|
|
),
|
|
close,
|
|
});
|
|
} catch (error) {
|
|
try {
|
|
await close();
|
|
} catch {
|
|
// Preserve configuration/readiness/assembly failure.
|
|
}
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
export * from '../security-administration/clusterAdministration';
|
|
export * from '../worker-credential/workerCredentialAdministration';
|