11#! /usr/bin/env bash
22set -e
33
4+ AWS_MAX_ATTEMPTS=20
5+ export AWS_MAX_ATTEMPTS
6+
47if [ -z " ${REPOSITORY_NAME} " ]; then
58 echo " REPOSITORY_NAME not set"
69 exit 1
@@ -11,65 +14,125 @@ if [ -z "${IMAGE_TAG}" ]; then
1114 exit 1
1215fi
1316
14- function wait_for_scan() {
15- echo " Giving some time for scan to begin..."
16- sleep 3
17- while [[ $( aws ecr describe-image-scan-findings --repository-name " ${REPOSITORY_NAME} " --image-id imageTag=" ${IMAGE_TAG} " | jq -r .imageScanStatus.status) != " COMPLETE" ]]; do
18- echo " SCAN IS NOT YET COMPLETE..."
19- sleep 3
20- done
21- echo " Final sleep to ensure findings are shown correctly"
22- sleep 60
23- }
24-
25- function check_for_high_critical_vuln() {
26- scan_results=$( aws ecr describe-image-scan-findings --repository-name " ${REPOSITORY_NAME} " --image-id imageTag=" ${IMAGE_TAG} " )
27- high=$( echo " $scan_results " | jq ' .imageScanFindings.enhancedFindings[]? | select(.severity == "HIGH" and .status != "SUPPRESSED")' )
28- critical=$( echo " $scan_results " | jq ' .imageScanFindings.enhancedFindings[]? | select(.severity == "CRITICAL" and .status != "SUPPRESSED")' )
29- }
30-
31- function return_scan_results() {
32- echo " === BEGIN IMAGE SCAN RESULTS ==="
33- echo " $scan_results "
34- echo " === END IMAGE SCAN RESULTS ==="
35- }
36-
37- function return_error() {
38- echo -e " \n**********************************************************"
39- echo " **********************************************************"
40- echo " **********************************************************"
41- echo " ERROR: There are CRITICAL/HIGH vulnerabilities. Stopping build."
42- echo " **********************************************************"
43- echo " **********************************************************"
44- echo " **********************************************************"
45- exit 2
46- }
47-
48- function analyze_scan_results() {
49- if [[ -n " $critical " ]]; then
50- echo " ERROR: There are CRITICAL vulnerabilities. Stopping build."
51-
52- echo " === BEGIN CRITICAL IMAGE SCAN RESULTS ==="
53- echo " $critical "
54- echo " === END CRITICAL IMAGE SCAN RESULTS ==="
55-
56- return_scan_results
57-
58- return_error
59- elif [[ -n " $high " ]]; then
60- echo " ERROR: There are HIGH vulnerabilities. Stopping build."
61-
62- echo " === BEGIN HIGH IMAGE SCAN RESULTS ==="
63- echo " $high "
64- echo " === END HIGH IMAGE SCAN RESULTS ==="
65-
66- return_scan_results
67- return_error
68- else
69- return_scan_results
17+ if [ -z " ${AWS_REGION} " ]; then
18+ echo " AWS_REGION not set"
19+ exit 1
20+ fi
21+
22+ if [ -z " ${ACCOUNT_ID} " ]; then
23+ echo " AWS_REGION not set"
24+ exit 1
25+ fi
26+
27+ IMAGE_DIGEST=$( aws ecr describe-images \
28+ --repository-name " $REPOSITORY_NAME " \
29+ --image-ids imageTag=" $IMAGE_TAG " \
30+ --query ' imageDetails[0].imageDigest' \
31+ --output text)
32+
33+ RESOURCE_ARN=" arn:aws:ecr:${AWS_REGION} :${ACCOUNT_ID} :repository/${REPOSITORY_NAME} /${IMAGE_DIGEST} "
34+
35+ echo " Monitoring scan for ${REPOSITORY_NAME} :${IMAGE_TAG} "
36+ echo " Resource ARN: ${RESOURCE_ARN} "
37+ echo
38+
39+ # Wait for ECR scan to reach COMPLETE
40+ STATUS=" "
41+ echo " Waiting for ECR scan to complete..."
42+ for i in {1..30}; do
43+ echo " Checking scan status. Attempt ${i} "
44+ STATUS=$( aws ecr describe-image-scan-findings \
45+ --repository-name " $REPOSITORY_NAME " \
46+ --image-id imageDigest=" $IMAGE_DIGEST " \
47+ --query ' imageScanStatus.status' \
48+ --output text 2> /dev/null || echo " NONE" )
49+
50+ if [[ " $STATUS " == " COMPLETE" ]]; then
51+ echo " ECR scan completed."
52+ break
53+ fi
54+
55+ if [[ " $STATUS " == " FAILED" ]]; then
56+ echo " Scan failed."
57+ exit 1
58+ fi
59+
60+ echo " SCAN IS NOT YET COMPLETE. Waiting 10 seconds before checking again..."
61+ sleep 10
62+ done
63+
64+ if [[ " $STATUS " != " COMPLETE" ]]; then
65+ echo " Timeout waiting for ECR scan to complete."
66+ exit 1
67+ fi
68+
69+ # Wait for Inspector2 findings to appear & stabilize
70+ # this is in place as scan may show as complete but findings have not yet stabilize
71+ echo
72+ echo " Waiting for Inspector2 findings to stabilize..."
73+
74+ PREV_HASH=" "
75+ for i in {1..12}; do # ~2 minutes max
76+ FINDINGS=$( aws inspector2 list-findings \
77+ --filter-criteria " {
78+ \" resourceId\" : [{\" comparison\" : \" EQUALS\" , \" value\" : \" ${RESOURCE_ARN} \" }],
79+ \" findingStatus\" : [{\" comparison\" : \" EQUALS\" , \" value\" : \" ACTIVE\" }]
80+ }" \
81+ --output json 2> /dev/null || echo " {}" )
82+
83+ CURR_HASH=$( echo " $FINDINGS " | sha256sum)
84+ COUNT=$( echo " $FINDINGS " | jq ' .findings | length' )
85+
86+ if [[ " $COUNT " -gt 0 && " $CURR_HASH " == " $PREV_HASH " ]]; then
87+ echo " Findings stabilized ($COUNT findings)."
88+ break
7089 fi
71- }
7290
73- wait_for_scan
74- check_for_high_critical_vuln
75- analyze_scan_results
91+ PREV_HASH=" $CURR_HASH "
92+ echo " Attempt: ${i} . Still waiting... (${COUNT} findings so far)"
93+ sleep 10
94+ done
95+
96+ # Extract counts and display findings
97+ echo
98+ echo " Final Inspector2 findings with suppressions removed:"
99+ echo
100+
101+ echo " $FINDINGS " | jq ' {
102+ findings: [
103+ .findings[]? | {
104+ severity: .severity,
105+ title: .title,
106+ package: .packageVulnerabilityDetails.vulnerablePackages[0].name,
107+ sourceUrl: .packageVulnerabilityDetails.sourceUrl,
108+ recommendation: (.remediation.recommendation.text // "N/A")
109+ }
110+ ]
111+ }'
112+
113+ echo
114+
115+ # Check for critical/high severity
116+ CRITICAL_COUNT=$( echo " $FINDINGS " | jq ' [.findings[]? | select(.severity=="CRITICAL")] | length' )
117+ HIGH_COUNT=$( echo " $FINDINGS " | jq ' [.findings[]? | select(.severity=="HIGH")] | length' )
118+
119+ if (( CRITICAL_COUNT > 0 || HIGH_COUNT > 0 )) ; then
120+ echo " ${CRITICAL_COUNT} CRITICAL and ${HIGH_COUNT} HIGH vulnerabilities detected!"
121+ echo
122+ echo " Critical/High vulnerabilities:"
123+ echo " $FINDINGS " | jq -r '
124+ .findings[]? |
125+ select(.severity=="CRITICAL" or .severity=="HIGH") |{
126+ severity: .severity,
127+ title: .title,
128+ package: .packageVulnerabilityDetails.vulnerablePackages[0].name,
129+ sourceUrl: .packageVulnerabilityDetails.sourceUrl,
130+ recommendation: (.remediation.recommendation.text // "N/A")
131+ }'
132+ echo
133+ echo " Failing pipeline due to Critical/High vulnerabilities."
134+ exit 2
135+ else
136+ echo " No Critical or High vulnerabilities found."
137+ exit 0
138+ fi
0 commit comments