@@ -229,13 +229,66 @@ upgrade-test: prepare
229229# ***************************************************************************
230230# # Find and scan dependent Docker images for security vulnerabilities
231231# # Options:
232- # # * [saveOutput] optional. Save the output to a xml file. Example: saveOutput=true
232+ # # * [saveOutput] optional. Save the output to a text file. Example: saveOutput=true
233233.PHONY : image-scan
234234image-scan :
235-
236- @echo "=====Scan dependent Docker images in charts/values.yaml" $(if $(saveOutput), | tee -a dep-image-scan.txt,)
237- @for depImage in $(shell grep -E "^\s*\bimage:\s+(.*)" charts/values.yaml | sed 's/image: //g' | sed 's/"//g'); do\
238- echo "= $${depImage}:" $(if $(saveOutput), | tee -a dep-image-scan.txt,) ; \
239- docker run --rm -v /var/run/docker.sock:/var/run/docker.sock anchore/grype:latest --output json $${depImage} | jq -r '[(.matches[] | [.artifact.name, .artifact.version, .vulnerability.id, .vulnerability.severity])] | .[] | @tsv' | sort -k4 | column -t $(if $(saveOutput), | tee -a dep-image-scan.txt,);\
240- echo $(if $(saveOutput), | tee -a dep-image-scan.txt,) ;\
235+ @$(if $(saveOutput ) , > dep-image-scan.txt)
236+ @echo " =====Scan dependent Docker images in charts/values.yaml and charts/charts/haproxy/values.yaml" $(if $(saveOutput ) , | tee -a dep-image-scan.txt,)
237+ set -e; \
238+ scanned_images_tracker_file=" $$ (mktemp)" ; \
239+ trap ' rm -f "$$scanned_images_tracker_file"' EXIT; \
240+ scan_image () { \
241+ img=" $$ 1" ; \
242+ src_file=" $$ 2" ; \
243+ if [ -z " $$ img" ]; then \
244+ echo " Warning: Empty image name provided from $$ src_file. Skipping." $(if $(saveOutput ) , | tee -a dep-image-scan.txt,) ; \
245+ return ; \
246+ fi ; \
247+ if grep -Fxq " $$ img" " $$ scanned_images_tracker_file" ; then \
248+ echo " = $$ img (from $$ src_file) - Already Processed" $(if $(saveOutput ) , | tee -a dep-image-scan.txt,) ; \
249+ return ; \
250+ fi ; \
251+ echo " = Scanning $$ img (from $$ src_file)" $(if $(saveOutput ) , | tee -a dep-image-scan.txt,) ; \
252+ if ! docker pull " $$ img" ; then \
253+ echo " Error: Failed to pull Docker image $$ img. Skipping scan." $(if $(saveOutput ) , | tee -a dep-image-scan.txt,) ; \
254+ echo " $$ img" >> " $$ scanned_images_tracker_file" ; \
255+ return ; \
256+ fi ; \
257+ echo " $$ img" >> " $$ scanned_images_tracker_file" ; \
258+ printf " %s," " $$ {img}" >> helm_image.list ; \
259+ grype_json_output=$$(docker run --rm -v /var/run/docker.sock:/var/run/docker.sock anchore/grype:latest --output json "$$img" 2>/dev/null ) ; \
260+ if [ -z " $$ grype_json_output" ]; then \
261+ echo " Warning: Grype produced no output for $$ img. Command might have failed or image not found/supported by grype." $(if $(saveOutput ) , | tee -a dep-image-scan.txt,) ; \
262+ echo $(if $(saveOutput ) , | tee -a dep-image-scan.txt,) ; \
263+ return ; \
264+ fi ; \
265+ if ! echo " $$ grype_json_output" | jq -e ' .descriptor.name' > /dev/null; then \
266+ echo " Warning: Grype output for $$ img is not valid JSON or image metadata is missing. Output was:" $(if $(saveOutput ) , | tee -a dep-image-scan.txt,) ; \
267+ echo " $$ grype_json_output" $(if $(saveOutput ) , | tee -a dep-image-scan.txt,) ; \
268+ echo $(if $(saveOutput ) , | tee -a dep-image-scan.txt,) ; \
269+ return ; \
270+ fi ; \
271+ summary=$$(echo "$$grype_json_output" | jq -r '([.matches[]?.vulnerability.severity] // [] ) as $$ all_severities | reduce [" Critical" ," High" ," Medium" ," Low" ," Negligible" ," Unknown" ][] as $$ sev ( {Critical:0,High:0,Medium:0,Low:0,Negligible:0,Unknown:0} ; .[$$ sev] = ([$$ all_severities[] | select(. == $$ sev)] | length) ) | " Critical=\(.Critical) High=\(.High) Medium=\(.Medium) Low=\(.Low) Negligible=\(.Negligible) Unknown=\(.Unknown)" ' ); \
272+ echo " Summary: $$ summary" $(if $(saveOutput ) , | tee -a dep-image-scan.txt,) ; \
273+ if echo " $$ grype_json_output" | jq -e ' .matches == null or (.matches | length == 0)' > /dev/null; then \
274+ echo " No vulnerabilities found to tabulate for $$ img." $(if $(saveOutput ) , | tee -a dep-image-scan.txt,) ; \
275+ else \
276+ scan_out_body=$$(echo "$$grype_json_output" | jq -r 'def sevorder: {Critical:0, High:1, Medium:2, Low:3, Negligible:4, Unknown:5}; [.matches[]? | {pkg: .artifact.name, ver: .artifact.version, cve: .vulnerability.id, sev: .vulnerability.severity}] | map(. + {sort_key: sevorder[.sev // "Unknown"]} ) | sort_by(.sort_key) | .[] | [.pkg // " N/A" , .ver // " N/A" , .cve // " N/A" , .sev // " N/A" ] | @tsv' ); \
277+ if [ -n " $$ scan_out_body" ]; then \
278+ (echo -e " Package\tVersion\tCVE\tSeverity" ; echo " $$ scan_out_body" ) | column -t -s $$ ' \t' $(if $(saveOutput ) , | tee -a dep-image-scan.txt,) ; \
279+ else \
280+ echo " No vulnerability details to display for $$ img (though summary reported counts)." $(if $(saveOutput ) , | tee -a dep-image-scan.txt,) ; \
281+ fi ; \
282+ fi ; \
283+ echo $(if $(saveOutput ) , | tee -a dep-image-scan.txt,) ; \
284+ }; \
285+ util_image=$$(grep -A2 'utilContainer:' charts/values.yaml | grep 'image:' | sed 's/.*image:[[:space:]]*//g' | sed 's/"//g' | xargs ) ; \
286+ scan_image " $$ util_image" " charts/values.yaml" ; \
287+ haproxy_image=$$(grep -A2 'image:' charts/charts/haproxy/values.yaml | grep 'repository:' | sed 's/.*repository:[[:space:]]*//g' | sed 's/"//g' | sed 's/#.*//g' | xargs ) ; \
288+ haproxy_tag=$$(grep -A2 'image:' charts/charts/haproxy/values.yaml | grep 'tag:' | sed 's/.*tag:[[:space:]]*//g' | sed 's/"//g' | sed 's/{{.*}}/latest/' | sed 's/#.*//g' | xargs ) ; \
289+ scan_image " $$ haproxy_image:$$ haproxy_tag" " charts/charts/haproxy/values.yaml" ; \
290+ for extra_image in $$ (grep -v ' ^\s*#' charts/charts/haproxy/values.yaml | grep -E ' image:[[:space:]]*[^[:space:]]+' | grep -v ' repository:' | grep -v ' tag:' | sed ' s/.*image:[[:space:]]*//g' | sed ' s/"//g' | sed ' s/#.*//g' | xargs -n1); do \
291+ if [ -n " $$ extra_image" ] && [ " $$ extra_image" != " image:" ]; then \
292+ scan_image " $$ {extra_image}" " charts/charts/haproxy/values.yaml" ; \
293+ fi ; \
241294 done
0 commit comments