Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Run CVE analysis when DB cache or upstream cdn is live #141

Merged
merged 1 commit into from
Aug 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/dir-scan.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,5 @@ jobs:
asset_prefix: test.insomnia
dir: ${{env.TEST_REPOSITORY}}
upload-sbom-release-assets: true
force_grype_db_update: true ## Explicitly skip cache
fail_build: false
1 change: 1 addition & 0 deletions .github/workflows/docker-image-scan.yml
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ jobs:
asset_prefix: test.kong-gateway-dev-linux-arm64
image: ${{env.IMAGE}}@${{ steps.image_manifest_metadata.outputs.arm64_sha }}
upload-sbom-release-assets: true
force_grype_db_update: true ## Explicitly skip db cache when available

test-download-sbom:
if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository }}
Expand Down
89 changes: 86 additions & 3 deletions security-actions/sca/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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/download-grype@v4.1.1

# 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/scan-action@v4.1.1
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
Expand All @@ -127,7 +206,7 @@ runs:
- name: Vulnerability analysis of SBOM
uses: anchore/scan-action@v4.1.1
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
Expand All @@ -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:
Expand All @@ -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 }}
Expand All @@ -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 }}
Expand All @@ -174,7 +257,7 @@ runs:
# Table format will supress any specified ignore rules
- name: Inspect Vulnerability analysis of SBOM
uses: anchore/scan-action@v4.1.1
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
Expand Down
92 changes: 89 additions & 3 deletions security-actions/scan-docker-image/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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/download-grype@v4.1.1

# 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/scan-action@v4.1.1
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/scan-action@v4.1.1
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
Expand All @@ -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:
Expand All @@ -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 }}
Expand All @@ -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 }}
Expand All @@ -178,7 +264,7 @@ runs:
# Table format will supress any specified ignore rules
- name: Inspect Vulnerability analysis of SBOM
uses: anchore/scan-action@v4.1.1
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
Expand Down
Loading