/** * Step 01 — Generate a named SSH key pair * * Generates an ed25519 key pair and stores it in the secrets directory: * * /git-ssh//public/ * /git-ssh//private/ * * The private key is written with mode 0600. * The public key can be registered as a read-only deploy key in Gitea. */ import { execFile as exec_file } from 'node:child_process' import { mkdirSync, mkdtempSync, chmodSync, existsSync, readFileSync, renameSync, rmSync } from 'node:fs' import * as path from 'node:path' import * as os from 'node:os' import { promisify } from 'node:util' import { fileURLToPath } from 'node:url' import yaml from 'js-yaml' const exec = promisify(exec_file) const HERE = path.dirname(fileURLToPath(import.meta.url)) const CONFIG = yaml.load(readFileSync(path.join(HERE, '..', 'config.yml'), 'utf8')) async function run(cmd, args = []) { console.log(`$ ${cmd} ${args.join(' ')}`) const { stdout, stderr } = await exec(cmd, args) if (stdout) { process.stdout.write(stdout) } if (stderr) { process.stderr.write(stderr) } return stdout.trim() } async function main() { const { secrets_base, user, key_name } = CONFIG const public_dir = path.join(secrets_base, 'git-ssh', user, 'public') const private_dir = path.join(secrets_base, 'git-ssh', user, 'private') const public_path = path.join(public_dir, key_name) const private_path = path.join(private_dir, key_name) if (existsSync(private_path) || existsSync(public_path)) { console.error(`Key "${key_name}" already exists for user "${user}". Aborting.`) process.exit(1) } mkdirSync(public_dir, { recursive: true }) mkdirSync(private_dir, { recursive: true, mode: 0o700 }) // Generate into a secure temp directory, then move into place const tmp_dir = mkdtempSync(path.join(os.tmpdir(), 'ci-keygen-')) const tmp_path = path.join(tmp_dir, 'key') try { await run('ssh-keygen', [ '-t', 'ed25519', '-N', '', // no passphrase '-C', `ci/${user}/${key_name}`, '-f', tmp_path, ]) renameSync(`${tmp_path}.pub`, public_path) renameSync(tmp_path, private_path) chmodSync(private_path, 0o600) } finally { rmSync(tmp_dir, { recursive: true, force: true }) } console.log(`\nKey "${key_name}" generated for user "${user}".`) console.log(`\nPublic key (add as read-only deploy key in Gitea):\n`) console.log(readFileSync(public_path, 'utf8')) } main().catch(err => { console.error(err) process.exit(1) })