-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathcd-public-builder-grype-scan.yml
More file actions
344 lines (296 loc) · 14.3 KB
/
cd-public-builder-grype-scan.yml
File metadata and controls
344 lines (296 loc) · 14.3 KB
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
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
# CD pipeline to download packages from public Habitat Builder API and run Grype security scan
# test inputs:
# hab_package: core/nginx
# hab_version: 24.09
# hab_release: 20250915012345
# hab_channel: stable, base, unstable, base-2025, lts-2024
# hab_auth_token: (if PAT not specified, uses secret)
# runner-os: run both ubuntu-latest and windows-latest
# this workflow installs a specified Chef Habitat package and runs a Grype security scan against it.
# It supports multiple OS runners (Linux, Windows, MacOS) and allows dynamic input of package details.
# The results of the Grype scan are uploaded as artifacts for further analysis.
# Example hab pkg install command:
# hab pkg install core/7zip/24.09/20250708070501 --channel base-2025 --auth HAB_PERSONAL_ACCESS_TOKEN
# -z, --auth <AUTH_TOKEN> Authentication token for Builder [env: HAB_AUTH_TOKEN=]
# --binlink-dir <BINLINK_DIR> Binlink all binaries from installed package(s) into BINLINK_DIR [env: HAB_BINLINK_DIR=] [default: /bin]
# -u, --url <BLDR_URL> Specify an alternate Builder endpoint. If not specified, the value will be taken from the HAB_BLDR_URL environment variable if defined. (default: https://bldr.habitat.sh)
# -c, --channel <CHANNEL> Install from the specified release channel [env: HAB_BLDR_CHANNEL=] [default: stable]
# this installs on the current OS (runner type is detected)
# Example hab pkg download command (we do not use this in the workflow but it's here for reference; allows --target):
# hab pkg download core/nginx/<VERSION>/<RELEASE> \
# --channel stable \
# --target x86_64-linux \
# --download-directory /tmp/habitat_packages
# called ad-hoc (dispatch) only
# performs the following actions:
# 1. create the specified runner (Windows or ubuntu latest, later add specific OS versions to matrix)
# 2. download grype
# 3. download and hab pkg install the specified product from builder per above
# (using the organization secret provided in common-github-actions repo GA_DOWNLOAD_GRYPE_LICENSE_ID or supplied)
# 4. grype dir:.
# 5. upload the vulnerability scan artifact
# GitHub runners available: per https://github.com/actions/runner-images?tab=readme-ov-file#available-images
# ubuntu-latest or ubuntu-24.04
# ubuntu-22.04
# ubuntu-slim
# macos-26 (ARM64)
# macos-15-intel
# macOS-15-arm64
# macos-14-large
# macOS-14-arm64
# windows-2025 or windows-latest
# windows-2022
# windows-2019 (deprecated)
#
# TODO: only ubuntu-latest and windows-latest runners are currently implemented; add MacOS later
#
# can add custom runner images per https://docs.github.com/en/actions/how-tos/manage-runners/larger-runners/use-custom-images on large self-hosted runners
name: CD grype for public Habitat Packages (bldr.habitat.sh)
on:
workflow_dispatch:
inputs:
hab_package:
description: "Chef Habitat package to install (e.g., core/nginx)"
required: true
default: "core/nginx"
hab_version:
description: "Chef Habitat package version (optional)"
required: false
hab_release:
description: "Chef Habitat package release (optional)"
required: false
hab_channel:
description: "Chef Habitat package channel (e.g., stable, base, base-2025); default is stable"
required: false
default: "stable"
hab_auth_token:
description: "Chef Habitat authentication token (optional, uses secret if not provided)"
required: false
runner_os:
description: "Runner OS to use (ubuntu-latest or windows-latest)"
required: false
type: choice
options:
- ubuntu-latest
- ubuntu-24.04
- ubuntu-22.04
- ubuntu-slim
- windows-latest
- windows-2025
- windows-2022
- windows-2019
- macos-26
- macos-15-intel
- macOS-15-arm64
- macos-14-large
- macOS-14-arm64
default: ubuntu-latest
jobs:
habitat-grype-scan-linux:
name: 'Grype scan (ubuntu-latest)'
runs-on: ubuntu-latest
if: ${{ success() && inputs.runner_os == 'ubuntu-latest' }}
steps:
- name: Install Chef Habitat
run: |
curl https://raw.githubusercontent.com/habitat-sh/habitat/main/components/hab/install.sh | sudo bash
- name: Configure Habitat
run: |
# Add Habitat to PATH (for current session and future steps if needed, though install.sh usually handles symlinks)
echo "/hab/bin" >> $GITHUB_PATH
# Accept the license
echo "HAB_LICENSE=accept-no-persist" >> $GITHUB_ENV
# Create the necessary directory structure for license file
sudo mkdir -p /hab/accepted-licenses/
sudo touch /hab/accepted-licenses/habitat
- name: Install Grype
continue-on-error: true
run: |
curl -sSfL https://get.anchore.io/grype | sh -s -- -b /usr/local/bin
- name: Install Habitat Package under test (Linux)
run: |
PACKAGE="${{ inputs.hab_package }}"
if [ -n "${{ inputs.hab_version }}" ]; then
PACKAGE="${PACKAGE}/${{ inputs.hab_version }}"
fi
if [ -n "${{ inputs.hab_release }}" ]; then
PACKAGE="${PACKAGE}/${{ inputs.hab_release }}"
fi
INSTALL_CMD="sudo hab pkg install ${PACKAGE}"
if [ -n "${{ inputs.hab_channel }}" ]; then
INSTALL_CMD="${INSTALL_CMD} --channel ${{ inputs.hab_channel }}"
fi
AUTH_TOKEN="${{ inputs.hab_auth_token }}"
if [ -z "${AUTH_TOKEN}" ]; then
AUTH_TOKEN="${{ secrets.GA_DOWNLOAD_GRYPE_LICENSE_ID }}"
echo "Using token from repository secret"
else
echo "Using token from workflow input"
fi
# if [ -n "${AUTH_TOKEN}" ]; then
# INSTALL_CMD="${INSTALL_CMD} --auth ${AUTH_TOKEN}"
# fi
echo "Installing: ${INSTALL_CMD}"
eval ${INSTALL_CMD}
- name: Run Grype Scan on Habitat Package
timeout-minutes: 15 # Sets a 15-minute timeout for this specific step
run: |
# Find the installed package path. 'hab pkg path' returns the path to the latest installed version.
PKG_PATH=$(hab pkg path ${{ inputs.hab_package }})
# run grype in runner
grype dir:$PKG_PATH --name ${{ inputs.hab_package }}
# run grype to output to file (which is uploaded to the job as an artifact)
OUTPUT_FILE="grype-results-ubuntu-${{ inputs.hab_package }}.txt"
OUTPUT_FILE="${OUTPUT_FILE//\//-}"
echo $OUTPUT_FILE
grype dir:$PKG_PATH --name ${{ inputs.hab_package }} > $OUTPUT_FILE
echo "OUTPUT_FILE=$OUTPUT_FILE" >> $GITHUB_ENV
- name: Upload Grype Scan Results
uses: actions/upload-artifact@v4
with:
name: grype-results-ubuntu-${{ env.OUTPUT_FILE }}
path: ${{ env.OUTPUT_FILE }}
habitat-grype-scan-macos:
name: 'Grype scan (macos-latest)'
runs-on: macos-15-intel
if: ${{ success() && inputs.runner_os == 'macos-15-intel' }}
steps:
- name: Install Chef Habitat
run: |
curl https://raw.githubusercontent.com/habitat-sh/habitat/main/components/hab/install.sh | sudo bash
hab license accept
hab version
- name: Configure Habitat
run: |
# Add Habitat to PATH (for current session and future steps if needed, though install.sh usually handles symlinks)
# echo "/hab/bin" >> $GITHUB_PATH
# Accept the license
echo "HAB_LICENSE=accept-no-persist" >> $GITHUB_ENV
# Create the necessary directory structure for license file
# sudo chmod -R 777 /hab
# sudo mkdir -p /hab/accepted-licenses/
# sudo touch /hab/accepted-licenses/habitat
- name: Install Grype
continue-on-error: true
run: |
curl -sSfL https://get.anchore.io/grype | sh -s -- -b /usr/local/bin
- name: Run Grype Scan on Habitat Package
timeout-minutes: 15 # Sets a 15-minute timeout for this specific step
run: |
# Find the installed package path. 'hab pkg path' returns the path to the latest installed version.
PKG_PATH=$(hab pkg path ${{ inputs.hab_package }})
# run grype in runner
grype dir:$PKG_PATH --name ${{ inputs.hab_package }}
# run grype to output to file (which is uploaded to the job as an artifact)
OUTPUT_FILE="grype-results-macos-${{ inputs.hab_package }}.txt"
OUTPUT_FILE="${OUTPUT_FILE//\//-}"
echo $OUTPUT_FILE
grype dir:$PKG_PATH --name ${{ inputs.hab_package }} > $OUTPUT_FILE
echo "OUTPUT_FILE=$OUTPUT_FILE" >> $GITHUB_ENV
- name: Install Habitat Package under test (MacOS)
run: |
PACKAGE="${{ inputs.hab_package }}"
if [ -n "${{ inputs.hab_version }}" ]; then
PACKAGE="${PACKAGE}/${{ inputs.hab_version }}"
fi
if [ -n "${{ inputs.hab_release }}" ]; then
PACKAGE="${PACKAGE}/${{ inputs.hab_release }}"
fi
INSTALL_CMD="sudo hab pkg install ${PACKAGE}"
if [ -n "${{ inputs.hab_channel }}" ]; then
INSTALL_CMD="${INSTALL_CMD} --channel ${{ inputs.hab_channel }}"
fi
AUTH_TOKEN="${{ inputs.hab_auth_token }}"
if [ -z "${AUTH_TOKEN}" ]; then
AUTH_TOKEN="${{ secrets.GA_DOWNLOAD_GRYPE_LICENSE_ID }}"
echo "Using token from repository secret"
else
echo "Using token from workflow input"
fi
# if [ -n "${AUTH_TOKEN}" ]; then
# INSTALL_CMD="${INSTALL_CMD} --auth ${AUTH_TOKEN}"
# fi
echo "Installing: ${INSTALL_CMD}"
eval ${INSTALL_CMD}
- name: Upload Grype Scan Results
uses: actions/upload-artifact@v4
with:
name: grype-results-macos-${{ env.OUTPUT_FILE }}
path: ${{ env.OUTPUT_FILE }}
habitat-grype-scan-windows:
name: 'Grype scan (windows-latest)'
runs-on: windows-latest
if: ${{ success() && inputs.runner_os == 'windows-latest' }}
steps:
- name: Install Chef Habitat (Windows)
run: |
choco install habitat
hab --version
- name: Configure Habitat (Windows)
run: |
# Accept the license
echo "HAB_LICENSE=accept-no-persist" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
# Create the necessary directory structure for license file
New-Item -ItemType Directory -Force -Path "C:\hab\accepted-licenses"
New-Item -ItemType File -Force -Path "C:\hab\accepted-licenses\habitat"
- name: Install Grype (Windows)
continue-on-error: true
run: |
$ErrorActionPreference = 'Stop'
# Download and install Grype for Windows
$grypeVersion = (Invoke-RestMethod -Uri "https://api.github.com/repos/anchore/grype/releases/latest").tag_name
$grypeUrl = "https://github.com/anchore/grype/releases/download/$grypeVersion/grype_$($grypeVersion.TrimStart('v'))_windows_amd64.zip"
$grypeZip = "$env:TEMP\grype.zip"
$grypeDir = "$env:TEMP\grype"
# Download Grype
Invoke-WebRequest -Uri $grypeUrl -OutFile $grypeZip
# Extract Grype
Expand-Archive -Path $grypeZip -DestinationPath $grypeDir -Force
# Add Grype to PATH for subsequent steps
echo "$grypeDir" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
# Verify installation
& "$grypeDir\grype.exe" version
- name: Install Habitat Package under test (Windows)
run: |
$Package = "${{ inputs.hab_package }}"
if ("${{ inputs.hab_version }}" -ne "") {
$Package = "${Package}/${{ inputs.hab_version }}"
}
if ("${{ inputs.hab_release }}" -ne "") {
$Package = "${Package}/${{ inputs.hab_release }}"
}
$InstallCmd = "hab pkg install ${Package}"
if ("${{ inputs.hab_channel }}" -ne "") {
$InstallCmd = "${InstallCmd} --channel ${{ inputs.hab_channel }}"
}
$AuthToken = "${{ inputs.hab_auth_token }}"
if ([string]::IsNullOrEmpty($AuthToken)) {
$AuthToken = "${{ secrets.GA_DOWNLOAD_GRYPE_LICENSE_ID }}"
Write-Host "Using token from repository secret"
} else {
Write-Host "Using token from workflow input"
}
# if (-not [string]::IsNullOrEmpty($AuthToken)) {
# $InstallCmd = "${InstallCmd} --auth ${AuthToken}"
# }
Write-Host "Installing: ${InstallCmd}"
Invoke-Expression $InstallCmd
- name: Run Grype Scan on Habitat Package (Windows)
timeout-minutes: 15 # Sets a 15-minute timeout for this specific step
run: |
# Find the installed package path. 'hab pkg path' returns the path to the latest installed version.
$PkgPath = hab pkg path ${{ inputs.hab_package }}
Write-Host "Package Path: $PkgPath"
# run grype in runner
grype dir:$PkgPath --name ${{ inputs.hab_package }}
# run grype to output to file (which is uploaded to the job as an artifact)
$OutputFile = "grype-results-windows-${{ inputs.hab_package }}.txt"
$OutputFile = $OutputFile -replace '/', '-'
Write-Host $OutputFile
grype dir:$PkgPath --name ${{ inputs.hab_package }} | Out-File -FilePath $OutputFile -Encoding utf8
echo "OUTPUT_FILE=$OutputFile" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
- name: Upload Grype Scan Results
uses: actions/upload-artifact@v4
with:
name: grype-results-windows-${{ env.OUTPUT_FILE }}
path: ${{ env.OUTPUT_FILE }}