switch to PKCS#8 key format for Bun compatibility

This commit is contained in:
2026-02-25 22:14:19 -06:00
parent 05bab2c90f
commit 49faf97c9b
4 changed files with 105 additions and 57 deletions
+65
View File
@@ -0,0 +1,65 @@
import { execSync } from "child_process";
const kubeconfig = "/Users/jroberts/projects/K8S-QuickDeploy/k8s.yaml";
function getKey(name: string): string {
const b64 = execSync(
`KUBECONFIG=${kubeconfig} kubectl get secret optima-keys-secret -n optima -o jsonpath="{.data.${name}}"`,
)
.toString()
.trim();
return Buffer.from(b64, "base64").toString("utf-8");
}
const privKeys = [
"ACCESS_TOKEN_PRIVATE_KEY",
"REFRESH_TOKEN_PRIVATE_KEY",
"PERMISSIONS_PRIVATE_KEY",
"SECURE_VALUES_PRIVATE_KEY",
];
const converted: Record<string, string> = {};
// Use openssl CLI to convert PKCS#1 to PKCS#8 (Bun's crypto has issues with some keys)
for (const k of privKeys) {
const pem = getKey(k);
const pkcs8 = execSync("openssl pkey -in /dev/stdin", {
input: pem,
}).toString();
converted[k] = pkcs8;
console.log(`${k}: converted to PKCS#8 ✅`);
}
const pubPem = getKey("SECURE_VALUES_PUBLIC_KEY");
const spki = execSync("openssl rsa -RSAPublicKey_in -pubout -in /dev/stdin", {
input: pubPem,
}).toString();
converted["SECURE_VALUES_PUBLIC_KEY"] = spki;
console.log("SECURE_VALUES_PUBLIC_KEY: converted to SPKI ✅");
// Generate kubectl command to recreate the secret with PKCS#8 keys
const args = Object.entries(converted)
.map(([k, v]) => `--from-literal=${k}='${v}'`)
.join(" \\\n ");
console.log("\n--- Delete and recreate secret with PKCS#8 keys ---\n");
console.log(
`KUBECONFIG=${kubeconfig} kubectl delete secret optima-keys-secret -n optima`,
);
console.log(
`KUBECONFIG=${kubeconfig} kubectl create secret generic optima-keys-secret -n optima \\\n ${args}`,
);
// Actually do it
console.log("\nApplying...");
execSync(
`KUBECONFIG=${kubeconfig} kubectl delete secret optima-keys-secret -n optima`,
);
const literals = Object.entries(converted).map(
([k, v]) => `--from-literal=${k}=${v}`,
);
const cmd = `KUBECONFIG=${kubeconfig} kubectl create secret generic optima-keys-secret -n optima ${literals.join(" ")}`;
execSync(cmd);
console.log("Secret recreated with PKCS#8 keys ✅");
+9 -5
View File
@@ -1,9 +1,9 @@
import keypair from "keypair";
import crypto from "crypto";
console.log(`
Generating Private Keys
-----------------
This script will go through and genrate all the keys necessary for running the Credential Manager API locally.
This script will go through and generate all the keys necessary for running the Credential Manager API locally.
This process might take several minutes.
-----------------`);
@@ -42,9 +42,13 @@ await Promise.all(
if (!privExists || !pubExists) {
// Always regenerate both files together to ensure the key pair matches
console.log(`Generating '${v}' and '${pubPath}'...`);
const keys = keypair({ bits: 4096 });
await Bun.write(v, keys.private);
await Bun.write(pubPath, keys.public);
const { privateKey, publicKey } = crypto.generateKeyPairSync("rsa", {
modulusLength: 4096,
privateKeyEncoding: { type: "pkcs8", format: "pem" },
publicKeyEncoding: { type: "spki", format: "pem" },
});
await Bun.write(v, privateKey);
await Bun.write(pubPath, publicKey);
}
return;
}),
+16 -11
View File
@@ -1,4 +1,4 @@
import keypair from "keypair";
import crypto from "crypto";
import { mkdirSync } from "fs";
const outputDir = "production-keys";
@@ -19,14 +19,18 @@ const generatedKeys: Record<string, { private: string; public: string }> = {};
for (const name of keyFiles) {
console.log(`Generating '${name}' key pair (4096-bit RSA)...`);
const keys = keypair({ bits: 4096 });
generatedKeys[name] = keys;
const { privateKey, publicKey } = crypto.generateKeyPairSync("rsa", {
modulusLength: 4096,
privateKeyEncoding: { type: "pkcs8", format: "pem" },
publicKeyEncoding: { type: "spki", format: "pem" },
});
generatedKeys[name] = { private: privateKey, public: publicKey };
const privPath = `${outputDir}/${name}.key`;
const pubPath = `${outputDir}/${name}.pub`;
await Bun.write(privPath, keys.private);
await Bun.write(pubPath, keys.public);
await Bun.write(privPath, privateKey);
await Bun.write(pubPath, publicKey);
console.log(`${privPath}`);
console.log(`${pubPath}`);
@@ -38,14 +42,15 @@ const toBase64 = (str: string) => Buffer.from(str).toString("base64");
const secretYaml = `apiVersion: v1
kind: Secret
metadata:
name: optima-keys
name: optima-keys-secret
namespace: optima
type: Opaque
data:
accessToken.key: ${toBase64(generatedKeys["accessToken"].private)}
refreshToken.key: ${toBase64(generatedKeys["refreshToken"].private)}
permissions.key: ${toBase64(generatedKeys["permissions"].private)}
secureValues.key: ${toBase64(generatedKeys["secureValues"].private)}
secureValues.pub: ${toBase64(generatedKeys["secureValues"].public)}
ACCESS_TOKEN_PRIVATE_KEY: ${toBase64(generatedKeys["accessToken"].private)}
REFRESH_TOKEN_PRIVATE_KEY: ${toBase64(generatedKeys["refreshToken"].private)}
PERMISSIONS_PRIVATE_KEY: ${toBase64(generatedKeys["permissions"].private)}
SECURE_VALUES_PRIVATE_KEY: ${toBase64(generatedKeys["secureValues"].private)}
SECURE_VALUES_PUBLIC_KEY: ${toBase64(generatedKeys["secureValues"].public)}
`;
const secretPath = `${outputDir}/optima-keys-secret.yaml`;