Skip to content

Commit 83ce367

Browse files
committed
test
Signed-off-by: Vipin Yadav <vipin.yadav@progress.com>
1 parent a8092f8 commit 83ce367

3 files changed

Lines changed: 193 additions & 31 deletions

File tree

.github/workflows/ci-main-pull-request.yml

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -541,6 +541,26 @@ on:
541541
# required: false
542542
# default: 'https://polaris.blackduck.com'
543543
# type: string
544+
perform-wiz-scan:
545+
description: 'Perform Wiz CLI security scan on Docker image'
546+
required: false
547+
type: boolean
548+
default: false
549+
wiz-fail-build:
550+
description: 'Fail the build on Wiz policy violations'
551+
required: false
552+
type: boolean
553+
default: true
554+
wiz-fail-on-critical:
555+
description: 'Fail the pipeline if Wiz finds CRITICAL vulnerabilities'
556+
required: false
557+
type: boolean
558+
default: false
559+
wiz-fail-on-high:
560+
description: 'Fail the pipeline if Wiz finds HIGH vulnerabilities'
561+
required: false
562+
type: boolean
563+
default: false
544564

545565
env:
546566
PRIMARY_APPLICATION: ${{ inputs.application }} # was 'default' # Custom repo property [primaryApplication]: chef360, automate, infra-server, habitat, supermarket, licensing, downloads, chef-client, inspec, chef-workstation (or derivatives like habitat-builder)
@@ -987,6 +1007,17 @@ jobs:
9871007
fail-grype-on-critical: ${{ inputs.grype-image-fail-on-critical }}
9881008
grype-image-skip-aws: ${{ inputs.grype-image-skip-aws }}
9891009

1010+
run-wiz-scan:
1011+
name: 'Wiz CLI security scan'
1012+
if: ${{ inputs.perform-wiz-scan == true }}
1013+
uses: chef/common-github-actions/.github/workflows/wiz.yml@grype-wiz
1014+
needs: checkout
1015+
with:
1016+
fail-build: ${{ inputs.wiz-fail-build }}
1017+
fail-on-critical: ${{ inputs.wiz-fail-on-critical }}
1018+
fail-on-high: ${{ inputs.wiz-fail-on-high }}
1019+
secrets: inherit
1020+
9901021
run-grype-hab-package-scan:
9911022
name: 'Grype scan Habitat packages from bldr.habitat.sh'
9921023
if: ${{ inputs.perform-grype-hab-scan == true }}
@@ -1128,7 +1159,7 @@ jobs:
11281159
# VER=$(cat VERSION)
11291160
# echo "VERSION=$VER" >> $GITHUB_ENV
11301161
# then ${{ env.VERSION }}
1131-
1162+
11321163
set-application-version:
11331164
runs-on: ubuntu-latest
11341165
name: 'Detect SBOM version for application'

.github/workflows/grype.yml

Lines changed: 4 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -98,28 +98,15 @@ jobs:
9898
elif [ -f "Makefile" ] && grep -q "^compose-build:" Makefile; then
9999
echo "Using Makefile compose-build target with GITHUB_TOKEN"
100100
export GITHUB_TOKEN="${{ secrets.GH_TOKEN }}"
101-
102-
# Record image IDs before build to detect newly built images
103-
BEFORE_IDS=$(docker images -q --no-trunc | sort)
104-
105101
make compose-build
106102
107103
echo "Detecting built images..."
108-
# Find newly created images by comparing before/after image IDs
109-
AFTER_IDS=$(docker images -q --no-trunc | sort)
110-
NEW_IDS=$(comm -13 <(echo "$BEFORE_IDS") <(echo "$AFTER_IDS"))
104+
docker compose images
105+
106+
IMAGES=$(docker images --format "{{.Repository}}:{{.Tag}}" | grep "^${REPO_NAME}" | grep -v "^<none>")
111107
112-
if [ -n "$NEW_IDS" ]; then
113-
IMAGES=""
114-
for id in $NEW_IDS; do
115-
img=$(docker images --format "{{.Repository}}:{{.Tag}}" --filter "id=${id}" | grep -v "<none>" | head -1)
116-
[ -n "$img" ] && IMAGES="${IMAGES}${img}"$'\n'
117-
done
118-
IMAGES=$(echo "$IMAGES" | grep -v '^$' | sort -u)
119-
fi
120-
121108
if [ -z "$IMAGES" ]; then
122-
echo "No new images detected, scanning all recent images"
109+
echo "No images found with prefix ${REPO_NAME}, scanning all recent images"
123110
IMAGES=$(docker images --format "{{.Repository}}:{{.Tag}}" | grep -v "^<none>" | head -5)
124111
fi
125112
# Strategy 3: Fallback to standard docker build

.github/workflows/wiz.yml

Lines changed: 157 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,13 @@ on:
1414
required: false
1515
type: boolean
1616
default: true
17-
wiz-image-skip-aws:
18-
description: 'Skip AWS ECR login (assumes images are scanned elsewhere)'
17+
fail-on-critical:
18+
description: 'Fail the build if Wiz finds CRITICAL vulnerabilities'
19+
required: false
20+
type: boolean
21+
default: false
22+
fail-on-high:
23+
description: 'Fail the build if Wiz finds HIGH vulnerabilities'
1924
required: false
2025
type: boolean
2126
default: false
@@ -55,14 +60,13 @@ jobs:
5560
env:
5661
GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
5762
run: |
58-
REPO_NAME=$(basename $(pwd))
59-
6063
if [ ! -f "Dockerfile" ]; then
61-
echo "❌ No Dockerfile found - this workflow requires a Dockerfile to scan Docker image"
64+
echo "❌ No Dockerfile found - cannot scan"
6265
exit 1
6366
fi
6467
6568
echo "Building Docker image..."
69+
REPO_NAME=$(basename $(pwd))
6670
6771
# Strategy 1: Check for build-docker.sh script (e.g., dsm-erchef)
6872
if [ -f "build-docker.sh" ]; then
@@ -94,14 +98,21 @@ jobs:
9498
9599
if [ -n "$NEW_IDS" ]; then
96100
for id in $NEW_IDS; do
97-
IMAGE=$(docker images --format "{{.Repository}}:{{.Tag}}" --filter "id=${id}" | grep -v "<none>" | head -1)
98-
[ -n "$IMAGE" ] && break
101+
# Use docker inspect instead of --filter (compatible with all Docker versions)
102+
IMAGE=$(docker inspect --format '{{index .RepoTags 0}}' "$id" 2>/dev/null || true)
103+
[ -n "$IMAGE" ] && [ "$IMAGE" != "<none>:<none>" ] && break
104+
IMAGE=""
99105
done
100106
fi
101107
102108
if [ -z "$IMAGE" ]; then
103-
echo "No new image detected, using most recent image"
104-
IMAGE=$(docker images --format "{{.Repository}}:{{.Tag}}" | grep -v "^<none>" | head -1)
109+
echo "No new image detected by ID comparison, falling back to repo name match"
110+
IMAGE=$(docker images --format "{{.Repository}}:{{.Tag}}" | grep -E "^${REPO_NAME}" | grep -v "<none>" | head -1)
111+
fi
112+
113+
if [ -z "$IMAGE" ]; then
114+
echo "⚠️ No image found matching ${REPO_NAME}, using most recent non-runner image"
115+
IMAGE=$(docker images --format "{{.Repository}}:{{.Tag}}" | grep -v "^<none>" | grep -v "^ghcr.io/github/" | grep -v "^ghcr.io/dependabot/" | head -1)
105116
fi
106117
# Strategy 3: Fallback to standard docker build
107118
else
@@ -118,10 +129,143 @@ jobs:
118129
echo "Image to scan: $IMAGE"
119130
echo "IMAGE=$IMAGE" >> "$GITHUB_OUTPUT"
120131
132+
- name: Fetch Wiz credentials from AKeyless
133+
id: fetch-secrets
134+
uses: LanceMcCarthy/akeyless-action@ca2424bb132118c0b907f38e6dae0475acc0fac4 # v5.2.1
135+
with:
136+
access-id: "p-5g555fgryzj2om"
137+
static-secrets: '{"/ProductSecurity/Tools/WIZ_CLIENT_ID":"WIZ_CLIENT_ID","/ProductSecurity/Tools/WIZ_CLIENT_SECRET":"WIZ_CLIENT_SECRET"}'
138+
139+
- name: Download Wiz CLI
140+
run: |
141+
curl -fsSL -o wizcli https://downloads.wiz.io/v1/wizcli/latest/wizcli-linux-amd64
142+
chmod +x wizcli
143+
121144
- name: Wiz CLI container image scan
122145
id: wiz-scan
123-
uses: prgs-community/githubactions-reusableworkflows/actions/wizcli@latest
146+
continue-on-error: true
147+
env:
148+
WIZ_CLIENT_ID: ${{ steps.fetch-secrets.outputs.WIZ_CLIENT_ID }}
149+
WIZ_CLIENT_SECRET: ${{ steps.fetch-secrets.outputs.WIZ_CLIENT_SECRET }}
150+
run: |
151+
set -o pipefail
152+
153+
SCAN_TYPE='container-image'
154+
SCAN_TARGET='${{ steps.build-image.outputs.IMAGE }}'
155+
156+
args=("$SCAN_TYPE")
157+
if [ -n "$SCAN_TARGET" ]; then
158+
args+=("$SCAN_TARGET")
159+
fi
160+
161+
# Always output JSON for severity analysis
162+
args+=("--json-output-file" "/tmp/wiz-scan.json")
163+
164+
./wizcli scan "${args[@]}" 2>&1 | tee /tmp/wiz-scan-results.txt
165+
EXIT_CODE=${PIPESTATUS[0]}
166+
167+
echo ""
168+
echo "============================================"
169+
echo "Wiz CLI Scan Output"
170+
echo "============================================"
171+
cat /tmp/wiz-scan-results.txt
172+
echo "============================================"
173+
echo ""
174+
175+
if [ $EXIT_CODE -eq 0 ]; then
176+
echo "scan-result=passed" >> $GITHUB_OUTPUT
177+
else
178+
echo "scan-result=failed" >> $GITHUB_OUTPUT
179+
fi
180+
exit $EXIT_CODE
181+
182+
- name: Check Wiz results for severity violations
183+
id: severity-check
184+
if: always()
185+
run: |
186+
JSON_FILE="/tmp/wiz-scan.json"
187+
188+
if [ ! -f "$JSON_FILE" ]; then
189+
echo "⚠️ Wiz JSON output not found, skipping severity check"
190+
echo "severity-result=skipped" >> $GITHUB_OUTPUT
191+
exit 0
192+
fi
193+
194+
# Count vulnerabilities by severity from Wiz JSON analytics summary
195+
CRITICAL_COUNT=$(jq '.result.analytics.vulnerabilities.criticalCount // 0' "$JSON_FILE" 2>/dev/null || echo "0")
196+
HIGH_COUNT=$(jq '.result.analytics.vulnerabilities.highCount // 0' "$JSON_FILE" 2>/dev/null || echo "0")
197+
198+
echo ""
199+
echo "============================================"
200+
echo "Wiz Security Scan - Vulnerability Summary"
201+
echo "============================================"
202+
echo "CRITICAL vulnerabilities: $CRITICAL_COUNT"
203+
echo "HIGH vulnerabilities: $HIGH_COUNT"
204+
echo "============================================"
205+
206+
# Save counts for job summary
207+
echo "critical-count=$CRITICAL_COUNT" >> $GITHUB_OUTPUT
208+
echo "high-count=$HIGH_COUNT" >> $GITHUB_OUTPUT
209+
210+
VIOLATIONS=""
211+
[ "${{ inputs.fail-on-critical }}" == "true" ] && [ "$CRITICAL_COUNT" -gt 0 ] && VIOLATIONS="${VIOLATIONS}${CRITICAL_COUNT} CRITICAL, "
212+
[ "${{ inputs.fail-on-high }}" == "true" ] && [ "$HIGH_COUNT" -gt 0 ] && VIOLATIONS="${VIOLATIONS}${HIGH_COUNT} HIGH, "
213+
214+
if [ -n "$VIOLATIONS" ]; then
215+
echo ""
216+
echo "❌ BUILD FAILED: Found ${VIOLATIONS%, } vulnerabilities"
217+
echo "severity-result=failed" >> $GITHUB_OUTPUT
218+
exit 1
219+
else
220+
echo ""
221+
echo "✅ No severity-violating vulnerabilities found"
222+
echo "severity-result=passed" >> $GITHUB_OUTPUT
223+
fi
224+
225+
- name: Write Job Summary
226+
if: always()
227+
run: |
228+
SCAN_RESULT="${{ steps.wiz-scan.outputs.scan-result }}"
229+
SEVERITY_RESULT="${{ steps.severity-check.outputs.severity-result }}"
230+
231+
# Overall result: fail if either policy or severity check failed
232+
if [ "$SCAN_RESULT" = "passed" ] && [ "$SEVERITY_RESULT" != "failed" ]; then
233+
ICON="✅"
234+
OVERALL="passed"
235+
else
236+
ICON="❌"
237+
OVERALL="failed"
238+
fi
239+
240+
{
241+
echo "## ${ICON} Wiz CLI Scan Results"
242+
echo ""
243+
echo "| Field | Value |"
244+
echo "|-------|-------|"
245+
echo "| **Scan type** | \`container-image\` |"
246+
echo "| **Target** | \`${{ steps.build-image.outputs.IMAGE }}\` |"
247+
echo "| **Policy result** | **${SCAN_RESULT}** |"
248+
echo "| **Severity result** | **${SEVERITY_RESULT}** |"
249+
echo "| **Overall** | **${OVERALL}** |"
250+
echo ""
251+
echo "### Vulnerability Counts"
252+
echo ""
253+
echo "| Severity | Count | Fail on? |"
254+
echo "|----------|-------|----------|"
255+
echo "| CRITICAL | ${{ steps.severity-check.outputs.critical-count || '0' }} | ${{ inputs.fail-on-critical }} |"
256+
echo "| HIGH | ${{ steps.severity-check.outputs.high-count || '0' }} | ${{ inputs.fail-on-high }} |"
257+
echo ""
258+
echo "### Scan Output"
259+
echo '```'
260+
cat /tmp/wiz-scan-results.txt 2>/dev/null || echo "(no output captured)"
261+
echo '```'
262+
} >> "$GITHUB_STEP_SUMMARY"
263+
264+
- name: Upload Wiz scan results
265+
if: always()
266+
uses: actions/upload-artifact@v4
124267
with:
125-
scan-type: 'container-image'
126-
scan-target: ${{ steps.build-image.outputs.IMAGE }}
127-
fail-build: ${{ inputs.fail-build }}
268+
name: wiz-scan-${{ github.event.repository.name }}
269+
path: |
270+
/tmp/wiz-scan.json
271+
/tmp/wiz-scan-results.txt

0 commit comments

Comments
 (0)