Compare commits

..

3 Commits

5 changed files with 93 additions and 27 deletions
@@ -6,12 +6,8 @@ export const generateSecureValue = (content: string) => {
// Generate a hash of the content
const hash = Password.hash(content);
// Parse the PKCS#1 PEM key into a proper KeyObject
const publicKey = crypto.createPublicKey({
key: secureValuesPublicKey,
format: "pem",
type: "pkcs1",
});
// Parse the PEM key into a proper KeyObject
const publicKey = crypto.createPublicKey(secureValuesPublicKey);
// Encrypt the content using the .secureValues.pub public key
const encrypted = crypto.publicEncrypt(
+1 -5
View File
@@ -3,11 +3,7 @@ import crypto from "crypto";
import { secureValuesPrivateKey } from "../../constants";
import GenericError from "../../Errors/GenericError";
const privateKey = crypto.createPrivateKey({
key: secureValuesPrivateKey,
format: "pem",
type: "pkcs1",
});
const privateKey = crypto.createPrivateKey(secureValuesPrivateKey);
export const readSecureValue = (
encryptedContent: string,
+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`;