Skip to content

Commit ed4eacd

Browse files
ericsmallingclaude
andcommitted
jenkins: HARBOR_ADMIN_PASSWORD env, cosign 600 perms, ttl.sh expiry docs
Bundled remediations from the ninth Copilot pass on PR #330: - HARBOR_ADMIN_PASSWORD: drop the hardcoded "Harbor12345" literal from cgLogin (Mode C push-auth), the harbor Terraform provider, and the Helm values template. All three now consume a single env var that defaults to "Harbor12345" (the chart's own default) when unset, but can be overridden via .env before running setup.sh. Wired through setup.sh → .env, deploy.sh → Helm + tfvars, JCasC globalNodeProperties → controller env → cgLogin. Updated the user-facing docs (top-level README, harbor/README, setup.sh and deploy.sh status prints) to mention the variable. - cosign perms: re-tighten to chmod 600. Round 7's switch to ${readFile:…} forced regress to 644 because JCasC (uid 1000) couldn't read host-user-owned 600 files across the bind mount. setup.sh now does a one-shot root container that chowns the key, pub, and password files to uid 1000:1000 and chmods 600 — JCasC reads as the same uid, and setup.sh no longer needs host-side read access (the passphrase isn't round-tripped through env any more). Teardown.sh's existing sudo-rm fallback covers cleanup. - ttl.sh expiry notes: the four per-app READMEs (python312, 314, node22, 25) all said "ttl.sh tags expire" unconditionally, but Mode C pushes go to Harbor (persistent). Reword to be conditional on $PUSH_REGISTRY. jobs.groovy descriptions had the same issue; also reworded. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent d24f252 commit ed4eacd

17 files changed

Lines changed: 103 additions & 32 deletions

File tree

jenkins/.env.example

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,15 @@
3232
# skips the OIDC chainctl exchange when true (Harbor pulls are anonymous).
3333
# HARBOR_ENABLED=false
3434

35+
# Harbor admin password. Default is the chart's own default ("Harbor12345")
36+
# so the demo works out of the box. setup.sh writes this when Harbor is
37+
# enabled; the value drives:
38+
# - the Helm chart's harborAdminPassword
39+
# - the Terraform harbor provider (used for the cgr-proxy project)
40+
# - cgLogin's Mode C push-auth (cgr-proxy admin docker config)
41+
# Override before running setup.sh to use a different password.
42+
# HARBOR_ADMIN_PASSWORD=Harbor12345
43+
3544
# Note: the Chainguard assumed identity UIDP (Mode A) is NOT stored here.
3645
# setup.sh writes it to shared-libraries/cg-images/IDENTITY (filesystem-SCM
3746
# live-loaded; cgLogin reads it at build time).

jenkins/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ These bit me while building out the seven samples — useful to know up front wh
160160
- **Gradle**: `environment { GRADLE_USER_HOME = "${WORKSPACE}/.gradle" }`
161161
- **npm / pnpm**: `environment { HOME = "${WORKSPACE}" }`
162162
- **Chainguard's `python:3.x-dev` runs as uid 65532**, which can't write to the system site-packages. For pipelines that want to `pip install --system` or `uv pip install --system`, pass `args '--user 0 --entrypoint='` in the Jenkinsfile **and** add `USER 0` to the corresponding stage in the Dockerfile.
163-
- **OCI-image pipelines push to whatever `$PUSH_REGISTRY` resolves to**: `ttl.sh/<prefix>` in Modes A/B (anonymous, 24h TTL) or `localhost/library` in Mode C (Harbor admin/Harbor12345 baked in by `cgLogin`). Per-app `IMAGE` envs use `${env.PUSH_REGISTRY}/<app-name>:<tag>` — works for both ttl.sh and Harbor without per-mode pipeline edits.
163+
- **OCI-image pipelines push to whatever `$PUSH_REGISTRY` resolves to**: `ttl.sh/<prefix>` in Modes A/B (anonymous, 24h TTL) or `localhost/library` in Mode C (Harbor admin auth supplied by `cgLogin`, sourced from `$HARBOR_ADMIN_PASSWORD` — defaults to the chart's `Harbor12345`, overridable in `.env`). Per-app `IMAGE` envs use `${env.PUSH_REGISTRY}/<app-name>:<tag>` — works for both ttl.sh and Harbor without per-mode pipeline edits.
164164
- **The Auth stage must precede any `agent { docker { image '...' } }` stage**, because the docker-workflow plugin pulls the agent's image using whatever creds are in `$DOCKER_CONFIG` *at the start of that stage*. The current pipeline shape (`Auth``Checkout` → docker-agent stages) gets the ordering right; preserve it when adding new pipelines.
165165

166166
## Teardown

jenkins/apps/node22-npm-express/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,4 @@ docker run --rm -p 8080:8080 $PUSH_REGISTRY/nodetest:22
4040
# Visit http://localhost:8080/
4141
```
4242

43-
ttl.sh tags expire (default 24 hours). Re-run the pipeline to refresh.
43+
If `$PUSH_REGISTRY` points at ttl.sh (Modes A/B), tags expire after the default 24 hours — re-run the pipeline to refresh. In Mode C the push goes to the local Harbor (`localhost/library/...`) and persists until teardown.

jenkins/apps/node25-pnpm-express/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,4 +35,4 @@ docker run --rm -p 8080:8080 $PUSH_REGISTRY/nodetest:25
3535
# Visit http://localhost:8080/
3636
```
3737

38-
ttl.sh tags expire (default 24 hours). Re-run the pipeline to refresh.
38+
If `$PUSH_REGISTRY` points at ttl.sh (Modes A/B), tags expire after the default 24 hours — re-run the pipeline to refresh. In Mode C the push goes to the local Harbor (`localhost/library/...`) and persists until teardown.

jenkins/apps/python312-pip-django/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,4 @@ docker run --rm -p 8080:8080 $PUSH_REGISTRY/pytest:3-12
2929
# Visit http://localhost:8080/
3030
```
3131

32-
ttl.sh tags expire (default 24 hours). Re-run the pipeline to refresh.
32+
If `$PUSH_REGISTRY` points at ttl.sh (Modes A/B), tags expire after the default 24 hours — re-run the pipeline to refresh. In Mode C the push goes to the local Harbor (`localhost/library/...`) and persists until teardown.

jenkins/apps/python314-uv-flask/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,4 @@ docker run --rm -p 8080:8080 $PUSH_REGISTRY/pytest:3-14
2727
# Visit http://localhost:8080/
2828
```
2929

30-
Note: ttl.sh tags expire (default 24 hours). Re-run the pipeline to refresh.
30+
Note: if `$PUSH_REGISTRY` points at ttl.sh (Modes A/B), tags expire after the default 24 hours — re-run the pipeline to refresh. In Mode C the push goes to the local Harbor (`localhost/library/...`) and persists until teardown.

jenkins/docker-compose.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,12 @@ services:
3030
PULL_REGISTRY: ${PULL_REGISTRY:-cgr.dev/${CHAINGUARD_ORG}}
3131
PUSH_REGISTRY: ${PUSH_REGISTRY:-ttl.sh/smalls}
3232
HARBOR_ENABLED: ${HARBOR_ENABLED:-false}
33+
# Harbor admin password — surfaced to pipelines via JCasC so cgLogin's
34+
# Mode C path doesn't have to hardcode the chart default in source.
35+
# setup.sh persists this in .env when Harbor is enabled; deploy.sh and
36+
# the harbor Terraform provider read the same value from there. Empty
37+
# when Harbor isn't in use — cgLogin only reads it on the Mode C path.
38+
HARBOR_ADMIN_PASSWORD: ${HARBOR_ADMIN_PASSWORD:-}
3339
# NOTE: the cosign signing-key passphrase used to live here as
3440
# COSIGN_PASSWORD. JCasC now reads it directly off the bind-mounted
3541
# file at boot via `${readFile:/tmp/cgjenkins-home/.secrets/cosign.password}`,

jenkins/harbor/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,6 @@ export PULL_PASS=...
5555
./deploy.sh
5656
```
5757

58-
The Harbor admin UI is at <https://localhost/harbor> (`admin` / `Harbor12345`). The chart issues a self-signed cert, so browsers will show a one-time warning — click through. Tear down with `./teardown.sh`.
58+
The Harbor admin UI is at <https://localhost/harbor>. The username is `admin`; the password is whatever `$HARBOR_ADMIN_PASSWORD` resolves to (default: the chart's `Harbor12345`; override by setting `HARBOR_ADMIN_PASSWORD` in `../.env` before running `../setup.sh`). The chart issues a self-signed cert, so browsers will show a one-time warning — click through. Tear down with `./teardown.sh`.
5959

6060
> **Why HTTPS for the UI but HTTP for the registry?** Harbor 2.12.3+ ships with `gorilla/csrf` v1.7.3, which hardcodes the request scheme to `https` inside its origin check. Harbor's middleware doesn't compensate, so a plain-HTTP `POST /c/login` is rejected with `403 origin invalid` before the password is even checked (upstream bug: [goharbor/harbor#22010](https://github.com/goharbor/harbor/issues/22010)). The Docker daemon, in turn, refuses HTTPS connections to `127.0.0.0/8` by default, so the registry path (`/v2/`, `/service/token`, etc.) must remain reachable over HTTP. We split the two: TLS is enabled on the ingress for the UI, but `ssl-redirect` is off so HTTP isn't forced — the `externalURL` stays `http://localhost` so Harbor advertises HTTP to docker clients. Browser users type `https://`, pipelines push over `http://`, both work.

jenkins/harbor/cg/helm/values.template

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@
1313
# so HTTP→HTTPS isn't forced — that lets `docker push` over HTTP coexist
1414
# with the HTTPS UI on the same ingress.
1515
externalURL: http://localhost
16+
# Admin password injected at deploy-template-render time from the host env.
17+
# deploy.sh defaults this to "Harbor12345" (the chart's own default) when
18+
# unset, so out-of-the-box demos still work. To override, set
19+
# HARBOR_ADMIN_PASSWORD in .env before running ./setup.sh.
20+
harborAdminPassword: "${HARBOR_ADMIN_PASSWORD}"
1621
expose:
1722
type: ingress
1823
tls:

jenkins/harbor/deploy.sh

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,14 @@ cd "$(dirname "$0")"
2222
: "${PULL_USER:?PULL_USER must be set (Chainguard pull-token username)}"
2323
: "${PULL_PASS:?PULL_PASS must be set (Chainguard pull-token password)}"
2424
KIND_CLUSTER_NAME="${KIND_CLUSTER_NAME:-jenkins-harbor}"
25+
# Harbor admin password — defaults to the chart's own default so out-of-the-
26+
# box demos work, but can be overridden via setup.sh / .env. The same value
27+
# is consumed by the Helm values template and by Terraform's harbor provider.
28+
HARBOR_ADMIN_PASSWORD="${HARBOR_ADMIN_PASSWORD:-Harbor12345}"
2529

2630
export ORG_NAME="${CHAINGUARD_ORG}"
2731
export REGISTRY_URL="cgr.dev/${CHAINGUARD_ORG}"
32+
export HARBOR_ADMIN_PASSWORD
2833

2934
for tool in kind kubectl helm terraform envsubst; do
3035
if ! command -v "$tool" >/dev/null 2>&1; then
@@ -94,6 +99,6 @@ envsubst < terraform/terraform.templatevars > terraform/terraform.tfvars
9499
)
95100

96101
echo "==> Done."
97-
echo " Harbor UI: https://localhost/harbor (admin / Harbor12345; click through cert warning)"
102+
echo " Harbor UI: https://localhost/harbor (admin / ${HARBOR_ADMIN_PASSWORD}; click through cert warning)"
98103
echo " Proxy cache URL: localhost/cgr-proxy/${CHAINGUARD_ORG}/<image>:<tag>"
99104
echo " Push project: localhost/library/<image>:<tag>"

0 commit comments

Comments
 (0)