mirror of
https://github.com/k3s-io/k3s.git
synced 2026-05-28 04:34:19 -04:00
Move to more secure split trivy workflow based on labels, not comments (#12592)
Signed-off-by: Derek Nola <derek.nola@suse.com>
This commit is contained in:
parent
7ab7865530
commit
c3a4c8df9a
3 changed files with 197 additions and 104 deletions
129
.github/workflows/trivy-scan.yml
vendored
Normal file
129
.github/workflows/trivy-scan.yml
vendored
Normal file
|
|
@ -0,0 +1,129 @@
|
|||
name: Trivy Scan Result
|
||||
|
||||
on:
|
||||
workflow_run:
|
||||
workflows: ["Trivy Scan Trigger"]
|
||||
types:
|
||||
- completed
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
trivy_scan:
|
||||
if: github.event.workflow_run.conclusion == 'success'
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write # Required to checkout the PR's head SHA.
|
||||
outputs:
|
||||
pr_number: ${{ steps.pr_context.outputs.pr_number }}
|
||||
|
||||
steps:
|
||||
# For some reason with workflow_run.id, download-artifact does not work.
|
||||
# Github Docs explicity provide an example of using github-script to download artifacts.
|
||||
- name: 'Download artifact'
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
let allArtifacts = await github.rest.actions.listWorkflowRunArtifacts({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
run_id: context.payload.workflow_run.id,
|
||||
});
|
||||
let matchArtifact = allArtifacts.data.artifacts.filter((artifact) => {
|
||||
return artifact.name == "pr-context-for-scan"
|
||||
})[0];
|
||||
let download = await github.rest.actions.downloadArtifact({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
artifact_id: matchArtifact.id,
|
||||
archive_format: 'zip',
|
||||
});
|
||||
const fs = require('fs');
|
||||
fs.writeFileSync('pr-context-for-scan.zip', Buffer.from(download.data));
|
||||
|
||||
- name: 'Unzip artifact to pr-context'
|
||||
run: unzip pr-context-for-scan.zip -d pr-context
|
||||
|
||||
- name: Setup PR context
|
||||
id: pr_context
|
||||
run: |
|
||||
pr_number=$(cat pr-context/pr_number)
|
||||
echo "pr_number=$pr_number" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Load K3s Image
|
||||
run: docker load -i pr-context/k3s.tar
|
||||
|
||||
- name: Download Rancher's VEX Hub report
|
||||
run: curl -fsSO https://raw.githubusercontent.com/rancher/vexhub/refs/heads/main/reports/rancher.openvex.json
|
||||
|
||||
- name: Run Trivy vulnerability scanner
|
||||
uses: aquasecurity/trivy-action@0.31.0
|
||||
with:
|
||||
image-ref: 'rancher/k3s:latest'
|
||||
format: 'table'
|
||||
severity: "HIGH,CRITICAL"
|
||||
output: "trivy-report.txt"
|
||||
env:
|
||||
TRIVY_VEX: rancher.openvex.json
|
||||
TRIVY_SHOW_SUPPRESSED: true
|
||||
|
||||
- name: Upload Trivy Report
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: trivy-report
|
||||
path: trivy-report.txt
|
||||
retention-days: 2
|
||||
if-no-files-found: error
|
||||
|
||||
report_results:
|
||||
needs: trivy_scan
|
||||
if: always() # Run even if the scan fails.
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
pull-requests: write # Required to post comments.
|
||||
|
||||
steps:
|
||||
- name: Download Trivy Report artifact
|
||||
uses: actions/download-artifact@v4
|
||||
if: needs.trivy_scan.result == 'success'
|
||||
with:
|
||||
name: trivy-report
|
||||
path: .
|
||||
|
||||
- name: Add Trivy Report to PR
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
GH_REPO: ${{ github.repository }}
|
||||
SCAN_RESULT: ${{ needs.trivy_scan.result }}
|
||||
PR_NUMBER: ${{ needs.trivy_scan.outputs.pr_number }}
|
||||
run: |
|
||||
if [[ "$SCAN_RESULT" == "failure" ]]; then
|
||||
gh issue comment $PR_NUMBER -b ":x: Trivy scan action failed, check logs :x:"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ -s trivy-report.txt ] && [ -n "$(grep -v '^\s*$' trivy-report.txt)" ]; then
|
||||
echo '```' | cat - trivy-report.txt > temp && mv temp trivy-report.txt
|
||||
echo '```' >> trivy-report.txt
|
||||
gh issue comment $PR_NUMBER -F trivy-report.txt
|
||||
else
|
||||
echo ':star2: No High or Critical CVEs Found :star2:' > trivy-report.txt
|
||||
gh issue comment $PR_NUMBER -F trivy-report.txt
|
||||
fi
|
||||
|
||||
remove_label:
|
||||
if: always() # Run even if the scan fails.
|
||||
needs: trivy_scan
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
pull-requests: write # Required to remove labels from the PR.
|
||||
|
||||
steps:
|
||||
- name: Remove 'scan-with-trivy' label
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
GH_REPO: ${{ github.repository }}
|
||||
PR_NUMBER: ${{ needs.trivy_scan.outputs.pr_number }}
|
||||
run: |
|
||||
gh pr edit $PR_NUMBER --remove-label "scan-with-trivy"
|
||||
68
.github/workflows/trivy-trigger.yml
vendored
Normal file
68
.github/workflows/trivy-trigger.yml
vendored
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
name: Trivy Scan Trigger
|
||||
|
||||
# This workflow is triggered when a pull request is labeled with 'scan-with-trivy'.
|
||||
# This can only be initiated by a user who is a member of the k3s-io organization and has write permissions.
|
||||
# It isolates the built of k3s within a unprivileged enviroment.
|
||||
# The follow up unprivileged workflow will then use the artifact created here to run the scan
|
||||
# and report the results back to the PR.
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [labeled]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
trigger-scan:
|
||||
if: github.event.label.name == 'scan-with-trivy'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Verify actor is a member of k3s-io organization and has write permissions
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const org = 'k3s-io';
|
||||
const actor = context.actor;
|
||||
const { repo, owner } = context.repo;
|
||||
|
||||
try {
|
||||
const result = await github.rest.orgs.checkMembershipForUser({
|
||||
org,
|
||||
username: actor,
|
||||
});
|
||||
} catch (error) {
|
||||
core.setFailed(`User ${actor} is not an public member of the ${org} organization`);
|
||||
}
|
||||
|
||||
const { data: { permission } } = await github.rest.repos.getCollaboratorPermissionLevel({
|
||||
owner,
|
||||
repo,
|
||||
username: actor
|
||||
});
|
||||
|
||||
if (permission !== 'admin' && permission !== 'write') {
|
||||
core.setFailed(`User @${actor} does not have write permission. Scan can only be triggered by repository collaborators with write access.`);
|
||||
}
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Build And Save K3s Image
|
||||
run: |
|
||||
make local-image
|
||||
make tag-image-latest
|
||||
docker save -o k3s.tar rancher/k3s:latest
|
||||
|
||||
- name: Create PR context artifact
|
||||
run: |
|
||||
mkdir -p pr-context
|
||||
echo "${{ github.event.pull_request.number }}" > pr-context/pr_number
|
||||
mv k3s.tar pr-context/k3s.tar
|
||||
|
||||
- name: Upload PR context artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: pr-context-for-scan
|
||||
path: pr-context/
|
||||
retention-days: 1
|
||||
104
.github/workflows/trivy.yaml
vendored
104
.github/workflows/trivy.yaml
vendored
|
|
@ -1,104 +0,0 @@
|
|||
name: PR Comment Triggered Trivy Scan
|
||||
|
||||
on:
|
||||
issue_comment:
|
||||
types: [created]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
trivy_scan:
|
||||
if: github.event.issue.pull_request && github.event.comment.body == '/trivy'
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
pull-requests: read
|
||||
steps:
|
||||
- name: Check if comment author is a member of k3s-dev team
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
# Catch 404 errors if user is not a member of the organization
|
||||
# 302 is expected as the GHA is not a member of the organization
|
||||
# Users must be set their membership to public for this to work
|
||||
# https://github.com/orgs/k3s-io/people
|
||||
script: |
|
||||
const org = context.repo.owner;
|
||||
const username = context.payload.comment.user.login;
|
||||
try {
|
||||
const result = await github.rest.orgs.checkMembershipForUser({
|
||||
org,
|
||||
username,
|
||||
});
|
||||
} catch (error) {
|
||||
core.setFailed(`User ${username} is not an public member of the ${org} organization`);
|
||||
}
|
||||
- name: Checkout PR code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: refs/pull/${{ github.event.issue.number }}/head
|
||||
|
||||
- name: Build K3s Image
|
||||
run: |
|
||||
make local-image
|
||||
make tag-image-latest
|
||||
|
||||
- name: Download Rancher's VEX Hub report
|
||||
run: curl -fsSO https://raw.githubusercontent.com/rancher/vexhub/refs/heads/main/reports/rancher.openvex.json
|
||||
|
||||
- name: Run Trivy vulnerability scanner
|
||||
uses: aquasecurity/trivy-action@0.31.0
|
||||
with:
|
||||
image-ref: 'rancher/k3s:latest'
|
||||
format: 'table'
|
||||
severity: "HIGH,CRITICAL"
|
||||
output: "trivy-report.txt"
|
||||
env:
|
||||
TRIVY_VEX: rancher.openvex.json
|
||||
TRIVY_SHOW_SUPPRESSED: true
|
||||
|
||||
- name: Upload Trivy Report
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: trivy-report
|
||||
path: trivy-report.txt
|
||||
retention-days: 2
|
||||
if-no-files-found: error
|
||||
|
||||
trivy_report:
|
||||
needs: trivy_scan
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
pull-requests: write
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
GH_REPO: ${{ github.repository }}
|
||||
steps:
|
||||
- name: Download Trivy Report
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: trivy-report
|
||||
|
||||
- name: Add Trivy Report to PR
|
||||
run: |
|
||||
if [ -s trivy-report.txt ] && [ -n "$(grep -v '^\s*$' trivy-report.txt)" ]; then
|
||||
echo '```' | cat - trivy-report.txt > temp && mv temp trivy-report.txt
|
||||
echo '```' >> trivy-report.txt
|
||||
gh issue comment ${{ github.event.issue.number }} -F trivy-report.txt
|
||||
else
|
||||
echo ':star2: No High or Critical CVEs Found :star2:' > trivy-report.txt
|
||||
gh issue comment ${{ github.event.issue.number }} -F trivy-report.txt
|
||||
fi
|
||||
|
||||
trivy_failure:
|
||||
needs: trivy_scan
|
||||
runs-on: ubuntu-latest
|
||||
if: always() && needs.trivy_scan.result == 'failure'
|
||||
permissions:
|
||||
pull-requests: write
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
GH_REPO: ${{ github.repository }}
|
||||
steps:
|
||||
- name: Report Failure
|
||||
run: |
|
||||
gh issue comment ${{ github.event.issue.number }} -b ":x: Trivy scan action failed, check logs :x:"
|
||||
Loading…
Reference in a new issue