Skip to content

Commit 7e1ee2b

Browse files
author
Vitaly Korolev
committed
Update grype scan logic to include dependent images.
1 parent 3e5f56a commit 7e1ee2b

File tree

1 file changed

+60
-9
lines changed

1 file changed

+60
-9
lines changed

makefile

Lines changed: 60 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ e2e-test: prepare
9696
minikube start --driver=docker --kubernetes-version=$(kubernetesVersion) -n=1 --memory=$(minikubeMemory) --cpus=2
9797

9898
@echo "=====Pull $(dockerImage) image for upgrade test"
99-
## This is only needed while we use minikube since the image is not accessible to go at runtime
99+
## This is only needed while we use minikube since the image is not accessible to go at runtime
100100
docker pull $(dockerImage)
101101

102102
# Get env details for debugging
@@ -229,15 +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
234234
image-scan:
235-
236235
@rm -f helm_image.list dep-image-scan.txt
236+
@$(if $(saveOutput), > dep-image-scan.txt)
237237
@echo "=====Scan dependent Docker images in charts/values.yaml" $(if $(saveOutput), | tee -a dep-image-scan.txt,)
238-
@for depImage in $(shell grep -E "^\s*\bimage:\s+(.*)" charts/values.yaml | sed 's/image: //g' | sed 's/"//g'); do\
239-
echo -n "$${depImage}," >> helm_image.list ; \
240-
echo "= $${depImage}:" $(if $(saveOutput), | tee -a dep-image-scan.txt,) ; \
241-
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,);\
242-
echo $(if $(saveOutput), | tee -a dep-image-scan.txt,) ;\
243-
done
238+
set -e; \
239+
scanned_images_tracker_file="$$(mktemp)"; \
240+
trap 'rm -f "$$scanned_images_tracker_file"' EXIT; \
241+
scan_image() { \
242+
img="$$1"; \
243+
src_file="$$2"; \
244+
if [ -z "$$img" ]; then \
245+
echo "Warning: Empty image name provided from $$src_file. Skipping." $(if $(saveOutput), | tee -a dep-image-scan.txt,); \
246+
return; \
247+
fi; \
248+
if grep -Fxq "$$img" "$$scanned_images_tracker_file"; then \
249+
echo "= $$img (from $$src_file) - Already Processed" $(if $(saveOutput), | tee -a dep-image-scan.txt,); \
250+
return; \
251+
fi; \
252+
echo "= Scanning $$img (from $$src_file)" $(if $(saveOutput), | tee -a dep-image-scan.txt,); \
253+
if ! docker pull "$$img"; then \
254+
echo "Error: Failed to pull Docker image $$img. Skipping scan." $(if $(saveOutput), | tee -a dep-image-scan.txt,); \
255+
echo "$$img" >> "$$scanned_images_tracker_file"; \
256+
return; \
257+
fi; \
258+
echo "$$img" >> "$$scanned_images_tracker_file"; \
259+
printf "%s," "$${img}" >> helm_image.list ; \
260+
grype_json_output=$$(docker run --rm -v /var/run/docker.sock:/var/run/docker.sock anchore/grype:latest --output json "$$img" 2>/dev/null); \
261+
if [ -z "$$grype_json_output" ]; then \
262+
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,); \
263+
echo $(if $(saveOutput), | tee -a dep-image-scan.txt,); \
264+
return; \
265+
fi; \
266+
if ! echo "$$grype_json_output" | jq -e '.descriptor.name' > /dev/null; then \
267+
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,); \
268+
echo "$$grype_json_output" $(if $(saveOutput), | tee -a dep-image-scan.txt,); \
269+
echo $(if $(saveOutput), | tee -a dep-image-scan.txt,); \
270+
return; \
271+
fi; \
272+
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)"'); \
273+
echo "Summary: $$summary" $(if $(saveOutput), | tee -a dep-image-scan.txt,); \
274+
if echo "$$grype_json_output" | jq -e '.matches == null or (.matches | length == 0)' > /dev/null; then \
275+
echo "No vulnerabilities found to tabulate for $$img." $(if $(saveOutput), | tee -a dep-image-scan.txt,); \
276+
else \
277+
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'); \
278+
if [ -n "$$scan_out_body" ]; then \
279+
(echo "Package\tVersion\tCVE\tSeverity"; echo "$$scan_out_body") | column -t -s $$'\t' $(if $(saveOutput), | tee -a dep-image-scan.txt,); \
280+
else \
281+
echo "No vulnerability details to display for $$img (though summary reported counts)." $(if $(saveOutput), | tee -a dep-image-scan.txt,); \
282+
fi; \
283+
fi; \
284+
echo $(if $(saveOutput), | tee -a dep-image-scan.txt,); \
285+
}; \
286+
util_image=$$(grep -A2 'utilContainer:' charts/values.yaml | grep 'image:' | sed 's/.*image:[[:space:]]*//g' | sed 's/"//g' | xargs); \
287+
scan_image "$$util_image" "charts/values.yaml"; \
288+
haproxy_image=$$(grep -A 3 '^haproxy:' charts/values.yaml | grep -A 1 '^\s*image:' | grep '^\s*repository:' | sed 's/.*repository:[[:space:]]*//g' | sed 's/"//g' | sed 's/#.*//g' | xargs); \
289+
haproxy_tag=$$(grep -A 4 '^haproxy:' charts/values.yaml | grep -A 2 '^\s*image:' | grep '^\s*tag:' | sed 's/.*tag:[[:space:]]*//g' | sed 's/"//g' | sed 's/{{.*}}/latest/' | sed 's/#.*//g' | xargs); \
290+
scan_image "$$haproxy_image:$$haproxy_tag" "charts/values.yaml";
291+
@# Remove trailing comma from helm_image.list if present
292+
@if [ -f helm_image.list ]; then \
293+
sed -i'' -e 's/,\s*$$//' helm_image.list; \
294+
fi

0 commit comments

Comments
 (0)