#!/bin/sh # infra/step-ca/init.sh # # Idempotent first-boot initialiser for the Mosaic Federation CA. # # On the first run (no /home/step/config/ca.json present) this script: # 1. Initialises Step-CA with a JWK provisioner named "mosaic-fed". # 2. Writes the CA configuration to the persistent volume at /home/step. # 3. Copies the federation X.509 template into the CA config directory. # 4. Patches the mosaic-fed provisioner entry in ca.json to reference the # template via options.x509.templateFile (using jq — must be installed # in the container image). # # On subsequent runs (config already exists) this script skips init and # starts the CA directly. # # The provisioner name "mosaic-fed" is consumed by: # apps/gateway/src/federation/ca.service.ts (added in M2-04) # # Password source: # Dev: mounted from ./infra/step-ca/dev-password via bind mount. # Prod: mounted from a Docker secret at /run/secrets/ca_password. # # OID template: # infra/step-ca/templates/federation.tpl emits custom OID extensions: # 1.3.6.1.4.1.99999.1 — mosaic_grant_id # 1.3.6.1.4.1.99999.2 — mosaic_subject_user_id set -e CA_CONFIG="/home/step/config/ca.json" PASSWORD_FILE="/run/secrets/ca_password" TEMPLATE_SRC="/etc/step-ca-templates/federation.tpl" TEMPLATE_DEST="/home/step/templates/federation.tpl" if [ ! -f "${CA_CONFIG}" ]; then echo "[step-ca init] First boot detected — initialising Mosaic Federation CA..." step ca init \ --name "Mosaic Federation CA" \ --dns "localhost" \ --dns "step-ca" \ --address ":9000" \ --provisioner "mosaic-fed" \ --password-file "${PASSWORD_FILE}" \ --provisioner-password-file "${PASSWORD_FILE}" \ --no-db echo "[step-ca init] CA initialised." # Copy the X.509 template into the Step-CA config directory. if [ -f "${TEMPLATE_SRC}" ]; then mkdir -p /home/step/templates cp "${TEMPLATE_SRC}" "${TEMPLATE_DEST}" echo "[step-ca init] Federation X.509 template copied to ${TEMPLATE_DEST}." else echo "[step-ca init] WARNING: Template source ${TEMPLATE_SRC} not found — skipping copy." fi # Wire the template into the mosaic-fed provisioner via jq. # This is idempotent: the block only runs once (first boot). # # jq filter: find the provisioner entry with name "mosaic-fed" and set # .options.x509.templateFile to the absolute path of the template. # All other provisioners and config keys are left unchanged. if [ -f "${TEMPLATE_DEST}" ] && command -v jq > /dev/null 2>&1; then echo "[step-ca init] Patching mosaic-fed provisioner with X.509 template..." TEMP_CONFIG="${CA_CONFIG}.tmp" jq --arg tpl "${TEMPLATE_DEST}" ' .authority.provisioners |= map( if .name == "mosaic-fed" then .options.x509.templateFile = $tpl else . end ) ' "${CA_CONFIG}" > "${TEMP_CONFIG}" && mv "${TEMP_CONFIG}" "${CA_CONFIG}" echo "[step-ca init] Provisioner patched." elif ! command -v jq > /dev/null 2>&1; then echo "[step-ca init] WARNING: jq not found — skipping provisioner template patch." echo "[step-ca init] Install jq in the step-ca image to enable automatic template wiring." fi echo "[step-ca init] Startup complete." else echo "[step-ca init] Config already exists — skipping init." fi echo "[step-ca init] Starting Step-CA on :9000..." exec step-ca /home/step/config/ca.json --password-file "${PASSWORD_FILE}"