-
Notifications
You must be signed in to change notification settings - Fork 3
240 lines (216 loc) · 10.1 KB
/
run-security-scans.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
name: Security Scans
on:
workflow_call:
inputs:
# The image reference generated by a build job.
image_url:
description: "An image_url of the form registry/repository:tag."
required: false
type: string
auth_project_number:
description: "The GCP Project Number used for authentication. A 12-digit number used as a unique identifier for the project. Used to find workload identity pool."
required: true
type: string
workload_identity_provider_override:
description: "The ID of the provider to use for authentication. Only used for overriding the default workload identity provider based on project number. It should be in the format of `projects/{{project}}/locations/global/workloadIdentityPools/{{workload_identity_pool_id}}/providers/{{workload_identity_pool_provider_id}}`"
required: false
type: string
service_account:
description: "The GCP service account connected to the identity pool that will be used by Terraform"
required: true
type: string
trivy:
description: "A boolean which determines whether or not Trivy vulnerability scan will be run. Defaults to true"
required: false
default: true
type: boolean
tfsec:
description: "A boolean which determines whether or not TFSec security scan will be run. Defaults to true"
required: false
default: true
type: boolean
allow_severity_level:
description: 'A string which determines the highest level of severity the security scans can find while still succeeding workflows. Only "medium", "high" and "critical" values are allowed. Note that these values are case sensitive.'
required: false
default: medium
type: string
env:
WORKLOAD_IDENTITY_PROVIDER_OVERRIDE: ${{ inputs.workload_identity_provider_override }}
AUTH_PROJECT_NUMBER: ${{ inputs.auth_project_number }}
SERVICE_ACCOUNT: ${{ inputs.service_account }}
IMAGE_URL: ${{ inputs.image_url }}
REGISTRY: ghcr.io
BRANCH: ${{ github.ref_name }}
HEAD_REF: ${{ github.head_ref }}
EVENT_NAME: ${{ github.event_name }}
ALLOW_SEVERITY_LEVEL: ${{ inputs.allow_severity_level }}
jobs:
setup-env:
runs-on: ubuntu-latest
outputs:
WORKLOAD_IDENTITY_PROVIDER: ${{ steps.set-output.outputs.WORKLOAD_IDENTITY_PROVIDER }}
steps:
- name: Deprecation Warning
run: |
echo "::warning::DEPRECATED: THIS WORKFLOW IS DEPRECATED AND WILL NOT RECEIVE FURTHER UPDATES. PLEASE CHECK OUT [Pharos](https://github.com/kartverket/pharos/) FOR SECURITY SCANS"
- name: Set vars
id: set-output
run: |
PRODUCT_NAME=$(echo $SERVICE_ACCOUNT | sed 's/-deploy.*//')
DEFAULT_WORKLOAD_IDENTITY="projects/$AUTH_PROJECT_NUMBER/locations/global/workloadIdentityPools/$PRODUCT_NAME-deploy-pool/providers/github-provider"
OVERRIDE=$WORKLOAD_IDENTITY_PROVIDER_OVERRIDE
PROVIDER=${OVERRIDE:-$DEFAULT_WORKLOAD_IDENTITY}
echo "WORKLOAD_IDENTITY_PROVIDER=$PROVIDER" >> $GITHUB_OUTPUT
- name: Check severity level
if: inputs.allow_severity_level != 'medium' && inputs.allow_severity_level != 'high' && inputs.allow_severity_level != 'critical'
run: |
echo "Error: The input 'allow_severity_level' was not one of the allowed strings, 'high', 'critical' or 'medium'. Found: "$ALLOW_SEVERITY_LEVEL".";
exit 1;
tfsec:
name: TFSec
if: inputs.tfsec == true && github.event.pull_request.draft == false
needs: [setup-env]
runs-on: ubuntu-latest
permissions:
contents: read
actions: read
security-events: write
# Use the Bash shell regardless whether the GitHub Actions runner is ubuntu-latest, macos-latest, or windows-latest
defaults:
run:
shell: bash
steps:
# Checkout the repository to the GitHub Actions runner
- name: Checkout repository
uses: actions/checkout@v4
- name: Run tfsec
id: tfsec
uses: aquasecurity/tfsec-sarif-action@21ded20e8ca120cd9d3d6ab04ef746477542a608
with:
sarif_file: tfsec.sarif
- name: Upload SARIF file
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: tfsec.sarif
trivy:
name: Trivy
if: inputs.trivy == true && inputs.image_url != '' && github.event.pull_request.draft == false
needs: [setup-env]
runs-on: ubuntu-latest
concurrency: ${{ inputs.image_url }}
# Use the Bash shell regardless whether the GitHub Actions runner is ubuntu-latest, macos-latest, or windows-latest
defaults:
run:
shell: bash
permissions:
contents: read
packages: write
# required for authentication to GCP
id-token: write
actions: read
security-events: write
env:
WORKLOAD_IDENTITY_PROVIDER: ${{ needs.setup-env.outputs.WORKLOAD_IDENTITY_PROVIDER }}
steps:
# Checkout the repository to the GitHub Actions runner
- name: Checkout code
uses: actions/checkout@v4
- name: Log into registry
uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Docker pull image
run: docker pull $IMAGE_URL
- name: Run Trivy vulnerability scanner
uses: aquasecurity/trivy-action@915b19bbe73b92a6cf82a1bc12b087c9a19a5fe2
with:
image-ref: ${{ env.IMAGE_URL }}
format: sarif
output: trivy-results.sarif
severity: UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL
timeout: 15m
- name: Upload Trivy scan results to GitHub Security tab
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: trivy-results.sarif
check-github-security:
name: Check Github Security Code Scanning
needs: [tfsec, trivy, setup-env]
# Always runs after tfsec and trivy, but not if they failed or got cancelled
if: |
always() &&
!contains(needs.*.result, 'failure') &&
!contains(needs.*.result, 'cancelled')
runs-on: ubuntu-latest
# Use the Bash shell regardless whether the GitHub Actions runner is ubuntu-latest, macos-latest, or windows-latest
defaults:
run:
shell: bash
env:
WORKLOAD_IDENTITY_PROVIDER: ${{ needs.setup-env.outputs.WORKLOAD_IDENTITY_PROVIDER }}
steps:
# Checkout the repository to the GitHub Actions runner
- name: Checkout repository
uses: actions/checkout@v4
- name: Set high and critical severity outputs
id: severity_check_outputs
run: |
content_header="Accept: application/vnd.github+json"
auth_header="Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}"
base_url="https://api.github.com/repos/${{ github.repository }}/code-scanning/alerts?ref=${{ github.ref }}&state=open"
result_severity_check_high=$(curl -s -H "$content_header" -H "$auth_header" "${base_url}&severity=high")
result_severity_check_critical=$(curl -s -H "$content_header" -H "$auth_header" "${base_url}&severity=critical")
result_severity_check_error=$(curl -s -H "$content_header" -H "$auth_header" "${base_url}&severity=error")
is_high_vuln_present=$([[ "$result_severity_check_high" =~ [a-zA-Z] ]] && echo "true" || echo "false")
is_critical_vuln_present=$([[ "$result_severity_check_critical" =~ [a-zA-Z] || "$result_severity_check_error" =~ [a-zA-Z] ]] && echo "true" || echo "false")
echo "is_high_vuln_present=$is_high_vuln_present" >> $GITHUB_OUTPUT
echo "is_critical_vuln_present=$is_critical_vuln_present" >> $GITHUB_OUTPUT
- name: Succeed or fail based on severity
id: severity_check
run: |
pr_number=$( echo ${{ env.BRANCH }} | sed 's/\/.*//');
is_high_vuln_present=${{ steps.severity_check_outputs.outputs.is_high_vuln_present }}
is_critical_vuln_present=${{ steps.severity_check_outputs.outputs.is_critical_vuln_present }}
error_start_message="Error: Vulnerabilities were found of level"
error_end_message="Go to the Code Scanning section of the GitHub Security tab to review these vulnerabilities."
error_search_pr_message="Search for is:open pr:"$pr_number" to find PR related vulnerabilities."
if [[ $is_high_vuln_present == 'false' && $is_critical_vuln_present == 'false' ]]
then
echo "Success! No high or critical code scanning alerts.";
exit 0;
fi
if [[ ${{ env.ALLOW_SEVERITY_LEVEL }} == 'medium' ]]
then
if [[ ${{ env.EVENT_NAME }} == 'pull_request' ]]
then
echo ""$error_start_message" high or critical. "$error_end_message" "$error_search_pr_message"";
exit 1;
else
echo ""$error_start_message" high or critical found on branch "${{ env.BRANCH }}". $error_end_message";
exit 1;
fi
elif [[ ${{ env.ALLOW_SEVERITY_LEVEL }} == 'high' ]]
then
if [[ $is_critical_vuln_present == 'false' ]]
then
echo "Only high vulnerabilities detected! Allowing due to input ALLOW_SEVERITY_LEVEL being set to high.";
exit 0;
fi
if [[ ${{ env.EVENT_NAME }} == 'pull_request' ]]
then
echo ""$error_start_message" critical. "$error_end_message" "$error_search_pr_message"";
exit 1;
else
echo ""$error_start_message" critical found on "${{ env.BRANCH }}" branch. $error_end_message";
exit 1;
fi
elif [[ ${{ env.ALLOW_SEVERITY_LEVEL }} == 'critical' ]]
then
echo "High or critical vulnerabilities detected! Allowing due to input ALLOW_SEVERITY_LEVEL being set to critical.";
exit 0;
else
echo "Input ALLOW_SEVERITY_LEVEL was not one of the known values, found "${{ env.ALLOW_SEVERITY_LEVEL }}". If you see this message, please contact SKIP.";
exit 1;
fi