Add github workflow to run govoulncheck on all branches with supported OpenTofu versions (#2636)

Signed-off-by: yottta <andrei.ciobanu@opentofu.org>
Signed-off-by: Andrei Ciobanu <andrei.ciobanu@opentofu.org>
This commit is contained in:
Andrei Ciobanu 2025-05-14 18:26:22 +03:00 committed by GitHub
parent 2ef59e2299
commit 8396d0459c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 170 additions and 0 deletions

72
.github/scripts/govulncheck-submit-issues.sh vendored Executable file
View file

@ -0,0 +1,72 @@
#!/usr/bin/env bash
# SPDX-License-Identifier: MPL-2.0
# This requires a "results" directory containing files with the name of the branch that the results are associated with.
# The files inside need to contain just a one liner JSON array like: ["vulnKey1","vulnKey2",...].
# Eg: `$ tail results/*`
# ==> results/main <==
# []
#
# ==> results/v1.7 <==
# ["GO-2024-2947","GO-2024-2948","GO-2025-3447","GO-2025-3487","GO-2025-3503"]
#
# ==> results/v1.8 <==
# ["GO-2025-3447","GO-2025-3487","GO-2025-3503"]
#
# ==> results/v1.9 <==
# ["GO-2025-3447","GO-2025-3487","GO-2025-3503"]
github_run_url="${1}"
# This first part converts the results of type ["vulnKey1","vulnKey2",...] from the files inside the "results" directory
# to {"vulnKey1": ["main", "v1.7", ...], "vulnKey2": ["main", "v1.7", ...]}
# Start the script with an empty json object
vuln_to_versions="{}"
cd results
for version in *; do
while IFS= read -r vuln;
do
[[ -z "${vuln}" ]] && continue
# Actions from this like:
# * is giving the shell var for the vulnerability key to jq (--arg vl "${vuln}")
# * is giving the shell var that contains the scanned version to jq (--arg vers "${version}"
# * is getting from vuln_to_versions the key name that needs to be a vulnerability key and assigns to its array the currently proceesed version ('.[$vl] = .[$vl] + [$vers]')
# * this is generating outputs like {"vulnKey": ["version1", "version2"]}. Eg: {"GO-2024-2947":["v1.7"]}
# * in the end overwrites the content of vuln_to_versions with the newly generated content
vuln_to_versions="$(echo "${vuln_to_versions}" | jq -c --arg vl "${vuln}" --arg vers "${version}" '.[$vl] = .[$vl] + [$vers]')"
done <<< "$(cat $version | jq -r '.[]')" # This one is exploding a json array into multiple lines
done
# This second part is just using the ".key" that is the vulnerability key and ".value" that is the list of affected version(s)
# to generate the commands to create GitHub issues.
while IFS= read -r vuln;
do
vuln_key="$(echo ${vuln} | jq -r '.key')"
affected_versions="$(echo ${vuln} | jq -r '.value[]' | xargs)"
ticket_title="${vuln_key} reported"
reported_issues="$(gh issue -R opentofu/opentofu list --search "\"${ticket_title}\"" --json number)"
no_of_issues="$(echo ${reported_issues} | jq -r '. | length')"
reported_issues="$(echo $reported_issues| jq -r '.[] | .number' | xargs)"
[[ ${no_of_issues} -ge 1 ]] && echo "Vulnerabilties found but already reported for ${vuln_key} in: ${reported_issues}" && continue
echo "--> Creating issue <--"
echo "This vulnerability might affect the following versions: ${affected_versions}" > ticket_content
echo "" >> ticket_content
echo "*Vulnerability info:* https://pkg.go.dev/vuln/${vuln_key}" >> ticket_content
echo "*Pipeline run:* ${github_run_url}" >> ticket_content
echo "Create issue..."
echo "Title: ${ticket_title}"
echo "Content:"
cat ticket_content
gh issue create --repo opentofu/opentofu --label "govulncheck" --title "${ticket_title}" --body-file ticket_content
echo "--> Creating issue (END) <--"
done <<< "$(echo "$vuln_to_versions" | jq -c 'to_entries[]')"
# ^ This is converting a json object that looks something like:
# {"GO-2024-2947":["v1.7"],"GO-2024-2948":["v1.7"],...}
# to a list of objects, each on its own line
# {"key":"GO-2024-2947","value":["v1.7"]}
# {"key":"GO-2024-2948","value":["v1.7"]}
# ...

93
.github/workflows/govulncheck.yml vendored Normal file
View file

@ -0,0 +1,93 @@
# This workflow is meant to run govulncheck on all the branches
# that are containing a maintained version of OpenTofu.
# For more considerations about this, check this PR: https://github.com/opentofu/opentofu/pull/2600
#
# This will try to create an issue for each vulnerability key that is found.
# If an issue for it already exists, it will skip creating it.
#
# This is meant to run _only_ from the main branch, on a scheduled manner.
# All the other branches will be scanned directly by the run triggered from the main branch.
name: Govulncheck
on:
schedule:
- cron: '00 15 * * MON'
workflow_dispatch: {}
jobs:
govulncheck:
name: Run govulncheck for ${{ matrix.branch }}
runs-on: ubuntu-latest
strategy:
matrix:
include:
- { branch: main }
- { branch: v1.9 }
- { branch: v1.8 }
- { branch: v1.7 }
fail-fast: false
steps:
- name: Checkout branch to be scanned
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
ref: ${{matrix.branch}}
- name: Determine Go version
id: go
uses: ./.github/actions/go-version
- name: Install Go toolchain
uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0
with:
go-version: ${{steps.go.outputs.version}}
- name: Install govulncheck
run: go install golang.org/x/vuln/cmd/govulncheck@d1f380186385b4f64e00313f31743df8e4b89a77 # v1.1.4
shell: bash
- name: Run and report govulncheck findings
run: |
govulncheck -format json ./... | tee results
# This is parsing the output of govulncheck by:
# * extracting only the findings that are affecting the current branch (.finding | select(.trace | length > 1))
# * getting only the vulnerability key out of the objects (.osv)
# * sorting and deduplicating the generated vulnerability keys (sort -u)
# * compacting the result into a json array like ["vulnKey1", "vulnKey2", ...] (jq -cs '.')
# * saving the results into a file which name is the version that we are scanning like "v1.8" (> "${{matrix.branch}}")
cat results | jq '.finding | select(.trace | length > 1) | .osv' | sort -u | jq -cs '.' > "${{matrix.branch}}"
shell: bash
# Upload the artifact to make it available to the next job.
# The artifact will be named as the branch name that we are scanning ("main" or "v1.7"...)
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: ${{matrix.branch}}-results
path: ${{matrix.branch}}
create-issues:
name: Compile results and create GH issues
needs:
- govulncheck
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
env:
GH_TOKEN: ${{ github.token }}
steps:
- name: Checkout branch for running the script
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
sparse-checkout: |
.github
# By providing the path where to download the artifacts and "merge-multiple: true", the downloader
# will gather all the files generated in the job(s) above into a single directory flattening the file tree.
# Eg: Instead of writing the results into "results/main-results/main" it will write the results into "results/main"
- name: Download vulns results
uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4
with:
path: results
merge-multiple: true
- name: Run and report govulncheck findings
run: .github/scripts/govulncheck-submit-issues.sh "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
shell: bash

View file

@ -245,6 +245,11 @@ git submodule update
<details>
<summary>
## Updating govulncheck github workflow (only for stable releases)
In [.github/workflows/govulncheck.yml](.github/workflows/govulncheck.yml), there is a matrix with the actively
maintained versions of OpenTofu.
When the new branch for the stable version is created, update the matrix above by adding the new branch and removing the deprecated version.
### Alpha (`X.Y.Z-alphaW`), Beta (`X.Y.Z-betaW`) and Release Candidate (`X.Y.Z-rcW`)
</summary>