commit feff0158e29dd516fff219a32ee6698900e1298d Author: Slawomir Koszewski Date: Sat Oct 17 08:59:44 2026 +0200 Added prototype files. diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c71c48f --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +node_modules/ +*.pem +*.pfx +cred.json +trust_store.yaml +package-lock.json diff --git a/make_certs.sh b/make_certs.sh new file mode 100755 index 0000000..b9d45fa --- /dev/null +++ b/make_certs.sh @@ -0,0 +1,47 @@ +# Root CA certificate +echo "Generating Root CA certificate..." +openssl req \ + -x509 \ + -newkey rsa:4096 \ + -keyout ca_key.pem \ + -out ca_cert.pem \ + -days 3650 \ + -noenc \ + -subj "/CN=Test CA $(date +"%Y-%m-%d")" \ + -addext "basicConstraints=critical,CA:TRUE,pathlen:1" \ + -addext "keyUsage=critical,keyCertSign,cRLSign" + +# Issuing CA certificate +echo +openssl req \ + -newkey rsa:4096 \ + -keyout issuing_ca_key.pem \ + -noenc \ + -subj "/CN=Issuing Test CA $(date +"%Y-%m-%d")" \ + -addext "basicConstraints=critical,CA:TRUE,pathlen:0" \ + -addext "keyUsage=critical,keyCertSign,cRLSign" | + openssl x509 \ + -req \ + -CA ca_cert.pem \ + -CAkey ca_key.pem \ + -copy_extensions copyall \ + -days 3650 \ + -out issuing_ca_cert.pem + +# Client certificate +echo "Generating Client certificate..." +openssl req \ + -newkey rsa:4096 \ + -keyout client_key.pem \ + -noenc \ + -subj "/CN=test-client" \ + -addext "basicConstraints=critical,CA:FALSE" \ + -addext "keyUsage=critical,digitalSignature,keyEncipherment" \ + -addext "extendedKeyUsage=clientAuth" | + openssl x509 \ + -req \ + -CA issuing_ca_cert.pem \ + -CAkey issuing_ca_key.pem \ + -copy_extensions copyall \ + -days 365 \ + -out client_cert.pem diff --git a/make_cred.mjs b/make_cred.mjs new file mode 100755 index 0000000..0600b45 --- /dev/null +++ b/make_cred.mjs @@ -0,0 +1,29 @@ +#!/usr/bin/env node +import { readFileSync, writeFileSync } from "node:fs"; +import { parseArgs } from "node:util"; + +const { values } = parseArgs({ + options: { + "private-key-file": { type: "string" }, + "client-email": { type: "string" }, + output: { type: "string", default: "cred.json" }, + }, +}); + +if (!values["private-key-file"] || !values["client-email"]) { + console.error("Usage: make_cred.mjs --private-key-file FILE --client-email EMAIL [--output FILE]"); + process.exit(1); +} + +const privateKey = readFileSync(values["private-key-file"], "utf8"); +const clientEmail = values["client-email"]; + +const cred = { + type: "service_account", + project_id: clientEmail.split("@")[1].split(".")[0], + private_key: privateKey, + client_email: clientEmail, + token_uri: "https://oauth2.googleapis.com/token", +}; + +writeFileSync(values.output, JSON.stringify(cred, null, 2) + "\n"); diff --git a/make_trust_store.mjs b/make_trust_store.mjs new file mode 100755 index 0000000..3dc27d2 --- /dev/null +++ b/make_trust_store.mjs @@ -0,0 +1,27 @@ +#!/usr/bin/env node +import { existsSync, readFileSync, writeFileSync } from "node:fs"; +import { parseArgs } from "node:util"; +import YAML from "yaml"; + +const { values } = parseArgs({ + options: { + "ca-cert": { type: "string", default: "ca_cert.pem" }, + "issuing-ca-cert": { type: "string", default: "issuing_ca_cert.pem" }, + output: { type: "string", default: "trust_store.yaml" }, + }, +}); + +// IMPORTANT: Strip the trailing newline from the PEM files, +// otherwise gcloud will reject the trust store with a cryptic error message. +const trustStore = { + trustAnchors: [{ pemCertificate: readFileSync(values["ca-cert"], "utf8").trimEnd() }], +}; + +// The issuing CA is optional; it is included only when its file exists. +if (existsSync(values["issuing-ca-cert"])) { + trustStore.intermediateCas = [ + { pemCertificate: readFileSync(values["issuing-ca-cert"], "utf8").trimEnd() }, + ]; +} + +writeFileSync(values.output, YAML.stringify({ trustStore }, { indentSeq: false })); diff --git a/make_wif.sh b/make_wif.sh new file mode 100755 index 0000000..b4e6cb1 --- /dev/null +++ b/make_wif.sh @@ -0,0 +1,32 @@ +# Create a workload identity pool and a X.509 provider +gcloud iam workload-identity-pools create dom-lab-pool \ + --project=dom-lab \ + --location=global \ + --display-name="Dom Lab Pool" + +# Create X.509 provider +gcloud iam workload-identity-pools providers create-x509 dom-lab-x509 \ + --project=dom-lab \ + --location=global \ + --workload-identity-pool=dom-lab-pool \ + --trust-store-config-path=trust_store.yaml \ + --attribute-mapping="google.subject=assertion.subject.dn.cn" + +# Create the service account +gcloud iam service-accounts create sa-test \ + --project=dom-lab \ + --display-name="SA Test" + +# Allow impersonation of the service account +gcloud iam service-accounts add-iam-policy-binding \ + sa-test@dom-lab.iam.gserviceaccount.com \ + --role=roles/iam.workloadIdentityUser \ + --member="principal://iam.googleapis.com/projects/267098479356/locations/global/workloadIdentityPools/dom-lab-pool/subject/test-client" + +# Create credentials configuration files +gcloud iam workload-identity-pools create-cred-config \ + projects/267098479356/locations/global/workloadIdentityPools/dom-lab-pool/providers/dom-lab-x509 \ + --service-account=sa-test@dom-lab.iam.gserviceaccount.com \ + --credential-cert-path=client_cert.pem \ + --credential-cert-private-key-path=client_key.pem \ + --output-file=cred.json diff --git a/package.json b/package.json new file mode 100644 index 0000000..65ba123 --- /dev/null +++ b/package.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "yaml": ">=2.9.1" + } +}