mirror of
https://github.com/shankar0123/certctl.git
synced 2026-06-07 12:21:31 +00:00
fix(deploy): wire CERTCTL_DEMO_MODE_ACK_TS into the demo overlay path
Phase 2 SEC-H3 (commit 69a2b5c) added a fail-closed requirement: when
CERTCTL_DEMO_MODE_ACK=true, the server refuses to start unless
CERTCTL_DEMO_MODE_ACK_TS=<unix-epoch> is set and within the last 24h.
The demo overlay (docker-compose.demo.yml) sets DEMO_MODE_ACK=true
but didn't supply the paired TS, so:
Failed to load configuration: phase-2 SEC-H3 fail-closed guard
(missing TS): CERTCTL_DEMO_MODE_ACK=true requires
CERTCTL_DEMO_MODE_ACK_TS=<unix-epoch> set within the last 24h —
refuse to start.
This bricks the cold-DB compose smoke job, the README quickstart
(`docker compose -f .yml -f demo.yml up`), and every operator using
the demo overlay locally — symptom: certctl-server container restart
loop with the SEC-H3 message above.
Fix is three-piece:
1. deploy/docker-compose.demo.yml passes the TS through from the
shell env via `CERTCTL_DEMO_MODE_ACK_TS: "${CERTCTL_DEMO_MODE_ACK_TS:-}"`.
The overlay can't hardcode the value (it would rot the next day)
and SEC-H3 is designed to refresh on every up.
2. deploy/demo-up.sh — new helper that mints
`CERTCTL_DEMO_MODE_ACK_TS=$(date +%s)` and forwards args to
`docker compose up`. The SEC-H3 error message points operators
at it. Replaces the bare `docker compose -f ... up` invocation
in the overlay's docstring + README quickstart references.
3. .github/workflows/ci.yml cold-db-compose-smoke job exports a fresh
TS before the initial up-d AND re-emits it into /tmp/_smoke.env so
the force-recreate at step 4 inherits the value (--env-file replaces
the shell-env source for compose-file interpolation, so omitting the
re-emission would re-trip the guard).
Other CI compose surfaces verified clean:
- docker-compose.test.yml uses auth=api-key (not demo-mode); not
affected.
- security-deep-scan.yml uses the base compose without the demo
overlay; not affected.
Verified locally: YAML parses, bash syntax check passes on demo-up.sh,
overlay's docstring + the SEC-H3 error message now agree on the helper
script's existence.
This commit is contained in:
@@ -346,6 +346,16 @@ jobs:
|
||||
# demo-mode or api-key, so the overlay is acceptable here.
|
||||
COMPOSE_FILES=(-f docker-compose.yml -f docker-compose.demo.yml)
|
||||
|
||||
# Phase 2 SEC-H3 (2026-05-13): the demo overlay sets
|
||||
# CERTCTL_DEMO_MODE_ACK=true; the SEC-H3 fail-closed guard
|
||||
# requires a paired CERTCTL_DEMO_MODE_ACK_TS within the last
|
||||
# 24h (a static YAML value would rot). The overlay reads
|
||||
# ${CERTCTL_DEMO_MODE_ACK_TS:-} from the shell, so we mint a
|
||||
# fresh timestamp here and export it for every compose
|
||||
# invocation in this job (initial up-d AND the force-recreate
|
||||
# at step 4).
|
||||
export CERTCTL_DEMO_MODE_ACK_TS="$(date +%s)"
|
||||
|
||||
log "1/4 down -v --remove-orphans"
|
||||
docker compose "${COMPOSE_FILES[@]}" down -v --remove-orphans 2>&1 | tail -3 || true
|
||||
|
||||
@@ -359,7 +369,15 @@ jobs:
|
||||
|
||||
log "4/4 minting day-0 admin (proves migration ladder + bootstrap path)"
|
||||
TOKEN="$(openssl rand -base64 32 | tr -d '\n')"
|
||||
echo "CERTCTL_BOOTSTRAP_TOKEN=$TOKEN" > /tmp/_smoke.env
|
||||
{
|
||||
echo "CERTCTL_BOOTSTRAP_TOKEN=$TOKEN"
|
||||
# Re-emit the demo-mode ACK TS into the --env-file so the
|
||||
# force-recreate at step 4 inherits it. `--env-file` REPLACES
|
||||
# the shell-env source for variable interpolation on compose
|
||||
# operations that use it, so omitting this line would re-trip
|
||||
# the SEC-H3 guard.
|
||||
echo "CERTCTL_DEMO_MODE_ACK_TS=$CERTCTL_DEMO_MODE_ACK_TS"
|
||||
} > /tmp/_smoke.env
|
||||
docker compose "${COMPOSE_FILES[@]}" --env-file /tmp/_smoke.env up -d --force-recreate certctl-server 2>&1 | tail -2
|
||||
sleep 5
|
||||
wait_for_service_healthy certctl-server
|
||||
|
||||
Executable
+38
@@ -0,0 +1,38 @@
|
||||
#!/usr/bin/env bash
|
||||
# deploy/demo-up.sh — boot the certctl demo stack with the fresh
|
||||
# CERTCTL_DEMO_MODE_ACK_TS the Phase 2 SEC-H3 guard requires.
|
||||
#
|
||||
# The demo overlay sets CERTCTL_DEMO_MODE_ACK=true. Phase 2 SEC-H3
|
||||
# (2026-05-13) pairs that with a fail-closed requirement: the server
|
||||
# refuses to start unless CERTCTL_DEMO_MODE_ACK_TS=<unix-epoch> is set
|
||||
# and is within the last 24h (with 1-minute future clock-skew tolerance).
|
||||
#
|
||||
# A static value in docker-compose.demo.yml would rot the next day, so
|
||||
# the overlay passthroughs the value from the shell environment. This
|
||||
# helper mints a fresh TS at run time and forwards any extra args to
|
||||
# `docker compose up`, so operators can use it as a drop-in replacement
|
||||
# for the bare command. Example:
|
||||
#
|
||||
# ./demo-up.sh -d # cold boot in detached mode
|
||||
# ./demo-up.sh -d --pull always # forward any flags through
|
||||
#
|
||||
# The cold-DB compose smoke in .github/workflows/ci.yml does the same
|
||||
# thing inline; this script exists so local operators don't have to
|
||||
# remember the export.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# cd to the deploy/ dir so the relative `-f` paths resolve regardless
|
||||
# of where the operator invokes this from. The script lives next to
|
||||
# the compose files it references.
|
||||
cd "$(dirname "$0")"
|
||||
|
||||
export CERTCTL_DEMO_MODE_ACK_TS="$(date +%s)"
|
||||
|
||||
echo "[demo-up] minting CERTCTL_DEMO_MODE_ACK_TS=$CERTCTL_DEMO_MODE_ACK_TS"
|
||||
echo "[demo-up] running: docker compose -f docker-compose.yml -f docker-compose.demo.yml up $*"
|
||||
|
||||
exec docker compose \
|
||||
-f docker-compose.yml \
|
||||
-f docker-compose.demo.yml \
|
||||
up "$@"
|
||||
@@ -5,8 +5,15 @@
|
||||
# Layered on top of the production-shaped base (docker-compose.yml) to give
|
||||
# operators a one-command, zero-config demo path:
|
||||
#
|
||||
# docker compose -f deploy/docker-compose.yml \
|
||||
# -f deploy/docker-compose.demo.yml up -d --build
|
||||
# deploy/demo-up.sh -d --build
|
||||
#
|
||||
# (which forwards args to `docker compose up` after exporting the fresh
|
||||
# CERTCTL_DEMO_MODE_ACK_TS that Phase 2 SEC-H3 requires). Equivalent
|
||||
# manual invocation:
|
||||
#
|
||||
# CERTCTL_DEMO_MODE_ACK_TS=$(date +%s) docker compose \
|
||||
# -f deploy/docker-compose.yml \
|
||||
# -f deploy/docker-compose.demo.yml up -d --build
|
||||
#
|
||||
# What this overlay does:
|
||||
#
|
||||
@@ -14,6 +21,10 @@
|
||||
# request is served as the synthetic admin actor `actor-demo-anon`;
|
||||
# the server emits a prominent ⚠ DEMO MODE WARN banner at boot with
|
||||
# a production-promotion checklist (cmd/server/main.go::emitDemoBanner).
|
||||
# Phase 2 SEC-H3 (2026-05-13) pairs DEMO_MODE_ACK with a required
|
||||
# DEMO_MODE_ACK_TS within the last 24h. The overlay reads
|
||||
# ${CERTCTL_DEMO_MODE_ACK_TS:-} from the shell — use deploy/demo-up.sh
|
||||
# (which exports a fresh TS) instead of bare `docker compose up`.
|
||||
#
|
||||
# 2. Flips CERTCTL_KEYGEN_MODE=server (the demo issues + holds the key on
|
||||
# the server to keep the dashboard populated; production deploys must
|
||||
@@ -48,8 +59,7 @@
|
||||
# To start fresh (wipe previous data):
|
||||
# docker compose -f deploy/docker-compose.yml \
|
||||
# -f deploy/docker-compose.demo.yml down -v
|
||||
# docker compose -f deploy/docker-compose.yml \
|
||||
# -f deploy/docker-compose.demo.yml up -d --build
|
||||
# deploy/demo-up.sh -d --build
|
||||
|
||||
services:
|
||||
postgres:
|
||||
@@ -67,6 +77,17 @@ services:
|
||||
# reminds the operator on every start.
|
||||
CERTCTL_AUTH_TYPE: none
|
||||
CERTCTL_DEMO_MODE_ACK: "true"
|
||||
# Phase 2 SEC-H3 (2026-05-13): DEMO_MODE_ACK=true requires a fresh
|
||||
# DEMO_MODE_ACK_TS within the last 24h. The overlay can't hardcode
|
||||
# a timestamp (it would rot the next day), so we passthrough from
|
||||
# the shell. Operators set this via:
|
||||
# CERTCTL_DEMO_MODE_ACK_TS=$(date +%s) docker compose \
|
||||
# -f docker-compose.yml -f docker-compose.demo.yml up -d
|
||||
# The cold-DB smoke + any helper script (deploy/demo-up.sh, when
|
||||
# it lands) export this before invoking compose. Empty value
|
||||
# fails the SEC-H3 guard with a clear operator-facing error
|
||||
# message pointing at this line.
|
||||
CERTCTL_DEMO_MODE_ACK_TS: "${CERTCTL_DEMO_MODE_ACK_TS:-}"
|
||||
# Server-side keygen so the demo can populate the dashboard with
|
||||
# full lifecycle history. Production deploys leave this at the
|
||||
# code default `agent` (CertctlAgent generates ECDSA P-256 keys
|
||||
|
||||
Reference in New Issue
Block a user