fix(TST-25,SEC): stop CI SSH key leaking in cleartext CI logs
The windows-x86 acceptance check 'no key material in logs' failed: run #37's job log printed the full WINDEV_SSH_KEY PEM in the step env echo. Gitea's secret masker is line-oriented, so a multiline PEM rendered as one line with literal \n escapes never matches the real-newline secret value and is not redacted. Fix: store WINDEV_SSH_KEY base64-encoded (single line) so the masker redacts it to ***; run-windev-ci.sh auto-decodes a base64 PEM (still accepts a raw PEM for local hand-testing). Drop the redundant WINDEV_SSH_KNOWN_HOSTS from the job env (host keys are public and come from the committed windev.known_hosts pin), removing another cleartext env line. Document the base64 requirement in the bring-up README. Operationally: the previously-exposed CI key has been rotated on windev (old pubkey revoked from administrators_authorized_keys, new key installed) and the Gitea WINDEV_SSH_KEY secret replaced with the new key's base64.
This commit is contained in:
@@ -136,8 +136,11 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Worker x86 build + tests on windev
|
||||
env:
|
||||
# WINDEV_SSH_KEY is stored base64-encoded (single line) so Gitea's line-oriented secret
|
||||
# masker redacts it in the step env echo; run-windev-ci.sh decodes it. A raw multiline PEM
|
||||
# would leak in cleartext here (TST-25 acceptance: no key material in logs). Known-hosts is
|
||||
# public and comes from the committed scripts/ci/windev.known_hosts pin (no secret needed).
|
||||
WINDEV_SSH_KEY: ${{ secrets.WINDEV_SSH_KEY }}
|
||||
WINDEV_SSH_KNOWN_HOSTS: ${{ secrets.WINDEV_SSH_KNOWN_HOSTS }}
|
||||
WINDEV_SSH_USER: ${{ vars.WINDEV_SSH_USER }}
|
||||
CI_SHA: ${{ github.sha }}
|
||||
# `test` = x86 build + Worker.Tests (~50s measured on windev). Demote to `build` only if the
|
||||
@@ -155,8 +158,11 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Full Worker.Tests + live-MXAccess smoke on windev
|
||||
env:
|
||||
# WINDEV_SSH_KEY is stored base64-encoded (single line) so Gitea's line-oriented secret
|
||||
# masker redacts it in the step env echo; run-windev-ci.sh decodes it. A raw multiline PEM
|
||||
# would leak in cleartext here (TST-25 acceptance: no key material in logs). Known-hosts is
|
||||
# public and comes from the committed scripts/ci/windev.known_hosts pin (no secret needed).
|
||||
WINDEV_SSH_KEY: ${{ secrets.WINDEV_SSH_KEY }}
|
||||
WINDEV_SSH_KNOWN_HOSTS: ${{ secrets.WINDEV_SSH_KNOWN_HOSTS }}
|
||||
WINDEV_SSH_USER: ${{ vars.WINDEV_SSH_USER }}
|
||||
CI_SHA: ${{ github.sha }}
|
||||
run: ./scripts/ci/run-windev-ci.sh live
|
||||
|
||||
@@ -31,10 +31,14 @@ first, then merge.
|
||||
personal windev key): `ssh-keygen -t ed25519 -f ci_windev -N ''`. Append `ci_windev.pub`
|
||||
to the windev CI account's `authorized_keys` (optionally with a forced `command=` limiting
|
||||
it to this bootstrap).
|
||||
3. **Gitea repo secrets** — store the private key as `WINDEV_SSH_KEY` and, optionally, the
|
||||
pinned host keys as `WINDEV_SSH_KNOWN_HOSTS` (the committed `windev.known_hosts` is the
|
||||
fallback). `run-windev-ci.sh` connects as user `ci` by default (`WINDEV_SSH_USER` to
|
||||
override); ensure that account exists on windev, or set `WINDEV_SSH_USER` to the intended one.
|
||||
3. **Gitea repo secret `WINDEV_SSH_KEY`** — store the private key **base64-encoded on a single
|
||||
line**: `base64 -w0 < ci_windev` (macOS: `base64 < ci_windev | tr -d '\n'`). This is required,
|
||||
not cosmetic — Gitea's secret masker is line-oriented, so a raw multiline PEM is **not**
|
||||
redacted in the step `env:` echo and leaks in cleartext; the single-line base64 masks to `***`.
|
||||
`run-windev-ci.sh` auto-decodes it. Host keys are public and come from the committed
|
||||
`windev.known_hosts` pin, so no `WINDEV_SSH_KNOWN_HOSTS` secret is wired into `ci.yml`.
|
||||
`run-windev-ci.sh` connects as user `ci` by default; set the `WINDEV_SSH_USER` **variable**
|
||||
(not a secret — it is public) to the actual account, and ensure that account exists on windev.
|
||||
4. **Network precheck** — confirm the Gitea runner container (on the `traefik` docker network,
|
||||
host `10.100.0.35`) can reach `10.100.0.48:22`: a one-off `nc -z -w5 10.100.0.48 22` step.
|
||||
The network was created for gitea name resolution, not LAN egress, so verify.
|
||||
|
||||
@@ -12,8 +12,12 @@
|
||||
#
|
||||
# Environment:
|
||||
# CI_SHA commit to test (default: `git rev-parse HEAD` in this checkout)
|
||||
# WINDEV_SSH_KEY private key PEM (Gitea secret). If empty, falls back to the
|
||||
# runner's default ssh identity/agent (used for local hand-testing).
|
||||
# WINDEV_SSH_KEY private key (Gitea secret). Store it BASE64-ENCODED (one line):
|
||||
# Gitea's secret masker is line-oriented, so a raw multiline PEM in
|
||||
# the step `env:` echo is NOT redacted and leaks in cleartext, whereas
|
||||
# the single-line base64 is masked to *** (TST-25 acceptance: no key
|
||||
# material in logs). A raw PEM is still accepted for local hand-testing
|
||||
# (auto-detected). If empty, falls back to the runner's default identity.
|
||||
# WINDEV_SSH_KNOWN_HOSTS pinned host keys (Gitea secret). If empty, uses the committed
|
||||
# scripts/ci/windev.known_hosts.
|
||||
# WINDEV_SSH_USER ssh user on windev (default: ci)
|
||||
@@ -60,9 +64,16 @@ fi
|
||||
SSH_OPTS+=(-o "UserKnownHostsFile=$KNOWN_HOSTS")
|
||||
|
||||
# Private key: secret if provided, else fall back to the default identity/agent.
|
||||
# CI stores it base64-encoded (single line) so Gitea's line-oriented secret masker redacts it
|
||||
# in the step env echo — a raw multiline PEM leaks in cleartext. Decode when it is valid base64
|
||||
# wrapping a PEM; otherwise treat the value as a raw PEM (local hand-testing convenience).
|
||||
if [ -n "${WINDEV_SSH_KEY:-}" ]; then
|
||||
KEY="$WORK/id_ci"
|
||||
( umask 077; printf '%s\n' "$WINDEV_SSH_KEY" > "$KEY" )
|
||||
if printf '%s' "$WINDEV_SSH_KEY" | base64 -d 2>/dev/null | grep -q 'PRIVATE KEY'; then
|
||||
( umask 077; printf '%s' "$WINDEV_SSH_KEY" | base64 -d > "$KEY" )
|
||||
else
|
||||
( umask 077; printf '%s\n' "$WINDEV_SSH_KEY" > "$KEY" )
|
||||
fi
|
||||
SSH_OPTS+=(-o IdentitiesOnly=yes -i "$KEY")
|
||||
fi
|
||||
|
||||
|
||||
Reference in New Issue
Block a user