Skip to content

Commit c2c8524

Browse files
authored
Merge branch 'main' into refactor/coverage-script-cleanup
2 parents 88e27fb + 1d18f88 commit c2c8524

28 files changed

Lines changed: 4384 additions & 820 deletions
Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
---
2+
# SPDX-FileCopyrightText: (C) 2025 Intel Corporation
3+
# SPDX-License-Identifier: Apache-2.0
4+
# Gitleaks Secret Scanner Action
5+
#
6+
# This composite action performs secret scanning using Gitleaks,
7+
# supporting full repository scans or changed-file-only mode, with SARIF reporting.
8+
#
9+
# Key Features:
10+
# - Detects hardcoded secrets and credentials
11+
# - Supports custom configuration and baselines
12+
# - Redaction of sensitive values in logs
13+
# - SARIF output for GitHub Code Scanning integration
14+
#
15+
# Process Stages:
16+
# 1. Environment Setup:
17+
# - Gitleaks installation (specific or latest version)
18+
#
19+
# 2. Scan Execution:
20+
# - Full repository or changed files only
21+
# - Apply custom config and baseline if provided
22+
#
23+
# 3. Results Processing:
24+
# - Report generation in SARIF/JSON/CSV
25+
# - Artifact upload
26+
# - Optional SARIF upload to GitHub Security tab
27+
#
28+
# Required Inputs:
29+
# - scan-scope: Scope of scan (all or changed)
30+
# - source: Path to scan
31+
#
32+
# Optional Inputs:
33+
# - config_path: Path to custom Gitleaks config
34+
# - baseline_path: Path to baseline file
35+
# - report_format: sarif, json, or csv (default: sarif)
36+
# - redact: Redact secrets in output (true/false)
37+
#
38+
# Outputs:
39+
# - exit_code: Gitleaks exit code
40+
# - report_path: Path to generated report
41+
#
42+
# Example Usage:
43+
# steps:
44+
# - uses: ./.github/actions/security/gitleaks
45+
# with:
46+
# scan-scope: "changed"
47+
# source: "./src"
48+
# config_path: "./ci/gitleaks_baselines/<repo-name>-gitleaks.json"
49+
# report_format: "json"
50+
#
51+
# Note: Requires `security-events: write` permission for SARIF upload.
52+
53+
name: "Gitleaks Secret Scanner"
54+
description: "Detect leaked secrets with Gitleaks. Supports full repo or only-changed files, SARIF upload, baselines, and custom config."
55+
56+
inputs:
57+
scan-scope:
58+
description: "Scope of files to scan (all/changed)"
59+
required: false
60+
default: "changed"
61+
source:
62+
description: "Path to scan (repository root by default)"
63+
required: false
64+
default: "."
65+
version:
66+
description: "Gitleaks version: 'latest' or a specific version (e.g., 8.28.0)"
67+
required: false
68+
default: "latest"
69+
config_path:
70+
description: "Path to a .gitleaks.toml config (if omitted, Gitleaks uses its defaults)"
71+
required: false
72+
default: ""
73+
baseline_path:
74+
description: "Path to a baseline file to ignore previously known leaks"
75+
required: false
76+
default: ""
77+
report_format:
78+
description: "Output format (sarif,json,csv)"
79+
required: false
80+
default: "sarif"
81+
redact:
82+
description: "Redact secrets in logs/report (true/false)"
83+
required: false
84+
default: "true"
85+
exit_code_on_leak:
86+
description: "Exit code to use when leaks are found (0 to never fail, 1 default)"
87+
required: false
88+
default: "1"
89+
report_suffix:
90+
description: "Suffix for artifact/report names (e.g., -linux, -windows). Include the leading '-'"
91+
required: false
92+
default: ""
93+
94+
outputs:
95+
exit_code:
96+
description: "Exit code from gitleaks detect"
97+
value: ${{ steps.run-gitleaks.outputs.exit_code }}
98+
report_path:
99+
description: "Path to the generated report file"
100+
value: ${{ steps.run-gitleaks.outputs.report_path }}
101+
102+
runs:
103+
using: "composite"
104+
steps:
105+
- name: Get changed files
106+
if: inputs['scan-scope'] == 'changed'
107+
id: changed-files
108+
uses: tj-actions/changed-files@ed68ef82c095e0d48ec87eccea555d944a631a4c # v46.0.5
109+
110+
- name: Install Gitleaks
111+
id: install
112+
shell: bash
113+
env:
114+
INPUT_VERSION: ${{ inputs.version }}
115+
run: |
116+
set -euo pipefail
117+
VER="${INPUT_VERSION}"
118+
119+
if [[ "$VER" == "latest" ]]; then
120+
# Resolve latest tag (e.g., v8.28.0) and strip the 'v' for the tarball name
121+
VER=$(curl -s https://api.github.com/repos/gitleaks/gitleaks/releases/latest \
122+
| grep -Po '"tag_name":\s*"v\K[0-9.]+' || true)
123+
if [[ -z "$VER" ]]; then
124+
echo "::error::Failed to resolve latest Gitleaks version"
125+
exit 1
126+
fi
127+
fi
128+
129+
echo "Installing Gitleaks version: $VER"
130+
curl -sSL \
131+
-o /tmp/gitleaks.tar.gz \
132+
"https://github.com/gitleaks/gitleaks/releases/download/v${VER}/gitleaks_${VER}_linux_x64.tar.gz"
133+
sudo tar xf /tmp/gitleaks.tar.gz -C /usr/local/bin gitleaks
134+
rm -f /tmp/gitleaks.tar.gz
135+
gitleaks version || (echo "::error::Gitleaks failed to install" && exit 1)
136+
137+
- name: Run Gitleaks
138+
id: run-gitleaks
139+
shell: bash
140+
env:
141+
INPUT_SCOPE: ${{ inputs['scan-scope'] }}
142+
INPUT_SOURCE: ${{ inputs.source }}
143+
INPUT_CONFIG: ${{ inputs.config_path }}
144+
INPUT_BASELINE: ${{ inputs.baseline_path }}
145+
INPUT_FORMAT: ${{ inputs.report_format }}
146+
INPUT_REDACT: ${{ inputs.redact }}
147+
INPUT_EXIT_CODE: ${{ inputs.exit_code_on_leak }}
148+
CHANGED_ALL: ${{ steps.changed-files.outputs.all_changed_files }}
149+
run: |
150+
set -euo pipefail
151+
152+
mkdir -p security-results/gitleaks
153+
RAND_SUFFIX=$(head /dev/urandom | tr -dc a-z0-9 | head -c 6)
154+
REPORT_FILE="security-results/gitleaks/gitleaks-results-${RAND_SUFFIX}.${INPUT_FORMAT}"
155+
echo "rand_suffix=${RAND_SUFFIX}" >> "$GITHUB_OUTPUT"
156+
157+
# Build scan directory depending on scope
158+
SCAN_DIR="${INPUT_SOURCE}"
159+
if [[ "$INPUT_SCOPE" == "changed" ]]; then
160+
if [[ -n "${CHANGED_ALL:-}" ]]; then
161+
echo "Scanning only changed files"
162+
TMPDIR="$(mktemp -d)"
163+
# Recreate directory structure and copy only changed files
164+
while IFS= read -r f; do
165+
# Skip deleted files and ensure directory exists
166+
if [[ -f "$f" ]]; then
167+
mkdir -p "$TMPDIR/$(dirname "$f")"
168+
cp --parents "$f" "$TMPDIR" 2>/dev/null || cp "$f" "$TMPDIR/$(dirname "$f")/"
169+
fi
170+
done <<< "${CHANGED_ALL}"
171+
SCAN_DIR="$TMPDIR"
172+
NO_GIT="--no-git"
173+
else
174+
echo "No changed files detected; scanning full source"
175+
NO_GIT=""
176+
fi
177+
fi
178+
179+
# Build CLI
180+
CMD=(
181+
gitleaks detect
182+
--source "$SCAN_DIR"
183+
--report-format "$INPUT_FORMAT"
184+
--report-path "$REPORT_FILE"
185+
--exit-code "$INPUT_EXIT_CODE"
186+
)
187+
[[ -n "${NO_GIT:-}" ]] && CMD+=( "$NO_GIT" )
188+
[[ "$INPUT_REDACT" == "true" ]] && CMD+=( --redact )
189+
[[ -n "$INPUT_CONFIG" && -f "$INPUT_CONFIG" ]] && CMD+=( --config "$INPUT_CONFIG" )
190+
[[ -n "$INPUT_BASELINE" && -f "$INPUT_BASELINE" ]] && CMD+=( --baseline-path "$INPUT_BASELINE" )
191+
192+
echo "Executing: ${CMD[*]}"
193+
set +e
194+
"${CMD[@]}"
195+
STATUS=$?
196+
set -e
197+
198+
if [[ -f "$REPORT_FILE" ]]; then
199+
echo "report_path=$REPORT_FILE" >> "$GITHUB_OUTPUT"
200+
else
201+
echo "::error::Report file was not generated"
202+
exit 1
203+
fi
204+
echo "exit_code=$STATUS" >> "$GITHUB_OUTPUT"
205+
# Don't hard-fail the job; let the caller decide based on outputs.exit_code
206+
if [[ "$STATUS" -ne 0 ]]; then
207+
echo "::warning::Gitleaks detected leaks (exit code $STATUS)"
208+
fi
209+
210+
- name: Upload report artifact
211+
if: steps.run-gitleaks.outputs.report_path != ''
212+
env:
213+
suffix: ${{ inputs.report_suffix }}
214+
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
215+
with:
216+
name: gitleaks-results-${{ steps.run-gitleaks.outputs.rand_suffix }}${{ env.suffix }}
217+
path: ${{ steps.run-gitleaks.outputs.report_path }}
218+
retention-days: 7
219+
220+
- name: Upload SARIF (code scanning)
221+
if: contains(steps.run-gitleaks.outputs.report_path, '.sarif')
222+
uses: github/codeql-action/upload-sarif@1b549b9259bda1cb5ddde3b41741a82a2d15a841 # v3.28.8
223+
with:
224+
sarif_file: ${{ steps.run-gitleaks.outputs.report_path }}

.github/workflows/boot_tester.yml

Lines changed: 49 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,46 @@ permissions:
1111
jobs:
1212
boot-test:
1313
runs-on: ubuntu-latest
14+
strategy:
15+
matrix:
16+
include:
17+
- distribution: "emt3"
18+
image_type: "raw"
19+
script: "scripts/build_emt3_raw.sh"
20+
- distribution: "emt3"
21+
image_type: "iso"
22+
script: "scripts/build_emt3_iso.sh"
23+
- distribution: "emt3"
24+
image_type: "immutable"
25+
script: "scripts/build_emt3_immutable.sh"
26+
- distribution: "elxr12"
27+
image_type: "raw"
28+
script: "scripts/build_elxr12_raw.sh"
29+
- distribution: "elxr12"
30+
image_type: "iso"
31+
script: "scripts/build_elxr12_iso.sh"
32+
- distribution: "elxr12"
33+
image_type: "immutable"
34+
script: "scripts/build_elxr12_immutable.sh"
35+
- distribution: "ubuntu24"
36+
image_type: "raw"
37+
script: "scripts/build_ubuntu24_raw.sh"
38+
- distribution: "ubuntu24"
39+
image_type: "iso"
40+
script: "scripts/build_ubuntu24_iso.sh"
41+
- distribution: "ubuntu24"
42+
image_type: "immutable"
43+
script: "scripts/build_ubuntu24_immutable.sh"
44+
- distribution: "azl3"
45+
image_type: "raw"
46+
script: "scripts/build_azl3_raw.sh"
47+
- distribution: "azl3"
48+
image_type: "iso"
49+
script: "scripts/build_azl3_iso.sh"
50+
- distribution: "azl3"
51+
image_type: "immutable"
52+
script: "scripts/build_azl3_immutable.sh"
53+
fail-fast: false # Continue testing other images even if one fails
1454
steps:
1555
- name: Checkout code
1656
uses: actions/checkout@v4
@@ -36,19 +76,19 @@ jobs:
3676
with:
3777
go-version: stable # or a pinned version you know exists
3878

39-
- name: Copy tester script
79+
- name: Prepare build script
4080
run: |
41-
if [ ! -f validate.sh ]; then
42-
echo "validate.sh not found!"
81+
if [ ! -f "${{ matrix.script }}" ]; then
82+
echo "${{ matrix.script }} not found!"
4383
exit 1
4484
fi
45-
chmod +x validate.sh
85+
chmod +x "${{ matrix.script }}"
4686
47-
- name: Run build-tester
87+
- name: Run ${{ matrix.distribution }} ${{ matrix.image_type }} boot test
4888
run: |
49-
echo "Starting validate.sh..."
89+
echo "Starting ${{ matrix.distribution }} ${{ matrix.image_type }} image build and boot test..."
5090
# Ensure script has access to docker group for Earthly
5191
sudo usermod -aG docker $USER
52-
# Run the validation script
53-
./validate.sh --qemu-test
54-
echo "Build and tests completed."
92+
# Run the specific build script with QEMU test
93+
./${{ matrix.script }} --qemu-test
94+
echo "${{ matrix.distribution }} ${{ matrix.image_type }} build and boot test completed."

0 commit comments

Comments
 (0)