|
1 | 1 | ---
|
2 |
| -name: Trivy Security Scan with Security Hub Integration |
| 2 | +# This is a basic workflow to help you get started with Actions |
3 | 3 |
|
4 |
| -'on': |
| 4 | +name: Trivy Scan |
| 5 | + |
| 6 | +# Controls when the action will run. Triggers the workflow on pull request |
| 7 | +# events but only for the develop branch |
| 8 | +on: # yamllint disable-line rule:truthy |
5 | 9 | push:
|
6 |
| - branches: [main] |
| 10 | + branches: |
| 11 | + - "**" # matches every branch |
| 12 | + - "!main" # excludes main |
7 | 13 | pull_request:
|
8 |
| - branches: [main] |
9 |
| -permissions: |
10 |
| - security-events: write |
11 |
| - contents: read |
12 |
| - id-token: write |
13 |
| - actions: read |
| 14 | + branches: |
| 15 | + - main |
14 | 16 |
|
| 17 | +# A workflow run is made up of one or more jobs that can run sequentially or in parallel |
15 | 18 | jobs:
|
16 |
| - security-scan: |
17 |
| - runs-on: ubuntu-latest |
18 |
| - env: |
19 |
| - AWS_REGION: ${{ secrets.AWS_REGION }} |
20 |
| - AWS_ACCOUNT_ID: ${{ secrets.AWS_ACCOUNT_ID }} |
21 |
| - ECR_REPO: ${{ secrets.ECR_REPO }} |
22 |
| - IMAGE_TAG: ${{ github.sha }} |
| 19 | + # This workflow contains a single job called "trivy" |
| 20 | + trivy: |
| 21 | + # The type of runner that the job will run on |
| 22 | + runs-on: [self-hosted, linux, codebuild] |
23 | 23 |
|
| 24 | + # Steps represent a sequence of tasks that will be executed as part of the job |
24 | 25 | steps:
|
25 |
| - - name: Checkout code |
26 |
| - uses: actions/checkout@v4 |
| 26 | + # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it |
| 27 | + - uses: actions/checkout@v3 |
27 | 28 |
|
28 |
| - - name: Set up AWS credentials |
29 |
| - uses: aws-actions/configure-aws-credentials@v4.0.2 |
| 29 | + - name: Run Trivy vulnerability scanner in repo mode |
| 30 | + uses: aquasecurity/trivy-action@0.28.0 |
30 | 31 | with:
|
31 |
| - aws-region: ${{ secrets.AWS_REGION }} |
32 |
| - role-to-assume: ${{ secrets.AWS_ROLE_ARN }} |
33 |
| - role-session-name: GitHubActions |
34 |
| - |
35 |
| - - name: Verify AWS credentials |
36 |
| - run: | |
37 |
| - aws sts get-caller-identity |
38 |
| - echo "AWS credentials configured successfully" |
39 |
| -
|
40 |
| - - name: Build Docker image |
41 |
| - run: docker build -t test-image:latest . |
42 |
| - |
43 |
| - - name: Run Trivy vulnerability scanner |
44 |
| - uses: aquasecurity/trivy-action@0.30.0 |
45 |
| - continue-on-error: true |
46 |
| - with: |
47 |
| - image-ref: test-image:latest |
48 |
| - severity: HIGH,CRITICAL |
49 |
| - exit-code: 1 |
50 |
| - format: sarif |
51 |
| - output: trivy-results.sarif |
52 |
| - |
53 |
| - - name: Generate Security Hub findings |
54 |
| - if: always() |
55 |
| - run: | |
56 |
| - # Scan with JSON format first to get structured data |
57 |
| - trivy image \ |
58 |
| - --severity LOW,MEDIUM,HIGH,CRITICAL \ |
59 |
| - --exit-code 0 \ |
60 |
| - --format json \ |
61 |
| - -o scan-results.json \ |
62 |
| - test-image:latest |
63 |
| -
|
64 |
| - # Create ASFF findings using jq |
65 |
| - cat scan-results.json | jq -r --arg account "$AWS_ACCOUNT_ID" --arg region "$AWS_REGION" ' |
66 |
| - [ |
67 |
| - .Results[]? | select(.Vulnerabilities) | .Vulnerabilities[] | { |
68 |
| - "SchemaVersion": "2018-10-08", |
69 |
| - "Id": ("trivy-" + .VulnerabilityID + "-" + (.PkgName // "unknown")), |
70 |
| - "ProductArn": ("arn:aws:securityhub:" + $region + "::product/aquasecurity/aquasecurity"), |
71 |
| - "GeneratorId": "Trivy", |
72 |
| - "AwsAccountId": $account, |
73 |
| - "Types": ["Software and Configuration Checks/Vulnerabilities/CVE"], |
74 |
| - "CreatedAt": (now | strftime("%Y-%m-%dT%H:%M:%SZ")), |
75 |
| - "UpdatedAt": (now | strftime("%Y-%m-%dT%H:%M:%SZ")), |
76 |
| - "Severity": { |
77 |
| - "Label": .Severity |
78 |
| - }, |
79 |
| - "Title": ("Trivy found " + .VulnerabilityID + " in " + (.PkgName // "unknown package")), |
80 |
| - "Description": (.Description // "No description available"), |
81 |
| - "Remediation": { |
82 |
| - "Recommendation": { |
83 |
| - "Text": "Update the package to fix the vulnerability", |
84 |
| - "Url": ("https://avd.aquasec.com/nvd/" + .VulnerabilityID) |
85 |
| - } |
86 |
| - }, |
87 |
| - "ProductFields": { |
88 |
| - "Product Name": "Trivy" |
89 |
| - }, |
90 |
| - "Resources": [{ |
91 |
| - "Type": "Container", |
92 |
| - "Id": "test-image:latest", |
93 |
| - "Partition": "aws", |
94 |
| - "Region": $region, |
95 |
| - "Details": { |
96 |
| - "Container": { |
97 |
| - "ImageName": "test-image:latest" |
98 |
| - }, |
99 |
| - "Other": { |
100 |
| - "CVE ID": .VulnerabilityID, |
101 |
| - "Package Name": (.PkgName // "unknown"), |
102 |
| - "Installed Version": (.InstalledVersion // "unknown"), |
103 |
| - "Fixed Version": (.FixedVersion // "Not available") |
104 |
| - } |
105 |
| - } |
106 |
| - }], |
107 |
| - "RecordState": "ACTIVE" |
108 |
| - } |
109 |
| - ] |
110 |
| - ' > findings.json |
111 |
| - env: |
112 |
| - AWS_ACCOUNT_ID: ${{ secrets.AWS_ACCOUNT_ID }} |
113 |
| - AWS_REGION: ${{ secrets.AWS_REGION }} |
114 |
| - |
115 |
| - - name: Push findings to Security Hub |
116 |
| - if: always() |
117 |
| - continue-on-error: true |
118 |
| - run: | |
119 |
| - # Check if Security Hub is enabled |
120 |
| - if ! aws securityhub describe-hub --region ${{ secrets.AWS_REGION }} >/dev/null 2>&1; then |
121 |
| - echo "⚠️ Security Hub is not enabled in region ${{ secrets.AWS_REGION }}" |
122 |
| - echo "Enable it with: aws securityhub enable-security-hub --region ${{ secrets.AWS_REGION }}" |
123 |
| - exit 0 |
124 |
| - fi |
125 |
| -
|
126 |
| - # Check if findings file exists and has content |
127 |
| - if [ -s findings.json ]; then |
128 |
| - echo "✅ Findings file generated successfully" |
129 |
| -
|
130 |
| - # Debug: Show findings count |
131 |
| - FINDINGS_COUNT=$(jq length findings.json) |
132 |
| - echo "📊 Found $FINDINGS_COUNT findings to import" |
133 |
| -
|
134 |
| - if [ "$FINDINGS_COUNT" -gt 0 ]; then |
135 |
| - # Import findings to Security Hub |
136 |
| - aws securityhub batch-import-findings \ |
137 |
| - --region ${{ secrets.AWS_REGION }} \ |
138 |
| - --findings file://findings.json |
139 |
| -
|
140 |
| - echo "✅ $FINDINGS_COUNT findings imported to Security Hub successfully" |
141 |
| - else |
142 |
| - echo "ℹ️ No findings to import" |
143 |
| - fi |
144 |
| - else |
145 |
| - echo "❌ Findings file is empty or does not exist" |
146 |
| - fi |
147 |
| -
|
148 |
| - - name: Display Security Hub findings summary |
149 |
| - if: always() |
150 |
| - run: | |
151 |
| - echo "📊 Security Hub Integration Summary:" |
152 |
| - echo "Region: ${{ secrets.AWS_REGION }}" |
153 |
| - echo "Account ID: ${{ secrets.AWS_ACCOUNT_ID }}" |
154 |
| - echo "Image scanned: test-image:latest" |
155 |
| -
|
156 |
| - if [ -f findings.json ]; then |
157 |
| - FINDINGS_COUNT=$(jq length findings.json 2>/dev/null || echo "0") |
158 |
| - echo "✅ Findings file generated successfully" |
159 |
| - echo "📄 Total findings: $FINDINGS_COUNT" |
160 |
| - echo "📄 File size: $(wc -c < findings.json) bytes" |
161 |
| - else |
162 |
| - echo "❌ Findings file not found" |
163 |
| - fi |
| 32 | + scan-type: "fs" |
| 33 | + scan-ref: "${{ github.workspace }}" |
| 34 | + trivy-config: "${{ github.workspace }}/trivy.yaml" |
0 commit comments