Merge pull request 'fix: [nomad-prep] P11 — wire lib/secret-scan.sh into Woodpecker CI gate (#798)' (#813) from fix/issue-798 into main
All checks were successful
ci/woodpecker/push/ci Pipeline was successful
All checks were successful
ci/woodpecker/push/ci Pipeline was successful
This commit is contained in:
commit
faf6490877
2 changed files with 100 additions and 0 deletions
68
.woodpecker/run-secret-scan.sh
Normal file
68
.woodpecker/run-secret-scan.sh
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
# run-secret-scan.sh — CI wrapper for lib/secret-scan.sh
|
||||
#
|
||||
# Scans files changed in this PR for plaintext secrets.
|
||||
# Exits non-zero if any secret is detected.
|
||||
|
||||
# shellcheck source=../lib/secret-scan.sh
|
||||
source lib/secret-scan.sh
|
||||
|
||||
# Path patterns considered secret-adjacent
|
||||
SECRET_PATH_PATTERNS=(
|
||||
'\.env'
|
||||
'tools/vault-.*\.sh'
|
||||
'nomad/'
|
||||
'vault/'
|
||||
'action-vault/'
|
||||
'lib/hvault\.sh'
|
||||
'lib/action-vault\.sh'
|
||||
)
|
||||
|
||||
# Build a single regex from patterns
|
||||
path_regex=$(printf '%s|' "${SECRET_PATH_PATTERNS[@]}")
|
||||
path_regex="${path_regex%|}"
|
||||
|
||||
# Get files changed in this PR vs target branch.
|
||||
# Note: shallow clone (depth 50) may lack the merge base for very large PRs,
|
||||
# causing git diff to fail — || true means the gate skips rather than blocks.
|
||||
changed_files=$(git diff --name-only --diff-filter=ACMR "origin/${CI_COMMIT_TARGET_BRANCH}...HEAD" || true)
|
||||
|
||||
if [ -z "$changed_files" ]; then
|
||||
echo "secret-scan: no changed files found, skipping"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Filter to secret-adjacent paths only
|
||||
target_files=$(printf '%s\n' "$changed_files" | grep -E "$path_regex" || true)
|
||||
|
||||
if [ -z "$target_files" ]; then
|
||||
echo "secret-scan: no secret-adjacent files changed, skipping"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "secret-scan: scanning $(printf '%s\n' "$target_files" | wc -l) file(s):"
|
||||
printf ' %s\n' "$target_files"
|
||||
|
||||
failures=0
|
||||
while IFS= read -r file; do
|
||||
# Skip deleted files / non-existent
|
||||
[ -f "$file" ] || continue
|
||||
# Skip binary files
|
||||
file -b --mime-encoding "$file" 2>/dev/null | grep -q binary && continue
|
||||
|
||||
content=$(cat "$file")
|
||||
if ! scan_for_secrets "$content"; then
|
||||
echo "FAIL: secret detected in $file"
|
||||
failures=$((failures + 1))
|
||||
fi
|
||||
done <<< "$target_files"
|
||||
|
||||
if [ "$failures" -gt 0 ]; then
|
||||
echo ""
|
||||
echo "secret-scan: $failures file(s) contain potential secrets — merge blocked"
|
||||
echo "If these are false positives, verify patterns in lib/secret-scan.sh"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "secret-scan: all files clean"
|
||||
32
.woodpecker/secret-scan.yml
Normal file
32
.woodpecker/secret-scan.yml
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
# .woodpecker/secret-scan.yml — Block PRs that leak plaintext secrets
|
||||
#
|
||||
# Triggers on pull requests touching secret-adjacent paths.
|
||||
# Sources lib/secret-scan.sh and scans each changed file's content.
|
||||
# Exits non-zero if any potential secret is detected.
|
||||
|
||||
when:
|
||||
- event: pull_request
|
||||
path:
|
||||
- ".env*"
|
||||
- "tools/vault-*.sh"
|
||||
- "nomad/**/*"
|
||||
- "vault/**/*"
|
||||
- "action-vault/**/*"
|
||||
- "lib/hvault.sh"
|
||||
- "lib/action-vault.sh"
|
||||
|
||||
clone:
|
||||
git:
|
||||
image: alpine/git
|
||||
commands:
|
||||
- AUTH_URL=$(printf '%s' "$CI_REPO_CLONE_URL" | sed "s|://|://token:$FORGE_TOKEN@|")
|
||||
- git clone --depth 50 "$AUTH_URL" .
|
||||
- git fetch --depth 50 origin "$CI_COMMIT_REF" "$CI_COMMIT_TARGET_BRANCH"
|
||||
- git checkout FETCH_HEAD
|
||||
|
||||
steps:
|
||||
- name: secret-scan
|
||||
image: alpine:3
|
||||
commands:
|
||||
- apk add --no-cache bash git grep file
|
||||
- bash .woodpecker/run-secret-scan.sh
|
||||
Loading…
Add table
Add a link
Reference in a new issue