Files

159 lines
5.8 KiB
YAML

name: Trivy Security Scan (Template)
on:
workflow_call:
inputs:
images:
description: 'JSON array of images to build and scan. Each entry: {"name": "my-app", "dockerfile": "Dockerfile", "context": "."}'
required: false
type: string
default: '[]'
secrets:
GITHUB_TOKEN:
required: true
jobs:
trivy-scan:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install Trivy
run: |
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin
- name: Trivy filesystem scan
run: |
trivy fs --no-progress --severity HIGH,CRITICAL \
--format json . \
> /tmp/fs-scan.json || true
- name: Build and scan Docker images
run: |
IMAGES='${{ inputs.images }}'
echo "$IMAGES" | jq -c '.[]' | while read -r item; do
NAME=$(echo "$item" | jq -r '.name')
DOCKERFILE=$(echo "$item" | jq -r '.dockerfile')
CONTEXT=$(echo "$item" | jq -r '.context')
echo "Building image: ${NAME}"
docker build -t "${NAME}:latest" -f "${DOCKERFILE}" "${CONTEXT}"
echo "Scanning image: ${NAME}"
trivy image --no-progress --severity HIGH,CRITICAL \
--format json "${NAME}:latest" \
> "/tmp/image-scan-${NAME}.json" || true
done
- name: Generate and publish security report to wiki
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
SCAN_DATE=$(date -u '+%Y-%m-%d %H:%M:%S UTC')
GITEA_URL="${{ github.server_url }}"
REPO="${{ github.repository }}"
COMMIT_SHA="${{ github.sha }}"
COMMIT_SHORT=$(echo "$COMMIT_SHA" | cut -c1-7)
generate_report() {
local json_file="$1"
local title="$2"
if ! jq empty "$json_file" 2>/dev/null; then
echo "## ${title}"
echo ""
echo "Failed to parse scan results."
echo ""
return
fi
local total_vulns
total_vulns=$(jq '[.Results[]? | .Vulnerabilities[]?] | length' "$json_file")
local high_count
high_count=$(jq '[.Results[]? | .Vulnerabilities[]? | select(.Severity == "HIGH")] | length' "$json_file")
local critical_count
critical_count=$(jq '[.Results[]? | .Vulnerabilities[]? | select(.Severity == "CRITICAL")] | length' "$json_file")
echo "## ${title}"
echo ""
echo "| Total | CRITICAL | HIGH |"
echo "|-------|----------|------|"
echo "| ${total_vulns} | ${critical_count} | ${high_count} |"
echo ""
if [ "$total_vulns" -eq 0 ]; then
echo "No vulnerabilities found."
echo ""
return
fi
echo "| Package | Installed | Fixed | Vulnerability | Severity | Title |"
echo "|---------|-----------|-------|---------------|----------|-------|"
jq -r '
[.Results[]? | .Vulnerabilities[]?]
| sort_by(if .Severity == "CRITICAL" then 0 else 1 end)
| .[]
| "| \(.PkgName) | \(.InstalledVersion) | \(.FixedVersion // "-") | \(.VulnerabilityID) | \(.Severity) | \(.Title // "-" | gsub("[\\n\\r]"; " ") | if length > 60 then .[:60] + "..." else . end) |"
' "$json_file"
echo ""
}
{
echo "# Security Scan Report"
echo ""
echo "| | |"
echo "|---|---|"
echo "| **Date** | ${SCAN_DATE} |"
echo "| **Commit** | ${COMMIT_SHORT} |"
echo "| **Branch** | ${{ github.ref_name }} |"
echo "| **Severity Filter** | HIGH, CRITICAL |"
echo ""
echo "---"
echo ""
generate_report /tmp/fs-scan.json "Filesystem Scan"
IMAGES='${{ inputs.images }}'
echo "$IMAGES" | jq -c '.[]' | while read -r item; do
NAME=$(echo "$item" | jq -r '.name')
echo "---"
echo ""
generate_report "/tmp/image-scan-${NAME}.json" "Docker Image - ${NAME}"
done
} > /tmp/wiki-content.md
base64 -w 0 /tmp/wiki-content.md > /tmp/content_b64.txt
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" \
-H "Authorization: token ${GITHUB_TOKEN}" \
"${GITEA_URL}/api/v1/repos/${REPO}/wiki/page/security")
if [ "$HTTP_CODE" = "200" ]; then
jq -n \
--rawfile content /tmp/content_b64.txt \
--arg message "Update security scan report - ${SCAN_DATE}" \
--arg title "security" \
'{content_base64: ($content | rtrimstr("\n")), message: $message, title: $title}' > /tmp/payload.json
curl -s -X PATCH \
-H "Authorization: token ${GITHUB_TOKEN}" \
-H "Content-Type: application/json" \
-d @/tmp/payload.json \
"${GITEA_URL}/api/v1/repos/${REPO}/wiki/page/security"
echo "Wiki page 'security' updated."
else
jq -n \
--rawfile content /tmp/content_b64.txt \
--arg message "Create security scan report - ${SCAN_DATE}" \
--arg title "security" \
'{content_base64: ($content | rtrimstr("\n")), message: $message, title: $title}' > /tmp/payload.json
curl -s -X POST \
-H "Authorization: token ${GITHUB_TOKEN}" \
-H "Content-Type: application/json" \
-d @/tmp/payload.json \
"${GITEA_URL}/api/v1/repos/${REPO}/wiki/new"
echo "Wiki page 'security' created."
fi