-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Run CVE analysis when DB cache or upstream cdn is live (#141)
Include graceful error / skip cve analysis for grype based on enforcement and db availability Signed-off-by: saisatishkarra <[email protected]> Co-authored-by: saisiatishkarra <[email protected]>
- Loading branch information
1 parent
7a3a7bd
commit a213265
Showing
4 changed files
with
178 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -37,6 +37,14 @@ inputs: | |
options: | ||
- 'true' | ||
- 'false' | ||
force_grype_db_update: | ||
required: false | ||
default: false | ||
description: 'Force to download DB when cache is available and up-to-date' | ||
type: choice | ||
options: | ||
- 'true' | ||
- 'false' | ||
|
||
# Outputs to be consumed by others using this SCA action | ||
outputs: | ||
|
@@ -110,11 +118,82 @@ runs: | |
files: "${{ steps.meta.outputs.sbom_spdx_file }}, ${{ steps.meta.outputs.sbom_cyclonedx_file }}" | ||
fail: true | ||
|
||
- name: Download Grype | ||
uses: anchore/scan-action/[email protected] | ||
|
||
# Check for any existing cache to reuse / update | ||
- name: Cache Grype DB | ||
id: cache_grype_db | ||
if: ${{ inputs.force_grype_db_update != 'true' }} | ||
uses: actions/cache@v4 | ||
env: | ||
cache-name: cache_grype_db | ||
with: | ||
# Grype cache files are stored in `~/.cache/grype/db` on Linux/macOS | ||
path: ~/.cache/grype/db | ||
key: ${{ env.cache-name }} | ||
|
||
# Make a network call to anchore grype CDN. | ||
# This could fail when CDN is flaky for long periods of time. | ||
# Setting timeout for available avoids long stuck grype processes on workflow jobs | ||
|
||
## Edgecase: Grype DB will never update if stale cache is found | ||
- name: Grype DB Check Updates | ||
#if: ${{ steps.cache_grype_db.outputs.cache-hit != 'true' }} | ||
id: grype_db_check_updates | ||
shell: bash | ||
run: | | ||
db_check_status=0 | ||
db_update_status=0 | ||
echo "::group::Grype DB Status Check" | ||
grype db check -vv || db_check_status=$? | ||
if [[ "${db_check_status}" -eq 0 ]]; then | ||
echo "::notice :: Grype DB is already up-to-date" | ||
fi | ||
echo "::endgroup::" | ||
echo "::group:: Update Grype DB" | ||
if [[ "${db_check_status}" -ne 0 ]] || [[ ${FORCE_GRYPE_DB_UPDATE} == "true" ]]; then | ||
grype db update -vv || db_update_status=$? | ||
fi | ||
if [[ "${db_update_status}" -ne 0 ]]; then | ||
GRYPE_DB_UPDATE_MSG="Grype DB updates was not successful. SCA / CVE Grype results might be skipped / unavailable due to DB issues" | ||
if [[ ${FAIL_BUILD} -eq 1 ]]; then | ||
echo "::error ::${GRYPE_DB_UPDATE_MSG}" | ||
exit ${FAIL_BUILD} | ||
elif [[ $FAIL_BUILD -eq 0 ]]; then | ||
echo "::warning ::${GRYPE_DB_UPDATE_MSG}" | ||
echo "GRYPE_DB_UPDATE_STATUS=${db_update_status}" >> $GITHUB_OUTPUT | ||
fi | ||
else | ||
echo "::notice :: Grype DB is updated succesfully" | ||
fi | ||
echo "::endgroup::" | ||
echo "GRYPE_DB_UPDATE_STATUS=${db_update_status}" >> $GITHUB_OUTPUT | ||
env: | ||
FAIL_BUILD: ${{ (steps.meta.outputs.global_enforce_build_failure == 'true' || inputs.fail_build == 'true') && '1' || '0' }} | ||
GRYPE_DB_UPDATE_AVAILABLE_TIMEOUT: 30s # timeout to fetch listing.json to check if db download is needed | ||
GRYPE_DB_UPDATE_DOWNLOAD_TIMEOUT: 600s # timeout for actual db download if needed | ||
FORCE_GRYPE_DB_UPDATE: ${{ inputs.force_grype_db_update }} | ||
|
||
- name: Cache Grype DB updates | ||
if: ${{ steps.grype_db_check_updates.outputs.GRYPE_DB_UPDATE_STATUS == 0 }} | ||
id: cache_grype_db_updates | ||
uses: actions/cache@v4 | ||
env: | ||
cache-name: cache_grype_db # Use generic cache key instead of unique keys for different refs since CVE DB doesn't change frequently | ||
with: | ||
# Grype cache files are stored in `~/.cache/grype/db` on Linux/macOS | ||
path: ~/.cache/grype/db | ||
key: ${{ env.cache-name }} | ||
|
||
# Don't fail during report generation | ||
- name: Vulnerability analysis of SBOM | ||
uses: anchore/[email protected] | ||
id: grype_analysis_sarif | ||
if: ${{ steps.sbom_report.outputs.files_exists == 'true' }} | ||
if: ${{ steps.sbom_report.outputs.files_exists == 'true' && steps.grype_db_check_updates.outputs.GRYPE_DB_UPDATE_STATUS == 0 }} # Run only if DB is available on the runner }} | ||
with: | ||
sbom: ${{ steps.meta.outputs.sbom_spdx_file }} | ||
output-format: sarif | ||
|
@@ -127,7 +206,7 @@ runs: | |
- name: Vulnerability analysis of SBOM | ||
uses: anchore/[email protected] | ||
id: grype_analysis_json | ||
if: ${{ steps.sbom_report.outputs.files_exists == 'true' }} | ||
if: ${{ steps.sbom_report.outputs.files_exists == 'true' && steps.grype_db_check_updates.outputs.GRYPE_DB_UPDATE_STATUS == 0 }} # Run only if DB is available on the runner}} | ||
with: | ||
sbom: ${{ steps.meta.outputs.sbom_spdx_file }} | ||
output-format: json | ||
|
@@ -138,6 +217,7 @@ runs: | |
GRYPE_DB_AUTO_UPDATE: false # Use grype db cache from grype step above | ||
|
||
- name: Check vulnerability analysis report existence | ||
if: ${{ steps.grype_db_check_updates.outputs.GRYPE_DB_UPDATE_STATUS == 0 }} | ||
uses: andstor/file-existence-action@v3 | ||
id: grype_report | ||
with: | ||
|
@@ -148,11 +228,13 @@ runs: | |
# Hack to increase readability of grype artifacts attached to workflows and releases | ||
- name: Rename grype analysis report | ||
shell: bash | ||
if: ${{ steps.grype_db_check_updates.outputs.GRYPE_DB_UPDATE_STATUS == 0 }} # Run only if DB is available on the runner | ||
run: | | ||
mv ${{ steps.grype_analysis_sarif.outputs.sarif }} ${{ steps.meta.outputs.grype_sarif_file }} | ||
mv ${{ steps.grype_analysis_json.outputs.json }} ${{ steps.meta.outputs.grype_json_file }} | ||
- name: Upload grype analysis report | ||
if: ${{ steps.grype_db_check_updates.outputs.GRYPE_DB_UPDATE_STATUS == 0 }} # Run only if DB is available on the runner | ||
uses: actions/upload-artifact@v4 | ||
with: | ||
name: ${{ steps.meta.outputs.grype_sarif_file }} | ||
|
@@ -162,6 +244,7 @@ runs: | |
|
||
# Upload grype cve reports | ||
- name: Upload grype analysis report | ||
if: ${{ steps.grype_db_check_updates.outputs.GRYPE_DB_UPDATE_STATUS == 0 }} # Run only if DB is available on the runner | ||
uses: actions/upload-artifact@v4 | ||
with: | ||
name: ${{ steps.meta.outputs.grype_json_file }} | ||
|
@@ -174,7 +257,7 @@ runs: | |
# Table format will supress any specified ignore rules | ||
- name: Inspect Vulnerability analysis of SBOM | ||
uses: anchore/[email protected] | ||
if: ${{ steps.sbom_report.outputs.files_exists == 'true' }} | ||
if: ${{ steps.sbom_report.outputs.files_exists == 'true' && steps.grype_db_check_updates.outputs.GRYPE_DB_UPDATE_STATUS == 0 }} | ||
with: | ||
sbom: ${{ steps.meta.outputs.sbom_spdx_file }} | ||
output-format: table | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -43,6 +43,14 @@ inputs: | |
options: | ||
- 'true' | ||
- 'false' | ||
force_grype_db_update: | ||
required: false | ||
default: false | ||
description: 'Force to download DB when cache is available and up-to-date' | ||
type: choice | ||
options: | ||
- 'true' | ||
- 'false' | ||
|
||
outputs: | ||
cis-json-report: | ||
|
@@ -113,25 +121,99 @@ runs: | |
with: | ||
files: "${{ steps.meta.outputs.sbom_spdx_file }}, ${{ steps.meta.outputs.sbom_cyclonedx_file }}" | ||
fail: true | ||
|
||
- name: Download Grype | ||
uses: anchore/scan-action/[email protected] | ||
|
||
# Check for any existing cache to reuse / update | ||
- name: Cache Grype DB | ||
if: ${{ inputs.force_grype_db_update != 'true' }} | ||
id: cache_grype_db | ||
uses: actions/cache@v4 | ||
env: | ||
cache-name: cache_grype_db | ||
with: | ||
# Grype cache files are stored in `~/.cache/grype/db` on Linux/macOS | ||
path: ~/.cache/grype/db | ||
key: ${{ env.cache-name }} | ||
|
||
# Make a network call to anchore grype CDN. | ||
# This could fail when CDN is flaky for long periods of time. | ||
# Setting timeout for available avoids long stuck grype processes on workflow jobs | ||
|
||
## Edgecase: Grype DB will never update if stale cache is found | ||
- name: Grype DB Check Updates | ||
#if: ${{ steps.cache_grype_db.outputs.cache-hit != 'true' }} | ||
id: grype_db_check_updates | ||
shell: bash | ||
run: | | ||
db_check_status=0 | ||
db_update_status=0 | ||
echo "::group::Grype DB Status Check" | ||
grype db check -vv || db_check_status=$? | ||
if [[ "${db_check_status}" -eq 0 ]]; then | ||
echo "::notice :: Grype DB is already up-to-date" | ||
fi | ||
echo "::endgroup::" | ||
echo "::group:: Update Grype DB" | ||
if [[ "${db_check_status}" -ne 0 ]] || [[ ${FORCE_GRYPE_DB_UPDATE} == "true" ]]; then | ||
grype db update -vv || db_update_status=$? | ||
fi | ||
if [[ "${db_update_status}" -ne 0 ]]; then | ||
GRYPE_DB_UPDATE_MSG="Grype DB updates was not successful. SCA / CVE Grype results might be skipped / unavailable due to DB issues" | ||
if [[ ${FAIL_BUILD} -eq 1 ]]; then | ||
echo "::error ::${GRYPE_DB_UPDATE_MSG}" | ||
exit ${FAIL_BUILD} | ||
elif [[ $FAIL_BUILD -eq 0 ]]; then | ||
echo "::warning ::${GRYPE_DB_UPDATE_MSG}" | ||
echo "GRYPE_DB_UPDATE_STATUS=${db_update_status}" >> $GITHUB_OUTPUT | ||
fi | ||
else | ||
echo "::notice :: Grype DB is updated succesfully" | ||
fi | ||
echo "::endgroup::" | ||
echo "GRYPE_DB_UPDATE_STATUS=${db_update_status}" >> $GITHUB_OUTPUT | ||
env: | ||
FAIL_BUILD: ${{ (steps.meta.outputs.global_enforce_build_failure == 'true' || inputs.fail_build == 'true') && '1' || '0' }} | ||
GRYPE_DB_UPDATE_AVAILABLE_TIMEOUT: 30s # timeout to fetch listing.json to check if db download is needed | ||
GRYPE_DB_UPDATE_DOWNLOAD_TIMEOUT: 600s # timeout for actual db download if needed | ||
FORCE_GRYPE_DB_UPDATE: ${{ inputs.force_grype_db_update }} | ||
|
||
- name: Cache Grype DB updates | ||
if: ${{ steps.grype_db_check_updates.outputs.GRYPE_DB_UPDATE_STATUS == 0 }} | ||
id: cache_grype_db_updates | ||
uses: actions/cache@v4 | ||
env: | ||
cache-name: cache_grype_db # Use generic cache key instead of unique keys for different refs since CVE DB doesn't change frequently | ||
with: | ||
# Grype cache files are stored in `~/.cache/grype/db` on Linux/macOS | ||
path: ~/.cache/grype/db | ||
key: ${{ env.cache-name }} | ||
|
||
# Grype is invoked first time ever | ||
# Don't fail during report generation | ||
- name: Vulnerability analysis of SBOM | ||
uses: anchore/[email protected] | ||
id: grype_analysis_sarif | ||
if: ${{ steps.sbom_report.outputs.files_exists == 'true' }} | ||
if: ${{ steps.sbom_report.outputs.files_exists == 'true' && steps.grype_db_check_updates.outputs.GRYPE_DB_UPDATE_STATUS == 0 }} | ||
with: | ||
sbom: ${{ steps.meta.outputs.sbom_spdx_file }} | ||
output-format: sarif | ||
fail-build: 'false' | ||
add-cpes-if-none: true | ||
severity-cutoff: ${{ steps.meta.outputs.global_severity_cutoff }} | ||
env: | ||
GRYPE_DB_AUTO_UPDATE: false | ||
|
||
# Don't fail during report generation | ||
# JSON format will report any ignored rules | ||
- name: Vulnerability analysis of SBOM | ||
uses: anchore/[email protected] | ||
id: grype_analysis_json | ||
if: ${{ steps.sbom_report.outputs.files_exists == 'true' }} | ||
if: ${{ steps.sbom_report.outputs.files_exists == 'true' && steps.grype_db_check_updates.outputs.GRYPE_DB_UPDATE_STATUS == 0 }} | ||
with: | ||
sbom: ${{ steps.meta.outputs.sbom_spdx_file }} | ||
output-format: json | ||
|
@@ -142,6 +224,7 @@ runs: | |
GRYPE_DB_AUTO_UPDATE: false # Use grype db cache from grype step above | ||
|
||
- name: Check vulnerability analysis report existence | ||
if: ${{ steps.grype_db_check_updates.outputs.GRYPE_DB_UPDATE_STATUS == 0 }} # Run only if DB is available on the runner | ||
uses: andstor/file-existence-action@v3 | ||
id: grype_report | ||
with: | ||
|
@@ -151,12 +234,14 @@ runs: | |
# Grype CVE Action generates an ./results.sarif or ./results.report and no way to customize output file name | ||
# Hack to increase readability of grype artifacts attached to workflows and releases | ||
- name: Rename grype analysis report | ||
if: ${{ steps.grype_db_check_updates.outputs.GRYPE_DB_UPDATE_STATUS == 0 }} # Run only if DB is available on the runner | ||
shell: bash | ||
run: | | ||
mv ${{ steps.grype_analysis_sarif.outputs.sarif }} ${{ steps.meta.outputs.grype_sarif_file }} | ||
mv ${{ steps.grype_analysis_json.outputs.json }} ${{ steps.meta.outputs.grype_json_file }} | ||
- name: Upload grype analysis report | ||
if: ${{ steps.grype_db_check_updates.outputs.GRYPE_DB_UPDATE_STATUS == 0 }} # Run only if DB is available on the runner | ||
uses: actions/upload-artifact@v4 | ||
with: | ||
name: ${{ steps.meta.outputs.grype_sarif_file }} | ||
|
@@ -166,6 +251,7 @@ runs: | |
|
||
# Upload grype cve reports | ||
- name: Upload grype analysis report | ||
if: ${{ steps.grype_db_check_updates.outputs.GRYPE_DB_UPDATE_STATUS == 0 }} # Run only if DB is available on the runner | ||
uses: actions/upload-artifact@v4 | ||
with: | ||
name: ${{ steps.meta.outputs.grype_json_file }} | ||
|
@@ -178,7 +264,7 @@ runs: | |
# Table format will supress any specified ignore rules | ||
- name: Inspect Vulnerability analysis of SBOM | ||
uses: anchore/[email protected] | ||
if: ${{ steps.sbom_report.outputs.files_exists == 'true' }} | ||
if: ${{ steps.sbom_report.outputs.files_exists == 'true' && steps.grype_db_check_updates.outputs.GRYPE_DB_UPDATE_STATUS == 0 }} | ||
with: | ||
sbom: ${{ steps.meta.outputs.sbom_spdx_file }} | ||
output-format: table | ||
|