mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-10-23 20:25:56 +00:00
Bind release browser qualification to the narrow CI identity
Use a dedicated Auth Keys write client restricted to tag:ci-deploy, never the broader demo registration. Reject missing configuration and validate the actual running Self tag and DNS before Serve. Keep exact-source, denial-stop, no-replay and cleanup contracts, with connected offline registration and Serve controls. Change-source: pulse-maintainer
This commit is contained in:
@@ -371,6 +371,28 @@ non-mutating wrapper that verifies the current committed stable target. All
|
||||
stable demo writes require an exact stable tag and activation marker and run
|
||||
from `release-convergence.yml` under the global customer-promotion lease.
|
||||
|
||||
## Published-RC browser qualification registration
|
||||
|
||||
`qualify-browser-update-release.yml` must **not** reuse the demo binding above.
|
||||
It uses the separate repository secrets **TS_CI_DEPLOY_OAUTH_CLIENT_ID** and
|
||||
**TS_CI_DEPLOY_OAUTH_SECRET** for a dedicated business-tailnet OAuth client with
|
||||
only **Auth Keys write**, restricted to **tag:ci-deploy**. These names must not
|
||||
alias/copy the `tag:infra` demo client or a full-access administrative client.
|
||||
The Tailnet/credential owner verifies that client scope and tag restriction when
|
||||
configuring the pair; source inspection and the node's observed tag do not prove
|
||||
OAuth scope. No secret value belongs in source, logs or receipts.
|
||||
|
||||
The workflow fails before joining when either dedicated secret is unavailable;
|
||||
there is no demo-credential, auth-key or caller-input fallback. It checks the
|
||||
actual running node's **Self.Tags == ["tag:ci-deploy"]** and its own business
|
||||
DNS name before starting Serve. Only its own `127.0.0.1:7655` is served over
|
||||
HTTPS, with no peer selection, SSH, routes or private demo/production target.
|
||||
This journey needs no expansion of CI access to private services. Cleanup resets
|
||||
that new Serve route even if route setup fails after the successful join; the
|
||||
pinned Tailscale action and fresh hosted VM own node teardown. A configured
|
||||
binding, source tests or a joined node is not native update/recovery acceptance.
|
||||
|
||||
|
||||
## Helm CI
|
||||
|
||||
**File**: `helm-ci.yml`
|
||||
|
||||
@@ -112,21 +112,33 @@ jobs:
|
||||
npx --no-install playwright install --with-deps chromium
|
||||
sudo apt-get update -qq
|
||||
sudo apt-get install -y --no-install-recommends jq curl openssh-client
|
||||
- name: Register a fresh ephemeral project CI node
|
||||
- name: Require the dedicated narrow CI registration binding
|
||||
env:
|
||||
CI_CLIENT_ID: ${{ secrets.TS_CI_DEPLOY_OAUTH_CLIENT_ID }}
|
||||
CI_CLIENT_SECRET: ${{ secrets.TS_CI_DEPLOY_OAUTH_SECRET }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
if [[ -z "$CI_CLIENT_ID" || -z "$CI_CLIENT_SECRET" ]]; then
|
||||
echo 'Dedicated tag:ci-deploy OAuth binding is not configured; no demo credential fallback is permitted.' >&2
|
||||
exit 2
|
||||
fi
|
||||
- name: Register a fresh ephemeral narrow CI node
|
||||
id: tailnet
|
||||
uses: tailscale/github-action@780049a30b6ff5c378a9e7b389d15ece7a204888 # v4.1.3
|
||||
with:
|
||||
oauth-client-id: ${{ secrets.TS_OAUTH_CLIENT_ID }}
|
||||
oauth-secret: ${{ secrets.TS_OAUTH_SECRET }}
|
||||
tags: tag:infra
|
||||
oauth-client-id: ${{ secrets.TS_CI_DEPLOY_OAUTH_CLIENT_ID }}
|
||||
oauth-secret: ${{ secrets.TS_CI_DEPLOY_OAUTH_SECRET }}
|
||||
tags: tag:ci-deploy
|
||||
version: '1.94.2'
|
||||
- name: Serve only this disposable install
|
||||
id: serve
|
||||
run: |
|
||||
set -euo pipefail
|
||||
# Never enumerate peer/private targets or use a supplied hostname.
|
||||
origin=$(tailscale status --json | python3 -c 'import json,re,sys; n=json.load(sys.stdin)["Self"]["DNSName"].rstrip("."); assert re.fullmatch(r"[a-z0-9-]+\.tawny-powan\.ts\.net", n); print("https://"+n)')
|
||||
# Validate the actual Self tag before Serve. Never select a peer or
|
||||
# fall back to the demo client's broader tag:infra identity.
|
||||
origin=$(tailscale status --json | python3 scripts/release_browser_tailnet.py)
|
||||
tailscale serve --bg --https=443 http://127.0.0.1:7655
|
||||
echo "origin=$origin" >> "$GITHUB_OUTPUT"
|
||||
python3 scripts/write_github_output.py origin "$origin"
|
||||
- name: Exercise native browser update and documented recovery
|
||||
env:
|
||||
FROM: ${{ steps.pair.outputs.from }}
|
||||
@@ -142,7 +154,7 @@ jobs:
|
||||
PLAYWRIGHT_BROWSERS_PATH="$RUNNER_TEMP/browser-release/browsers" \
|
||||
bash scripts/release_lifecycle_rehearsal.sh --hosted-browser --from "$FROM" --to "$TAG"
|
||||
- name: Close ephemeral Serve route
|
||||
if: always() && steps.serve.outcome == 'success'
|
||||
if: always() && steps.tailnet.outcome == 'success'
|
||||
run: tailscale serve reset
|
||||
- name: Retain bounded identity and terminal receipts, never credentials
|
||||
if: always()
|
||||
|
||||
Reference in New Issue
Block a user