Skip to content

Commit e16c497

Browse files
ericsmallingclaude
andcommitted
jenkins: validate setup.sh inputs, pipefail in cgSign/Verify, lockfile cleanup
Five Copilot findings from the eleventh pass on PR #330: - setup.sh: trim + validate user-supplied CHAINGUARD_ORG and PUSH_REGISTRY (sanitize_env_value + validate_env_value helpers) before persisting. Rejects empty, internal whitespace, and quotes — all of which would silently break .env parsing by docker compose / JCasC / bash `source`. Also re-validates values inherited from .env so a hand-edited corruption surfaces at setup.sh entry rather than mid-`terraform apply`. - cgSign + cgVerify: switch the digest-resolution sh blocks from `set -eu` to `set -eu -o pipefail` so a failing `docker image inspect` mid-pipeline surfaces as the script's exit status rather than being masked by the trailing `head -1` returning 0. - teardown.sh: also remove iac/.terraform.lock.hcl and harbor/terraform/.terraform.lock.hcl on cleanup. They're generated by terraform init and gitignored, so a "full teardown" leaving them behind contradicts the script's stated goal. (Preserved alongside iac/terraform.tfstate when TF_DESTROY_FAILED so the user can retry.) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent bdba2e9 commit e16c497

4 files changed

Lines changed: 52 additions & 7 deletions

File tree

jenkins/setup.sh

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,16 +41,53 @@ prompt_yn() {
4141
[[ "$ans" =~ ^[Yy] ]]
4242
}
4343

44+
# Strip leading/trailing whitespace from $1 and echo the result.
45+
sanitize_env_value() {
46+
local v="$1"
47+
v="${v#"${v%%[![:space:]]*}"}"
48+
v="${v%"${v##*[![:space:]]}"}"
49+
printf '%s' "$v"
50+
}
51+
52+
# Validate a value about to be written to .env. Rejects empty, internal
53+
# whitespace, and quotes — all of which would either silently corrupt the
54+
# dotenv line (parsed by docker compose / JCasC / bash `source`) or be
55+
# easy footguns from a stray paste.
56+
validate_env_value() {
57+
local name="$1" v="$2"
58+
if [[ -z "$v" ]]; then
59+
echo " ERROR: $name must not be empty." >&2
60+
return 1
61+
fi
62+
if [[ "$v" =~ [[:space:]] ]]; then
63+
echo " ERROR: $name must not contain whitespace (got: '$v')." >&2
64+
return 1
65+
fi
66+
if [[ "$v" == *\"* || "$v" == *\'* ]]; then
67+
echo " ERROR: $name must not contain quotes (got: '$v')." >&2
68+
return 1
69+
fi
70+
return 0
71+
}
72+
4473
# Prompt for the Chainguard org if .env didn't supply one. The answer gets
4574
# persisted to .env in Phase 1 below, so subsequent re-runs go straight
4675
# through without prompting.
4776
if [[ -z "${CHAINGUARD_ORG:-}" ]]; then
4877
echo "==> No Chainguard org configured."
4978
echo " Examples: 'chainguard' (public catalog) or 'your-org.example.com'."
50-
while [[ -z "${CHAINGUARD_ORG:-}" ]]; do
79+
while :; do
5180
read -rp " Enter your Chainguard org: " CHAINGUARD_ORG
81+
CHAINGUARD_ORG=$(sanitize_env_value "$CHAINGUARD_ORG")
82+
if validate_env_value CHAINGUARD_ORG "$CHAINGUARD_ORG"; then break; fi
5283
done
5384
echo
85+
else
86+
# Even values supplied via env / .env can have stray whitespace from a
87+
# hand-edited dotenv — re-validate so the corruption surfaces here rather
88+
# than mid-`terraform apply`.
89+
CHAINGUARD_ORG=$(sanitize_env_value "$CHAINGUARD_ORG")
90+
validate_env_value CHAINGUARD_ORG "$CHAINGUARD_ORG" || exit 1
5491
fi
5592
ORG="$CHAINGUARD_ORG"
5693
echo "==> Chainguard org: ${ORG}"
@@ -76,13 +113,15 @@ if [[ "$PUSH_TO_HARBOR" == "true" ]]; then
76113
else
77114
PUSH_REGISTRY_DEFAULT="${PUSH_REGISTRY:-}"
78115
PUSH_REGISTRY=""
79-
while [[ -z "$PUSH_REGISTRY" ]]; do
116+
while :; do
80117
if [[ -n "$PUSH_REGISTRY_DEFAULT" ]]; then
81118
read -rp "Where should pipelines push their built images? [last used: ${PUSH_REGISTRY_DEFAULT}]: " PUSH_REG_INPUT
82119
PUSH_REGISTRY="${PUSH_REG_INPUT:-$PUSH_REGISTRY_DEFAULT}"
83120
else
84121
read -rp "Where should pipelines push their built images? (e.g. ttl.sh/your-prefix): " PUSH_REGISTRY
85122
fi
123+
PUSH_REGISTRY=$(sanitize_env_value "$PUSH_REGISTRY")
124+
if validate_env_value PUSH_REGISTRY "$PUSH_REGISTRY"; then break; fi
86125
done
87126
fi
88127

jenkins/shared-libraries/cg-images/vars/cgSign.groovy

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,10 @@ def call(String image) {
5757
string(credentialsId: 'cosign-password', variable: 'COSIGN_PASSWORD'),
5858
]) {
5959
sh '''
60-
set -eu
60+
set -eu -o pipefail
61+
# pipefail so a failing `docker image inspect` (e.g. image not in
62+
# the local cache yet) is surfaced as the pipeline's exit status
63+
# rather than masked by the trailing `head -1` returning 0.
6164
# Pick the RepoDigest whose repo matches the image we just pushed.
6265
# The local image cache may have stale RepoDigests from prior runs
6366
# under different registries (e.g. localhost/library from a Mode C

jenkins/shared-libraries/cg-images/vars/cgVerify.groovy

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,10 @@ def call(String image) {
3636
file(credentialsId: 'cosign-public-key', variable: 'COSIGN_PUB_FILE'),
3737
]) {
3838
sh '''
39-
set -eu
39+
set -eu -o pipefail
40+
# pipefail so a failing `docker image inspect` (e.g. image not in
41+
# the local cache yet) is surfaced as the pipeline's exit status
42+
# rather than masked by the trailing `head -1` returning 0.
4043
# Pick the RepoDigest whose repo matches the image we want to verify.
4144
# See cgSign.groovy for why .RepoDigests can have stale entries from
4245
# prior runs.

jenkins/teardown.sh

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -98,11 +98,11 @@ rm -f shared-libraries/cg-images/IDENTITY
9898
# kind cluster gets blown away wholesale by harbor/teardown.sh), so we
9999
# clean it unconditionally.
100100
if (( TF_DESTROY_FAILED == 0 )); then
101-
rm -rf iac/.terraform iac/terraform.tfstate iac/terraform.tfstate.backup iac/jenkins-jwks.json
101+
rm -rf iac/.terraform iac/.terraform.lock.hcl iac/terraform.tfstate iac/terraform.tfstate.backup iac/jenkins-jwks.json
102102
else
103-
echo " Preserving iac/terraform.tfstate so a future ./teardown.sh can retry the destroy."
103+
echo " Preserving iac/terraform.tfstate (and .terraform.lock.hcl) so a future ./teardown.sh can retry the destroy."
104104
fi
105-
rm -rf harbor/terraform/.terraform harbor/terraform/terraform.tfstate harbor/terraform/terraform.tfstate.backup harbor/terraform/terraform.tfvars
105+
rm -rf harbor/terraform/.terraform harbor/terraform/.terraform.lock.hcl harbor/terraform/terraform.tfstate harbor/terraform/terraform.tfstate.backup harbor/terraform/terraform.tfvars
106106
rm -f harbor/cg/helm/values.yaml harbor/cg/manifests/deploy-ingress-nginx.yaml
107107

108108
if [[ "$WIPE_ENV" == "true" ]]; then

0 commit comments

Comments
 (0)