--- Build: pass | Tests: pass — 71 passed (3 files) --- Build: pass | Tests: pass — 2163 passed (630 files)
232 lines
7 KiB
TypeScript
232 lines
7 KiB
TypeScript
import { randomBytes } from 'crypto';
|
|
import fs from 'fs';
|
|
|
|
import {
|
|
brainDb,
|
|
brainDbUser,
|
|
forgejoDb,
|
|
forgejoDbUser,
|
|
opsDb,
|
|
opsDbUser,
|
|
sharedGitDb,
|
|
sharedGitDbUser,
|
|
sharedBrainDb,
|
|
sharedBrainDbUser,
|
|
sharedOpsDb,
|
|
sharedOpsDbUser,
|
|
sharedSkillsDb,
|
|
sharedSkillsDbUser,
|
|
skillsDb,
|
|
skillsDbUser,
|
|
} from '../src/db-identifiers.js';
|
|
import { normalizeTenantId } from '../src/platform-layout.js';
|
|
import { ensureEnvFile, extractEnvValue, writeEnvLine } from './profile.js';
|
|
|
|
export interface SplitBrainSecrets {
|
|
envFile: string;
|
|
tenantId: string;
|
|
subnetBase: string;
|
|
dbHost: string;
|
|
skillsDbUser: string;
|
|
skillsDbName: string;
|
|
memoryDbUser: string;
|
|
memoryDbName: string;
|
|
forgejoDbUser: string;
|
|
forgejoDbName: string;
|
|
opsDbUser: string;
|
|
opsDbName: string;
|
|
postgresAdminPassword: string;
|
|
skillsDbPassword: string;
|
|
memoryDbPassword: string;
|
|
forgejoDbPassword: string;
|
|
opsDbPassword: string;
|
|
strapiDbPassword: string;
|
|
strapiAppKeys: string;
|
|
strapiApiTokenSalt: string;
|
|
strapiAdminJwtSecret: string;
|
|
strapiTransferTokenSalt: string;
|
|
strapiJwtSecret: string;
|
|
skillsDbUrl: string;
|
|
memoryDbUrl: string;
|
|
forgejoDbUrl: string;
|
|
opsDbUrl: string;
|
|
}
|
|
|
|
function generateSecret(bytes = 24): string {
|
|
return randomBytes(bytes).toString('base64url');
|
|
}
|
|
|
|
function generateStrapiAppKeys(): string {
|
|
return Array.from({ length: 4 }, () => generateSecret(24)).join(',');
|
|
}
|
|
|
|
function currentEnvValue(content: string, key: string): string | null {
|
|
const value = extractEnvValue(content, key);
|
|
return value && value.trim() ? value.trim() : null;
|
|
}
|
|
|
|
function buildPostgresUrl(
|
|
user: string,
|
|
password: string,
|
|
host: string,
|
|
database: string,
|
|
): string {
|
|
return `postgresql://${encodeURIComponent(user)}:${encodeURIComponent(password)}@${host}:5432/${encodeURIComponent(database)}`;
|
|
}
|
|
|
|
function writeIfMissing(envFile: string, key: string, value: string): void {
|
|
const content = fs.readFileSync(envFile, 'utf-8');
|
|
if (!currentEnvValue(content, key)) {
|
|
writeEnvLine(envFile, key, value);
|
|
}
|
|
}
|
|
|
|
export function ensureSplitBrainSecrets(
|
|
projectRoot: string,
|
|
): SplitBrainSecrets {
|
|
const envFile = ensureEnvFile(projectRoot);
|
|
let content = fs.readFileSync(envFile, 'utf-8');
|
|
|
|
const rawTenantId = currentEnvValue(content, 'TENANT_ID');
|
|
const tenantId = rawTenantId ? normalizeTenantId(rawTenantId) : '';
|
|
const subnetBase =
|
|
currentEnvValue(content, 'AGENT_SUBNET_BASE') ||
|
|
currentEnvValue(content, 'WARDEN_SUBNET_BASE') ||
|
|
'10.0.1';
|
|
const dbRuntime = (
|
|
process.env.DB_RUNTIME ||
|
|
currentEnvValue(content, 'DB_RUNTIME') ||
|
|
'jail'
|
|
)
|
|
.trim()
|
|
.toLowerCase();
|
|
const dbHost =
|
|
process.env.DB_HOST ||
|
|
currentEnvValue(content, 'DB_HOST') ||
|
|
(dbRuntime === 'host'
|
|
? `${subnetBase}.1`
|
|
: currentEnvValue(content, 'WARDEN_DB_IP') || `${subnetBase}.5`);
|
|
|
|
const skillsUser =
|
|
currentEnvValue(content, 'SKILLS_DB_USER') ||
|
|
(tenantId ? skillsDbUser(tenantId) : sharedSkillsDbUser());
|
|
const skillsName =
|
|
currentEnvValue(content, 'SKILLS_DB_NAME') ||
|
|
(tenantId ? skillsDb(tenantId) : sharedSkillsDb());
|
|
const memoryUser =
|
|
currentEnvValue(content, 'MEMORY_DB_USER') ||
|
|
(tenantId ? brainDbUser(tenantId) : sharedBrainDbUser());
|
|
const memoryName =
|
|
currentEnvValue(content, 'MEMORY_DB_NAME') ||
|
|
(tenantId ? brainDb(tenantId) : sharedBrainDb());
|
|
const forgejoUser =
|
|
currentEnvValue(content, 'FORGEJO_DB_USER') ||
|
|
(tenantId ? forgejoDbUser(tenantId) : sharedGitDbUser());
|
|
const forgejoName =
|
|
currentEnvValue(content, 'FORGEJO_DB_NAME') ||
|
|
(tenantId ? forgejoDb(tenantId) : sharedGitDb());
|
|
const opsUser =
|
|
currentEnvValue(content, 'OPS_DB_USER') ||
|
|
(tenantId ? opsDbUser(tenantId) : sharedOpsDbUser());
|
|
const opsName =
|
|
currentEnvValue(content, 'OPS_DB_NAME') ||
|
|
(tenantId ? opsDb(tenantId) : sharedOpsDb());
|
|
|
|
writeIfMissing(envFile, 'POSTGRES_ADMIN_PASSWORD', generateSecret(24));
|
|
writeIfMissing(envFile, 'SKILLS_DB_PASSWORD', generateSecret(24));
|
|
writeIfMissing(envFile, 'MEMORY_DB_PASSWORD', generateSecret(24));
|
|
writeIfMissing(envFile, 'FORGEJO_DB_PASSWORD', generateSecret(24));
|
|
writeIfMissing(envFile, 'OPS_DB_PASSWORD', generateSecret(24));
|
|
writeIfMissing(envFile, 'STRAPI_DB_PASSWORD', generateSecret(24));
|
|
writeIfMissing(envFile, 'STRAPI_APP_KEYS', generateStrapiAppKeys());
|
|
writeIfMissing(envFile, 'STRAPI_API_TOKEN_SALT', generateSecret(24));
|
|
writeIfMissing(envFile, 'STRAPI_ADMIN_JWT_SECRET', generateSecret(24));
|
|
writeIfMissing(envFile, 'STRAPI_TRANSFER_TOKEN_SALT', generateSecret(24));
|
|
writeIfMissing(envFile, 'STRAPI_JWT_SECRET', generateSecret(24));
|
|
|
|
content = fs.readFileSync(envFile, 'utf-8');
|
|
|
|
const postgresAdminPassword =
|
|
currentEnvValue(content, 'POSTGRES_ADMIN_PASSWORD') || generateSecret(24);
|
|
const skillsDbPassword =
|
|
currentEnvValue(content, 'SKILLS_DB_PASSWORD') || generateSecret(24);
|
|
const memoryDbPassword =
|
|
currentEnvValue(content, 'MEMORY_DB_PASSWORD') || generateSecret(24);
|
|
const forgejoDbPassword =
|
|
currentEnvValue(content, 'FORGEJO_DB_PASSWORD') || generateSecret(24);
|
|
const opsDbPassword =
|
|
currentEnvValue(content, 'OPS_DB_PASSWORD') || generateSecret(24);
|
|
const strapiDbPassword =
|
|
currentEnvValue(content, 'STRAPI_DB_PASSWORD') || generateSecret(24);
|
|
const strapiAppKeys =
|
|
currentEnvValue(content, 'STRAPI_APP_KEYS') || generateStrapiAppKeys();
|
|
const strapiApiTokenSalt =
|
|
currentEnvValue(content, 'STRAPI_API_TOKEN_SALT') || generateSecret(24);
|
|
const strapiAdminJwtSecret =
|
|
currentEnvValue(content, 'STRAPI_ADMIN_JWT_SECRET') || generateSecret(24);
|
|
const strapiTransferTokenSalt =
|
|
currentEnvValue(content, 'STRAPI_TRANSFER_TOKEN_SALT') ||
|
|
generateSecret(24);
|
|
const strapiJwtSecret =
|
|
currentEnvValue(content, 'STRAPI_JWT_SECRET') || generateSecret(24);
|
|
|
|
const skillsDbUrl = buildPostgresUrl(
|
|
skillsUser,
|
|
skillsDbPassword,
|
|
dbHost,
|
|
skillsName,
|
|
);
|
|
const memoryDbUrl = buildPostgresUrl(
|
|
memoryUser,
|
|
memoryDbPassword,
|
|
dbHost,
|
|
memoryName,
|
|
);
|
|
const forgejoDbUrl = buildPostgresUrl(
|
|
forgejoUser,
|
|
forgejoDbPassword,
|
|
dbHost,
|
|
forgejoName,
|
|
);
|
|
const opsDbUrl = buildPostgresUrl(
|
|
opsUser,
|
|
opsDbPassword,
|
|
dbHost,
|
|
opsName,
|
|
);
|
|
|
|
writeEnvLine(envFile, 'SKILLS_DB_URL', skillsDbUrl);
|
|
writeEnvLine(envFile, 'MEMORY_DB_URL', memoryDbUrl);
|
|
writeEnvLine(envFile, 'FORGEJO_DB_URL', forgejoDbUrl);
|
|
writeEnvLine(envFile, 'OPS_DB_URL', opsDbUrl);
|
|
|
|
return {
|
|
envFile,
|
|
tenantId,
|
|
subnetBase,
|
|
dbHost,
|
|
skillsDbUser: skillsUser,
|
|
skillsDbName: skillsName,
|
|
memoryDbUser: memoryUser,
|
|
memoryDbName: memoryName,
|
|
forgejoDbUser: forgejoUser,
|
|
forgejoDbName: forgejoName,
|
|
opsDbUser: opsUser,
|
|
opsDbName: opsName,
|
|
postgresAdminPassword,
|
|
skillsDbPassword,
|
|
memoryDbPassword,
|
|
forgejoDbPassword,
|
|
opsDbPassword,
|
|
strapiDbPassword,
|
|
strapiAppKeys,
|
|
strapiApiTokenSalt,
|
|
strapiAdminJwtSecret,
|
|
strapiTransferTokenSalt,
|
|
strapiJwtSecret,
|
|
skillsDbUrl,
|
|
memoryDbUrl,
|
|
forgejoDbUrl,
|
|
opsDbUrl,
|
|
};
|
|
}
|