@@ -4,20 +4,19 @@ executors:
44 py3 :
55 docker :
66 - image : cimg/python:3.7
7- circleci_medium :
7+ circleci_large :
88 machine :
9- image : ubuntu-1604:201903 -01
10- resource_class : medium
9+ image : ubuntu-1604:202007 -01
10+ resource_class : large
1111 circleci_xlarge :
1212 machine :
13- image : ubuntu-1604:201903 -01
13+ image : ubuntu-1604:202007 -01
1414 resource_class : xlarge
1515
1616orbs :
17- clair : ovotech/clair-scanner @1.6.0
17+ anchore : anchore/anchore-engine @1.8.2
1818
1919jobs :
20-
2120 build_debian_10 :
2221 executor : py3
2322 steps :
@@ -33,11 +32,13 @@ jobs:
3332 command : |
3433 docker save -o workspace_cache/splunk-debian-10.tar splunk-debian-10:latest
3534 docker save -o workspace_cache/uf-debian-10.tar uf-debian-10:latest
35+ docker save -o workspace_cache/base-debian-10.tar base-debian-10:latest
3636 - persist_to_workspace :
3737 root : workspace_cache
3838 paths :
3939 - splunk-debian-10.tar
4040 - uf-debian-10.tar
41+ - base-debian-10.tar
4142
4243 build_redhat_8 :
4344 executor : py3
@@ -54,33 +55,71 @@ jobs:
5455 command : |
5556 docker save -o workspace_cache/splunk-redhat-8.tar splunk-redhat-8:latest
5657 docker save -o workspace_cache/uf-redhat-8.tar uf-redhat-8:latest
58+ docker save -o workspace_cache/base-redhat-8.tar base-redhat-8:latest
5759 - persist_to_workspace :
5860 root : workspace_cache
5961 paths :
6062 - splunk-redhat-8.tar
6163 - uf-redhat-8.tar
64+ - base-redhat-8.tar
6265
63- scan_images :
64- executor : clair/default
66+ scan_images_trivy :
67+ executor : py3
6568 steps :
6669 - checkout
6770 - setup_remote_docker
6871 - attach_workspace :
6972 at : workspace_cache
70- - modified-clair-scan :
71- docker_tar_dir : /root/project/workspace_cache/
72- whitelist : /root/project/clair-whitelist.yml
73+ - run :
74+ name : Install trivy
75+ command : |
76+ VERSION=$(
77+ curl --silent "https://api.github.com/repos/aquasecurity/trivy/releases/latest" | \
78+ grep '"tag_name":' | \
79+ sed -E 's/.*"v([^"]+)".*/\1/'
80+ )
81+ wget https://github.com/aquasecurity/trivy/releases/download/v${VERSION}/trivy_${VERSION}_Linux-64bit.tar.gz
82+ tar zxvf trivy_${VERSION}_Linux-64bit.tar.gz
83+ - run :
84+ name : Scan images
85+ command : |
86+ for image in ./workspace_cache/*.tar; do
87+ [ -e "$image" ] || continue
88+ ./trivy image --exit-code 0 --ignore-unfixed --severity "HIGH,CRITICAL" --no-progress -i "$image"
89+ done
90+
91+ scan_images_anchore :
92+ executor : anchore/anchore_engine
93+ steps :
94+ - checkout
95+ - setup_remote_docker
96+ - attach_workspace :
97+ at : workspace_cache
98+ - run :
99+ name : Load images
100+ command : |
101+ for image in ./workspace_cache/*.tar; do
102+ [ -e "$image" ] || continue
103+ docker load --input "$image"
104+ done
105+ - anchore/analyze_local_image :
106+ image_name : ' splunk-redhat-8 uf-redhat-8 base-redhat-8 splunk-debian-10 uf-debian-10 base-debian-10'
107+ policy_bundle_file_path : .circleci/anchore-policy.json
108+ timeout : ' 600'
109+ - anchore/parse_reports
110+ - store_artifacts :
111+ path : anchore-reports
73112
74113 test_redhat_8_small :
75- executor : circleci_medium
114+ executor : circleci_large
76115 steps :
77116 - checkout
78117 - attach_workspace :
79118 at : workspace_cache
80119 - run :
81120 name : Setup python3
82121 command : |
83- pyenv global 2.7.12 3.5.2
122+ pyenv global 2.7.18 3.7.8
84123 python --version
85124 pip --version
86125 python3 --version
@@ -112,7 +151,7 @@ jobs:
112151 - run :
113152 name : Setup python3
114153 command : |
115- pyenv global 2.7.12 3.5.2
154+ pyenv global 2.7.18 3.7.8
116155 python --version
117156 pip --version
118157 python3 --version
@@ -136,15 +175,15 @@ jobs:
136175 path : test-results
137176
138177 test_debian_10_small :
139- executor : circleci_medium
178+ executor : circleci_large
140179 steps :
141180 - checkout
142181 - attach_workspace :
143182 at : workspace_cache
144183 - run :
145184 name : Setup python3
146185 command : |
147- pyenv global 2.7.12 3.5.2
186+ pyenv global 2.7.18 3.7.8
148187 python --version
149188 pip --version
150189 python3 --version
@@ -179,7 +218,7 @@ jobs:
179218 - run :
180219 name : Setup python3
181220 command : |
182- pyenv global 2.7.12 3.5.2
221+ pyenv global 2.7.18 3.7.8
183222 python --version
184223 pip --version
185224 python3 --version
@@ -208,7 +247,11 @@ workflows:
208247 jobs :
209248 - build_debian_10
210249 - build_redhat_8
211- - scan_images :
250+ - scan_images_trivy :
251+ requires :
252+ - build_debian_10
253+ - build_redhat_8
254+ - scan_images_anchore :
212255 requires :
213256 - build_debian_10
214257 - build_redhat_8
@@ -228,138 +271,3 @@ workflows:
228271 requires :
229272 - build_debian_10
230273 - build_redhat_8
231-
232- commands :
233- modified-clair-scan :
234- description : " Scan an image for vulnerabilities"
235- parameters :
236- image :
237- type : " string"
238- description : " Name of the image to scan"
239- default : " "
240- image_file :
241- type : " string"
242- description : " Path to a file of images to scan"
243- default : " "
244- whitelist :
245- type : " string"
246- description : " Path to a CVE whitelist"
247- default : " "
248- severity_threshold :
249- type : " string"
250- description : " The threshold (equal and above) at which discovered vulnerabilities are reported. May be 'Defcon1', 'Critical', 'High', 'Medium', 'Low', 'Negligible' or 'Unknown'"
251- default : " High"
252- fail_on_discovered_vulnerabilities :
253- type : " boolean"
254- description : " Fail command when vulnerabilities at severity equal to or above the threshold are discovered"
255- default : true
256- fail_on_unsupported_images :
257- type : " boolean"
258- description : " Fail command when image cannot be scanned for vulnerabilities"
259- default : true
260- disable_verbose_console_output :
261- type : " boolean"
262- description : " Disable verbose console output"
263- default : false
264- docker_tar_dir :
265- type : " string"
266- description : " Path of directory that Docker tarballs are stored"
267- default : " /docker-tars"
268- steps :
269- - run :
270- name : " Vulnerability scan"
271- command : |
272- #!/usr/bin/env bash
273-
274- set -xe
275-
276- DOCKER_TAR_DIR="<< parameters.docker_tar_dir >>"
277-
278- if [ -z "<< parameters.image_file >><< parameters.image >>" ] && [ -z "$(ls -A "$DOCKER_TAR_DIR" 2>/dev/null)" ]; then
279- echo "image_file or image parameters or docker tarballs must be present"
280- exit 255
281- fi
282-
283- REPORT_DIR=/clair-reports
284- mkdir $REPORT_DIR
285-
286- DB=$(docker run -p 5432:5432 -d arminc/clair-db:latest)
287- CLAIR=$(docker run -p 6060:6060 --link "$DB":postgres -d arminc/clair-local-scan:latest)
288- CLAIR_SCANNER=$(docker run -v /var/run/docker.sock:/var/run/docker.sock -d ovotech/clair-scanner@sha256:8a4f920b4e7e40dbcec4a6168263d45d3385f2970ee33e5135dd0e3b75d39c75 tail -f /dev/null)
289-
290- clair_ip=$(docker exec -it "$CLAIR" hostname -i | grep -oE '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+')
291- scanner_ip=$(docker exec -it "$CLAIR_SCANNER" hostname -i | grep -oE '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+')
292-
293- if [ -n "<< parameters.whitelist >>" ]; then
294- cat "<< parameters.whitelist >>"
295- docker cp "<< parameters.whitelist >>" "$CLAIR_SCANNER:/whitelist.yml"
296-
297- WHITELIST="-w /whitelist.yml"
298- fi
299-
300- function scan() {
301- local image=$1
302- # replace forward-slashes and colons with underscores
303- munged_image=$(echo "$image" | sed 's/\//_/g' | sed 's/:/_/g')
304- sanitised_image_filename="${munged_image}.json"
305- local ret=0
306- local docker_cmd=(docker exec -it "$CLAIR_SCANNER" clair-scanner \
307- --ip "$scanner_ip" \
308- --clair=http://"$clair_ip":6060 \
309- -t "<< parameters.severity_threshold >>" \
310- --report "/$sanitised_image_filename" \
311- --log "/log.json" $WHITELIST \
312- --reportAll=true \
313- --exit-when-no-features=false \
314- "$image")
315-
316- # if verbose output is disabled, analyse status code for more fine-grained output
317- if [ "<< parameters.disable_verbose_console_output >>" == "true" ];then
318- "${docker_cmd[@]}" > /dev/null 2>&1 || ret=$?
319- else
320- "${docker_cmd[@]}" 2>&1 || ret=$?
321- fi
322- if [ $ret -eq 0 ]; then
323- echo "No unapproved vulnerabilities"
324- elif [ $ret -eq 1 ]; then
325- echo "Unapproved vulnerabilities found"
326- if [ "<< parameters.fail_on_discovered_vulnerabilities >>" == "true" ];then
327- EXIT_STATUS=1
328- fi
329- elif [ $ret -eq 5 ]; then
330- echo "Image was not scanned, not supported."
331- if [ "<< parameters.fail_on_unsupported_images >>" == "true" ];then
332- EXIT_STATUS=1
333- fi
334- else
335- echo "Unknown clair-scanner return code $ret."
336- EXIT_STATUS=1
337- fi
338-
339- docker cp "$CLAIR_SCANNER:/$sanitised_image_filename" "$REPORT_DIR/$sanitised_image_filename" || true
340- }
341-
342- EXIT_STATUS=0
343-
344- for entry in "$DOCKER_TAR_DIR"/*.tar; do
345- [ -e "$entry" ] || continue
346- images=$(docker load -i "$entry" | sed -e 's/Loaded image: //g')
347- for image in $images; do
348- scan "$image"
349- done
350- done
351-
352- if [ -n "<< parameters.image_file >>" ]; then
353- images=$(cat "<< parameters.image_file >>")
354- for image in $images; do
355- scan "$image"
356- done
357- fi
358- if [ -n "<< parameters.image >>" ]; then
359- image="<< parameters.image >>"
360- scan "$image"
361- fi
362-
363- exit $EXIT_STATUS
364- - store_artifacts :
365- path : /clair-reports
0 commit comments