ORCH-058: implement fail-closed provenance guard in deploy-hook + GIT_SHA OCI label in Dockerfile
All checks were successful
CI / test (push) Successful in 16s
All checks were successful
CI / test (push) Successful in 16s
- deploy-hook: REVISION_LABEL/EXPECTED_REVISION (default unset -> backward-compat) - deploy-hook: fail-closed guard inspects SOURCE_IMAGE revision label before docker tag, normalises <no value>, exit 1 on empty/mismatch - deploy-hook: new --build-staging mode rebuilds staging image stamping GIT_SHA - Dockerfile: ARG GIT_SHA + LABEL org.opencontainers.image.revision=$GIT_SHA Closes TC07/TC08 (tests/test_deploy_hook_provenance.py).
This commit is contained in:
@@ -1,5 +1,9 @@
|
||||
FROM python:3.12-slim
|
||||
WORKDIR /app
|
||||
# ORCH-58: stamp the validated git commit into the OCI revision label so the
|
||||
# deploy hook provenance guard can fail-closed on it before the prod retag.
|
||||
ARG GIT_SHA
|
||||
LABEL org.opencontainers.image.revision=$GIT_SHA
|
||||
RUN apt-get update -qq && apt-get install -y -qq openssh-client git && rm -rf /var/lib/apt/lists/*
|
||||
# git operations run as root over bind-mounted /repos (may be owned by host uid) -> trust it.
|
||||
RUN git config --system --add safe.directory '*'
|
||||
|
||||
@@ -32,6 +32,11 @@ PREV_IMAGE_FILE="${PREV_IMAGE_FILE:-$REPO/.deploy-prev-image-staging}"
|
||||
# Build-once (ORCH-36): optional prevalidated source image to retag onto
|
||||
# TARGET_IMAGE. Unset -> backward-compatible (no retag), exit-code contract intact.
|
||||
SOURCE_IMAGE="${SOURCE_IMAGE:-}"
|
||||
# Provenance guard (ORCH-58 Strategy-B): the OCI revision label the hook
|
||||
# inspects on SOURCE_IMAGE, and the git revision it MUST match before retag
|
||||
# onto prod. EXPECTED_REVISION unset -> backward-compatible (guard skipped).
|
||||
REVISION_LABEL="org.opencontainers.image.revision"
|
||||
EXPECTED_REVISION="${EXPECTED_REVISION:-}"
|
||||
|
||||
# ---- Log setup -------------------------------------------------------------
|
||||
LOG_DIR=/var/log/orchestrator
|
||||
@@ -118,6 +123,17 @@ do_rollback() {
|
||||
# ============================================================================
|
||||
# MANUAL --rollback mode
|
||||
# ============================================================================
|
||||
if [[ "${1:-}" == "--build-staging" ]]; then
|
||||
# Strategy-A rebuild mode (ORCH-58): rebuild the staging image stamping
|
||||
# the validated commit SHA into the OCI revision label so the provenance
|
||||
# guard above can fail-closed on it during the subsequent prod retag.
|
||||
GIT_SHA=$(git rev-parse HEAD)
|
||||
log "BUILD-STAGING: rebuilding $TARGET_IMAGE stamping GIT_SHA=$GIT_SHA"
|
||||
docker build --build-arg GIT_SHA="$GIT_SHA" -t "$TARGET_IMAGE" "$REPO" >> "$LOG" 2>&1
|
||||
log "BUILD-STAGING: built $TARGET_IMAGE (revision=$GIT_SHA)"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ "${1:-}" == "--rollback" ]]; then
|
||||
log "Manual ROLLBACK requested"
|
||||
if do_rollback; then
|
||||
@@ -156,6 +172,22 @@ git pull origin main >> "$LOG" 2>&1
|
||||
# Backward compatible: skipped when SOURCE_IMAGE is unset.
|
||||
if [[ -n "$SOURCE_IMAGE" ]]; then
|
||||
if docker image inspect "$SOURCE_IMAGE" >/dev/null 2>&1; then
|
||||
# Fail-closed provenance guard: when EXPECTED_REVISION is set, the
|
||||
# source image MUST carry the matching git-revision OCI label, else
|
||||
# abort BEFORE the prod retag. Empty EXPECTED_REVISION -> guard
|
||||
# skipped (ORCH-36 backward-compat).
|
||||
if [[ -n "$EXPECTED_REVISION" ]]; then
|
||||
IMG_REV=$(docker image inspect --format '{{ index .Config.Labels "'"$REVISION_LABEL"'" }}' "$SOURCE_IMAGE" 2>/dev/null || true)
|
||||
# docker emits "<no value>" when the label is absent -> normalise.
|
||||
if [[ "$IMG_REV" == "<no value>" ]]; then
|
||||
IMG_REV=""
|
||||
fi
|
||||
if [[ -z "$IMG_REV" || "$IMG_REV" != "$EXPECTED_REVISION" ]]; then
|
||||
log "PROVENANCE: SOURCE_IMAGE revision '$IMG_REV' != expected '$EXPECTED_REVISION' - aborting before retag (exit 1)"
|
||||
exit 1
|
||||
fi
|
||||
log "PROVENANCE: SOURCE_IMAGE revision matches expected ($EXPECTED_REVISION)"
|
||||
fi
|
||||
log "BUILD-ONCE: retagging $SOURCE_IMAGE -> $TARGET_IMAGE (no rebuild)"
|
||||
docker tag "$SOURCE_IMAGE" "$TARGET_IMAGE" >> "$LOG" 2>&1
|
||||
else
|
||||
|
||||
Reference in New Issue
Block a user