ci(secrets->kms): migrate CP_ADMIN_API_TOKEN to Infisical KMS (wave-3 molecule-ai/molecule-core) #3274

Merged
agent-reviewer-cr2 merged 3 commits from ci/migrate-cp-admin-api-token-infisical into main 2026-06-25 22:06:46 +00:00
7 changed files with 339 additions and 13 deletions
@@ -772,7 +772,10 @@ jobs:
timeout-minutes: 90
env:
CP_URL: ${{ vars.PROD_CP_URL || 'https://api.moleculesai.app' }}
CP_ADMIN_API_TOKEN: ${{ secrets.CP_ADMIN_API_TOKEN }}
# CP_ADMIN_API_TOKEN now arrives via $GITHUB_ENV from the "Fetch
# CP_ADMIN_API_TOKEN from Infisical KMS" step below (wave-3 migration);
# it is the Infisical SSOT value. The "Build deploy plan" step still
# validates it is non-empty before any production rollout.
GITEA_HOST: git.moleculesai.app
GITEA_TOKEN: ${{ secrets.PROD_AUTO_DEPLOY_CONTROL_TOKEN || secrets.AUTO_SYNC_TOKEN }}
CI_STATUS_TIMEOUT_SECONDS: "3600"
@@ -804,6 +807,50 @@ jobs:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
# KMS wave-3 (Gitea-Actions-secrets -> Infisical SSOT): source
# CP_ADMIN_API_TOKEN from Infisical (prod /shared/controlplane-admin) via
# the CI machine identity instead of the duplicated Gitea Actions secret,
# mirroring this repo's boot-to-registration-e2e KMS pattern. Exported to
# $GITHUB_ENV so the plan + redeploy steps read it as a masked env var.
#
# TRUSTED-REF GATING: molecule-core is a PUBLIC repo; this step consumes
# the INFISICAL_CI_* machine-identity secrets, so it must only run on a
# TRUSTED event — a push to the protected main branch or an operator
# workflow_dispatch. This workflow has no pull_request trigger, so an
# untrusted-fork PR cannot reach it.
- name: Fetch CP_ADMIN_API_TOKEN from Infisical KMS
id: cp_admin_token
if: >-
github.event_name == 'workflow_dispatch' ||
(github.event_name == 'push' && github.ref == 'refs/heads/main')
env:
INFISICAL_CI_CLIENT_ID: ${{ secrets.INFISICAL_CI_CLIENT_ID }}
INFISICAL_CI_CLIENT_SECRET: ${{ secrets.INFISICAL_CI_CLIENT_SECRET }}
INFISICAL_PROJECT_ID: ${{ secrets.INFISICAL_CI_PROJECT_ID }}
run: |
set -uo pipefail
BASE="https://key.moleculesai.app"
TOK=$(curl -fsS -X POST "$BASE/api/v1/auth/universal-auth/login" \
-H 'Content-Type: application/json' \
-d "{\"clientId\":\"$INFISICAL_CI_CLIENT_ID\",\"clientSecret\":\"$INFISICAL_CI_CLIENT_SECRET\"}" \
| python3 -c 'import sys,json;print(json.load(sys.stdin)["accessToken"])')
read_secret() {
curl -fsS "$BASE/api/v3/secrets/raw/$1?workspaceId=$INFISICAL_PROJECT_ID&environment=prod&secretPath=$2" \
-H "Authorization: Bearer $TOK" \
| python3 -c 'import sys,json; v=json.load(sys.stdin).get("secret",{}).get("secretValue"); sys.stdout.write(v if isinstance(v,str) else "")'
}
CP_ADMIN_API_TOKEN=$(read_secret CP_ADMIN_API_TOKEN %2Fshared%2Fcontrolplane-admin)
echo "::add-mask::$CP_ADMIN_API_TOKEN"
# Masking-control: production auto-deploy is side-effecting. Assert
# NON-EMPTY and FAIL LOUD — never roll the prod fleet with an empty
# admin token.
if [ -z "$CP_ADMIN_API_TOKEN" ]; then
echo "::error::Infisical returned empty CP_ADMIN_API_TOKEN at prod /shared/controlplane-admin — failing closed."
exit 1
fi
echo "CP_ADMIN_API_TOKEN=$CP_ADMIN_API_TOKEN" >> "$GITHUB_ENV"
echo "CP_ADMIN_API_TOKEN loaded from Infisical (len=${#CP_ADMIN_API_TOKEN})"
- name: Build deploy plan
id: plan
run: |
+48 -5
View File
@@ -88,6 +88,50 @@ jobs:
# integrated auto-deploy workflow.
PROD_AUTO_DEPLOY_DISABLED: ${{ vars.PROD_AUTO_DEPLOY_DISABLED || secrets.PROD_AUTO_DEPLOY_DISABLED || '' }}
steps:
# KMS wave-3 (Gitea-Actions-secrets -> Infisical SSOT): source
# CP_ADMIN_API_TOKEN from Infisical (prod /shared/controlplane-admin) via
# the CI machine identity instead of the duplicated Gitea Actions secret,
# mirroring the molecule-controlplane bench-provision-time bootstrap and
# this repo's boot-to-registration-e2e KMS pattern. The value is exported
# to $GITHUB_ENV so the "Call CP redeploy-fleet" step reads it as an
# ordinary masked env var.
#
# TRUSTED-REF GATING: molecule-core is a PUBLIC repo; this step consumes
# the INFISICAL_CI_* machine-identity secrets, so it must only run on a
# TRUSTED event. This workflow is workflow_dispatch-only, so the guard
# matches that; it is defense-in-depth if other triggers are ever added.
- name: Fetch CP_ADMIN_API_TOKEN from Infisical KMS
id: cp_admin_token
if: >-
github.event_name == 'workflow_dispatch'
env:
INFISICAL_CI_CLIENT_ID: ${{ secrets.INFISICAL_CI_CLIENT_ID }}
INFISICAL_CI_CLIENT_SECRET: ${{ secrets.INFISICAL_CI_CLIENT_SECRET }}
INFISICAL_PROJECT_ID: ${{ secrets.INFISICAL_CI_PROJECT_ID }}
run: |
set -uo pipefail
BASE="https://key.moleculesai.app"
TOK=$(curl -fsS -X POST "$BASE/api/v1/auth/universal-auth/login" \
-H 'Content-Type: application/json' \
-d "{\"clientId\":\"$INFISICAL_CI_CLIENT_ID\",\"clientSecret\":\"$INFISICAL_CI_CLIENT_SECRET\"}" \
| python3 -c 'import sys,json;print(json.load(sys.stdin)["accessToken"])')
read_secret() {
curl -fsS "$BASE/api/v3/secrets/raw/$1?workspaceId=$INFISICAL_PROJECT_ID&environment=prod&secretPath=$2" \
-H "Authorization: Bearer $TOK" \
| python3 -c 'import sys,json; v=json.load(sys.stdin).get("secret",{}).get("secretValue"); sys.stdout.write(v if isinstance(v,str) else "")'
}
CP_ADMIN_API_TOKEN=$(read_secret CP_ADMIN_API_TOKEN %2Fshared%2Fcontrolplane-admin)
echo "::add-mask::$CP_ADMIN_API_TOKEN"
# Masking-control: Infisical is the authoritative source for this token.
# Assert NON-EMPTY and FAIL LOUD — a side-effecting prod redeploy must
# never run with an empty admin token.
if [ -z "$CP_ADMIN_API_TOKEN" ]; then
echo "::error::Infisical returned empty CP_ADMIN_API_TOKEN at prod /shared/controlplane-admin — failing closed."
exit 1
fi
echo "CP_ADMIN_API_TOKEN=$CP_ADMIN_API_TOKEN" >> "$GITHUB_ENV"
echo "CP_ADMIN_API_TOKEN loaded from Infisical (len=${#CP_ADMIN_API_TOKEN})"
- name: Kill-switch guard
# Rule 9 fix: exit fast if kill switch is set. No redeploy happens.
if: env.PROD_AUTO_DEPLOY_DISABLED == 'true'
@@ -124,13 +168,12 @@ jobs:
fi
- name: Call CP redeploy-fleet
# CP_ADMIN_API_TOKEN must be set as a repo/org secret on
# molecule-ai/molecule-core, matching the staging/prod CP's
# CP_ADMIN_API_TOKEN env. Stored in Railway, mirrored to this
# repo's secrets for CI.
# CP_ADMIN_API_TOKEN now arrives via $GITHUB_ENV from the "Fetch
# CP_ADMIN_API_TOKEN from Infisical KMS" step above (wave-3 migration);
# it is the Infisical SSOT value, matching the staging/prod CP's
# CP_ADMIN_API_TOKEN env. The [ -z ... ] guard below still validates it.
env:
CP_URL: ${{ vars.CP_URL || 'https://api.moleculesai.app' }}
CP_ADMIN_API_TOKEN: ${{ secrets.CP_ADMIN_API_TOKEN }}
TARGET_TAG: ${{ steps.tag.outputs.target_tag }}
CANARY_SLUG: ${{ vars.PROD_REDEPLOY_CANARY_SLUG || secrets.PROD_REDEPLOY_CANARY_SLUG || '' }}
SOAK_SECONDS: ${{ vars.PROD_REDEPLOY_SOAK_SECONDS || secrets.PROD_REDEPLOY_SOAK_SECONDS || '' }}
+49 -3
View File
@@ -219,15 +219,61 @@ jobs:
env:
SHA: ${{ needs.staging-smoke.outputs.sha }}
CP_URL: ${{ vars.CP_URL || 'https://staging-api.moleculesai.app' }}
# CP_ADMIN_API_TOKEN gates write access to the redeploy endpoint.
# Stored at the repo level so all workflows pick it up automatically.
CP_ADMIN_API_TOKEN: ${{ secrets.CP_ADMIN_API_TOKEN }}
# CP_ADMIN_API_TOKEN now arrives via $GITHUB_ENV from the "Fetch
# CP_ADMIN_API_TOKEN from Infisical KMS" step below (wave-3 migration);
# it is the Infisical SSOT value and gates write access to the redeploy
# endpoint. The "Check CP credentials" step still validates it is set.
# canary_slug pin: deploy the verified :staging-<sha> to the canary
# first (soak 120s), then fan out to the rest of the fleet.
CANARY_SLUG: ${{ vars.CANARY_PROMOTE_SLUG || '' }}
SOAK_SECONDS: ${{ vars.CANARY_PROMOTE_SOAK || '120' }}
BATCH_SIZE: ${{ vars.CANARY_PROMOTE_BATCH || '3' }}
steps:
# KMS wave-3 (Gitea-Actions-secrets -> Infisical SSOT): source
# CP_ADMIN_API_TOKEN from Infisical (prod /shared/controlplane-admin) via
# the CI machine identity instead of the duplicated Gitea Actions secret,
# mirroring this repo's boot-to-registration-e2e KMS pattern. Exported to
# $GITHUB_ENV so the credential-check + promote steps read it as a masked
# env var.
#
# TRUSTED-REF GATING: molecule-core is a PUBLIC repo; this step consumes
# the INFISICAL_CI_* machine-identity secrets, so it must only run on a
# TRUSTED event — a push to the protected staging branch, or an operator
# workflow_dispatch. This workflow has no pull_request trigger, so an
# untrusted-fork PR cannot reach it.
- name: Fetch CP_ADMIN_API_TOKEN from Infisical KMS
id: cp_admin_token
if: >-
github.event_name == 'workflow_dispatch' ||
(github.event_name == 'push' && github.ref == 'refs/heads/staging')
env:
INFISICAL_CI_CLIENT_ID: ${{ secrets.INFISICAL_CI_CLIENT_ID }}
INFISICAL_CI_CLIENT_SECRET: ${{ secrets.INFISICAL_CI_CLIENT_SECRET }}
INFISICAL_PROJECT_ID: ${{ secrets.INFISICAL_CI_PROJECT_ID }}
run: |
set -uo pipefail
BASE="https://key.moleculesai.app"
TOK=$(curl -fsS -X POST "$BASE/api/v1/auth/universal-auth/login" \
-H 'Content-Type: application/json' \
-d "{\"clientId\":\"$INFISICAL_CI_CLIENT_ID\",\"clientSecret\":\"$INFISICAL_CI_CLIENT_SECRET\"}" \
| python3 -c 'import sys,json;print(json.load(sys.stdin)["accessToken"])')
read_secret() {
curl -fsS "$BASE/api/v3/secrets/raw/$1?workspaceId=$INFISICAL_PROJECT_ID&environment=prod&secretPath=$2" \
-H "Authorization: Bearer $TOK" \
| python3 -c 'import sys,json; v=json.load(sys.stdin).get("secret",{}).get("secretValue"); sys.stdout.write(v if isinstance(v,str) else "")'
}
CP_ADMIN_API_TOKEN=$(read_secret CP_ADMIN_API_TOKEN %2Fshared%2Fcontrolplane-admin)
echo "::add-mask::$CP_ADMIN_API_TOKEN"
# Masking-control: this promote step performs a side-effecting fleet
# redeploy. Assert NON-EMPTY and FAIL LOUD — never promote with an
# empty admin token.
if [ -z "$CP_ADMIN_API_TOKEN" ]; then
echo "::error::Infisical returned empty CP_ADMIN_API_TOKEN at prod /shared/controlplane-admin — failing closed."
exit 1
fi
echo "CP_ADMIN_API_TOKEN=$CP_ADMIN_API_TOKEN" >> "$GITHUB_ENV"
echo "CP_ADMIN_API_TOKEN loaded from Infisical (len=${#CP_ADMIN_API_TOKEN})"
- name: Check CP credentials
run: |
if [ -z "${CP_ADMIN_API_TOKEN:-}" ]; then
+44 -1
View File
@@ -76,7 +76,9 @@ jobs:
AWS_REGION: us-east-2
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_SECRETS_JANITOR_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRETS_JANITOR_SECRET_ACCESS_KEY }}
CP_ADMIN_API_TOKEN: ${{ secrets.CP_ADMIN_API_TOKEN }}
# CP_ADMIN_API_TOKEN now arrives via $GITHUB_ENV from the "Fetch
# CP_ADMIN_API_TOKEN from Infisical KMS" step below (wave-3 migration).
# The Verify-required-secrets gate still validates it is non-empty.
CP_STAGING_ADMIN_API_TOKEN: ${{ secrets.CP_STAGING_ADMIN_API_TOKEN }}
MAX_DELETE_PCT: 50
GRACE_HOURS: 24
@@ -84,6 +86,47 @@ jobs:
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
# KMS wave-3 (Gitea-Actions-secrets -> Infisical SSOT): source
# CP_ADMIN_API_TOKEN from Infisical (prod /shared/controlplane-admin) via
# the CI machine identity instead of the duplicated Gitea Actions secret,
# mirroring this repo's boot-to-registration-e2e KMS pattern. Exported to
# $GITHUB_ENV so the verify + sweep steps read it as a masked env var.
#
# TRUSTED-REF GATING: molecule-core is a PUBLIC repo; this step consumes
# the INFISICAL_CI_* machine-identity secrets, so it must only run on a
# TRUSTED event — the schedule cron or an operator workflow_dispatch. An
# untrusted-fork PR cannot reach this step.
- name: Fetch CP_ADMIN_API_TOKEN from Infisical KMS
id: cp_admin_token
if: >-
github.event_name == 'schedule' ||
github.event_name == 'workflow_dispatch'
env:
INFISICAL_CI_CLIENT_ID: ${{ secrets.INFISICAL_CI_CLIENT_ID }}
INFISICAL_CI_CLIENT_SECRET: ${{ secrets.INFISICAL_CI_CLIENT_SECRET }}
INFISICAL_PROJECT_ID: ${{ secrets.INFISICAL_CI_PROJECT_ID }}
run: |
set -uo pipefail
BASE="https://key.moleculesai.app"
TOK=$(curl -fsS -X POST "$BASE/api/v1/auth/universal-auth/login" \
-H 'Content-Type: application/json' \
-d "{\"clientId\":\"$INFISICAL_CI_CLIENT_ID\",\"clientSecret\":\"$INFISICAL_CI_CLIENT_SECRET\"}" \
| python3 -c 'import sys,json;print(json.load(sys.stdin)["accessToken"])')
read_secret() {
curl -fsS "$BASE/api/v3/secrets/raw/$1?workspaceId=$INFISICAL_PROJECT_ID&environment=prod&secretPath=$2" \
-H "Authorization: Bearer $TOK" \
| python3 -c 'import sys,json; v=json.load(sys.stdin).get("secret",{}).get("secretValue"); sys.stdout.write(v if isinstance(v,str) else "")'
}
CP_ADMIN_API_TOKEN=$(read_secret CP_ADMIN_API_TOKEN %2Fshared%2Fcontrolplane-admin)
echo "::add-mask::$CP_ADMIN_API_TOKEN"
# Masking-control: assert NON-EMPTY and FAIL LOUD.
if [ -z "$CP_ADMIN_API_TOKEN" ]; then
echo "::error::Infisical returned empty CP_ADMIN_API_TOKEN at prod /shared/controlplane-admin — failing closed."
exit 1
fi
echo "CP_ADMIN_API_TOKEN=$CP_ADMIN_API_TOKEN" >> "$GITHUB_ENV"
echo "CP_ADMIN_API_TOKEN loaded from Infisical (len=${#CP_ADMIN_API_TOKEN})"
- name: Verify required secrets present
id: verify
# Schedule-vs-dispatch behaviour split mirrors sweep-cf-orphans
+44 -1
View File
@@ -83,7 +83,9 @@ jobs:
env:
CF_API_TOKEN: ${{ secrets.CF_API_TOKEN || secrets.CLOUDFLARE_API_TOKEN }}
CF_ZONE_ID: ${{ secrets.CF_ZONE_ID || secrets.CLOUDFLARE_ZONE_ID }}
CP_ADMIN_API_TOKEN: ${{ secrets.CP_ADMIN_API_TOKEN }}
# CP_ADMIN_API_TOKEN now arrives via $GITHUB_ENV from the "Fetch
# CP_ADMIN_API_TOKEN from Infisical KMS" step below (wave-3 migration).
# The Verify-required-secrets gate still validates it is non-empty.
CP_STAGING_ADMIN_API_TOKEN: ${{ secrets.CP_STAGING_ADMIN_API_TOKEN }}
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
@@ -93,6 +95,47 @@ jobs:
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
# KMS wave-3 (Gitea-Actions-secrets -> Infisical SSOT): source
# CP_ADMIN_API_TOKEN from Infisical (prod /shared/controlplane-admin) via
# the CI machine identity instead of the duplicated Gitea Actions secret,
# mirroring this repo's boot-to-registration-e2e KMS pattern. Exported to
# $GITHUB_ENV so the verify + sweep steps read it as a masked env var.
#
# TRUSTED-REF GATING: molecule-core is a PUBLIC repo; this step consumes
# the INFISICAL_CI_* machine-identity secrets, so it must only run on a
# TRUSTED event — the schedule cron or an operator workflow_dispatch. An
# untrusted-fork PR cannot reach this step.
- name: Fetch CP_ADMIN_API_TOKEN from Infisical KMS
id: cp_admin_token
if: >-
github.event_name == 'schedule' ||
github.event_name == 'workflow_dispatch'
env:
INFISICAL_CI_CLIENT_ID: ${{ secrets.INFISICAL_CI_CLIENT_ID }}
INFISICAL_CI_CLIENT_SECRET: ${{ secrets.INFISICAL_CI_CLIENT_SECRET }}
INFISICAL_PROJECT_ID: ${{ secrets.INFISICAL_CI_PROJECT_ID }}
run: |
set -uo pipefail
BASE="https://key.moleculesai.app"
TOK=$(curl -fsS -X POST "$BASE/api/v1/auth/universal-auth/login" \
-H 'Content-Type: application/json' \
-d "{\"clientId\":\"$INFISICAL_CI_CLIENT_ID\",\"clientSecret\":\"$INFISICAL_CI_CLIENT_SECRET\"}" \
| python3 -c 'import sys,json;print(json.load(sys.stdin)["accessToken"])')
read_secret() {
curl -fsS "$BASE/api/v3/secrets/raw/$1?workspaceId=$INFISICAL_PROJECT_ID&environment=prod&secretPath=$2" \
-H "Authorization: Bearer $TOK" \
| python3 -c 'import sys,json; v=json.load(sys.stdin).get("secret",{}).get("secretValue"); sys.stdout.write(v if isinstance(v,str) else "")'
}
CP_ADMIN_API_TOKEN=$(read_secret CP_ADMIN_API_TOKEN %2Fshared%2Fcontrolplane-admin)
echo "::add-mask::$CP_ADMIN_API_TOKEN"
# Masking-control: assert NON-EMPTY and FAIL LOUD.
if [ -z "$CP_ADMIN_API_TOKEN" ]; then
echo "::error::Infisical returned empty CP_ADMIN_API_TOKEN at prod /shared/controlplane-admin — failing closed."
exit 1
fi
echo "CP_ADMIN_API_TOKEN=$CP_ADMIN_API_TOKEN" >> "$GITHUB_ENV"
echo "CP_ADMIN_API_TOKEN loaded from Infisical (len=${#CP_ADMIN_API_TOKEN})"
- name: Verify required secrets present
id: verify
# Schedule-vs-dispatch behaviour split (hardened 2026-04-28
+46 -1
View File
@@ -78,13 +78,58 @@ jobs:
env:
CF_API_TOKEN: ${{ secrets.CF_API_TOKEN || secrets.CLOUDFLARE_API_TOKEN }}
CF_ACCOUNT_ID: ${{ secrets.CF_ACCOUNT_ID || secrets.CLOUDFLARE_ACCOUNT_ID }}
CP_ADMIN_API_TOKEN: ${{ secrets.CP_ADMIN_API_TOKEN }}
# CP_ADMIN_API_TOKEN now arrives via $GITHUB_ENV from the "Fetch
# CP_ADMIN_API_TOKEN from Infisical KMS" step below (wave-3 migration).
# The Verify-required-secrets gate still validates it is non-empty.
CP_STAGING_ADMIN_API_TOKEN: ${{ secrets.CP_STAGING_ADMIN_API_TOKEN }}
MAX_DELETE_PCT: ${{ github.event.inputs.max_delete_pct || '90' }}
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
# KMS wave-3 (Gitea-Actions-secrets -> Infisical SSOT): source
# CP_ADMIN_API_TOKEN from Infisical (prod /shared/controlplane-admin) via
# the CI machine identity instead of the duplicated Gitea Actions secret,
# mirroring this repo's boot-to-registration-e2e KMS pattern. Exported to
# $GITHUB_ENV so the verify + sweep steps read it as a masked env var.
#
# TRUSTED-REF GATING: molecule-core is a PUBLIC repo; this step consumes
# the INFISICAL_CI_* machine-identity secrets, so it must only run on a
# TRUSTED event — the schedule cron or an operator workflow_dispatch. An
# untrusted-fork PR cannot reach this step.
- name: Fetch CP_ADMIN_API_TOKEN from Infisical KMS
id: cp_admin_token
if: >-
github.event_name == 'schedule' ||
github.event_name == 'workflow_dispatch'
env:
INFISICAL_CI_CLIENT_ID: ${{ secrets.INFISICAL_CI_CLIENT_ID }}
INFISICAL_CI_CLIENT_SECRET: ${{ secrets.INFISICAL_CI_CLIENT_SECRET }}
INFISICAL_PROJECT_ID: ${{ secrets.INFISICAL_CI_PROJECT_ID }}
run: |
set -uo pipefail
BASE="https://key.moleculesai.app"
TOK=$(curl -fsS -X POST "$BASE/api/v1/auth/universal-auth/login" \
-H 'Content-Type: application/json' \
-d "{\"clientId\":\"$INFISICAL_CI_CLIENT_ID\",\"clientSecret\":\"$INFISICAL_CI_CLIENT_SECRET\"}" \
| python3 -c 'import sys,json;print(json.load(sys.stdin)["accessToken"])')
read_secret() {
curl -fsS "$BASE/api/v3/secrets/raw/$1?workspaceId=$INFISICAL_PROJECT_ID&environment=prod&secretPath=$2" \
-H "Authorization: Bearer $TOK" \
| python3 -c 'import sys,json; v=json.load(sys.stdin).get("secret",{}).get("secretValue"); sys.stdout.write(v if isinstance(v,str) else "")'
}
CP_ADMIN_API_TOKEN=$(read_secret CP_ADMIN_API_TOKEN %2Fshared%2Fcontrolplane-admin)
echo "::add-mask::$CP_ADMIN_API_TOKEN"
# Masking-control: assert NON-EMPTY and FAIL LOUD. On a scheduled run
# an empty token would otherwise be caught by the verify step as
# "missing", but failing here is louder and closer to the cause.
if [ -z "$CP_ADMIN_API_TOKEN" ]; then
echo "::error::Infisical returned empty CP_ADMIN_API_TOKEN at prod /shared/controlplane-admin — failing closed."
exit 1
fi
echo "CP_ADMIN_API_TOKEN=$CP_ADMIN_API_TOKEN" >> "$GITHUB_ENV"
echo "CP_ADMIN_API_TOKEN loaded from Infisical (len=${#CP_ADMIN_API_TOKEN})"
- name: Verify required secrets present
id: verify
# Schedule-vs-dispatch behaviour split mirrors sweep-cf-orphans
+60 -1
View File
@@ -105,7 +105,10 @@ jobs:
timeout-minutes: 30
env:
MOLECULE_CP_URL: ${{ vars.CP_URL || 'https://staging-api.moleculesai.app' }}
MOLECULE_ADMIN_TOKEN: ${{ secrets.CP_ADMIN_API_TOKEN }}
# MOLECULE_ADMIN_TOKEN (alias for CP_ADMIN_API_TOKEN) now arrives via
# $GITHUB_ENV from the "Fetch CP_ADMIN_API_TOKEN from Infisical KMS" step
# below (wave-3 migration). The "Verify required secret present" step
# still validates it is non-empty before the e2e runs.
E2E_EXPECTED_MODEL: moonshot/kimi-k2.6
steps:
- name: No-op pass (delivery surface unchanged in this diff)
@@ -115,6 +118,62 @@ jobs:
echo "::notice::template-delivery-e2e no-op pass (detect-changes: ${{ needs.detect-changes.outputs.debug }})."
- if: needs.detect-changes.outputs.delivery == 'true'
uses: actions/checkout@v4
# KMS wave-3 (Gitea-Actions-secrets -> Infisical SSOT): source the admin
# token (consumed here as MOLECULE_ADMIN_TOKEN) from Infisical (prod
# /shared/controlplane-admin) via the CI machine identity instead of the
# duplicated Gitea Actions secret, mirroring this repo's
# boot-to-registration-e2e KMS pattern. Exported to $GITHUB_ENV under the
# alias MOLECULE_ADMIN_TOKEN so the verify + e2e steps read it unchanged.
# Only runs when the delivery surface changed (the real e2e runs); a
# no-op PR never touches the CI identity.
#
# TRUSTED-REF GATING: molecule-core is a PUBLIC repo; this step consumes
# the INFISICAL_CI_* machine-identity secrets, so it must only run on a
# TRUSTED event — operator workflow_dispatch, a push to the protected main
# branch, or a SAME-REPO pull_request. The pull_request clause uses the
# FAIL-CLOSED positive allowlist
# (github.event.pull_request.head.repo.full_name == github.repository):
# it admits ONLY a same-repo head and fails closed on a fork, a
# detached/cross-repo head, OR a missing/null head.repo field (the negative
# `head.repo.fork == false` form would FAIL-OPEN on a null `fork`, since
# `null == false` coerces TRUE in the expression engine). An untrusted-fork
# PR is therefore excluded so it cannot harvest the KMS token. A fork
# delivery PR will fail the "Verify required secret present" check below
# (loud, not silent) until a maintainer runs it from a trusted ref.
- name: Fetch CP_ADMIN_API_TOKEN from Infisical KMS
id: cp_admin_token
if: >-
needs.detect-changes.outputs.delivery == 'true' &&
(github.event_name == 'workflow_dispatch' ||
(github.event_name == 'push' && github.ref == 'refs/heads/main') ||
(github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository))
env:
INFISICAL_CI_CLIENT_ID: ${{ secrets.INFISICAL_CI_CLIENT_ID }}
INFISICAL_CI_CLIENT_SECRET: ${{ secrets.INFISICAL_CI_CLIENT_SECRET }}
INFISICAL_PROJECT_ID: ${{ secrets.INFISICAL_CI_PROJECT_ID }}
run: |
set -uo pipefail
BASE="https://key.moleculesai.app"
TOK=$(curl -fsS -X POST "$BASE/api/v1/auth/universal-auth/login" \
-H 'Content-Type: application/json' \
-d "{\"clientId\":\"$INFISICAL_CI_CLIENT_ID\",\"clientSecret\":\"$INFISICAL_CI_CLIENT_SECRET\"}" \
| python3 -c 'import sys,json;print(json.load(sys.stdin)["accessToken"])')
read_secret() {
curl -fsS "$BASE/api/v3/secrets/raw/$1?workspaceId=$INFISICAL_PROJECT_ID&environment=prod&secretPath=$2" \
-H "Authorization: Bearer $TOK" \
| python3 -c 'import sys,json; v=json.load(sys.stdin).get("secret",{}).get("secretValue"); sys.stdout.write(v if isinstance(v,str) else "")'
}
CP_ADMIN_API_TOKEN=$(read_secret CP_ADMIN_API_TOKEN %2Fshared%2Fcontrolplane-admin)
echo "::add-mask::$CP_ADMIN_API_TOKEN"
# Masking-control: this required delivery gate must not run against an
# empty admin token. Assert NON-EMPTY and FAIL LOUD.
if [ -z "$CP_ADMIN_API_TOKEN" ]; then
echo "::error::Infisical returned empty CP_ADMIN_API_TOKEN at prod /shared/controlplane-admin — failing closed."
exit 1
fi
# Export under the alias the e2e consumes.
echo "MOLECULE_ADMIN_TOKEN=$CP_ADMIN_API_TOKEN" >> "$GITHUB_ENV"
echo "CP_ADMIN_API_TOKEN loaded from Infisical (len=${#CP_ADMIN_API_TOKEN})"
- name: Verify required secret present
if: needs.detect-changes.outputs.delivery == 'true'
run: |