Repository navigation
Expand file tree
/
Copy pathaction.yml
More file actions
254 lines (254 loc) · 10.8 KB
/
Copy pathaction.yml
File metadata and controls
254 lines (254 loc) · 10.8 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
# yamllint disable rule:line-length
# yamllint disable rule:quoted-strings
---
name: MCVS-docker-action
description: |
Mission Critical Vulnerability Scanner (MCVS) Docker action.
inputs:
build-args:
description: |
Docker build arguments. Passed as-is if multiline, else formatted as
`APPLICATION=value`.
context:
default: "."
description: |
Directory path that contains all the files needed to build a Docker image.
dockle-accept-key:
description: |
One of the Dockle checks is the inspection of use of secrets in
environment variables. Currently, there is a reported bug
`goodwithtech/dockle/issues/250`, i.e. if a specific version of a package
will be installed then an error will be thrown by Dockle, which is
incorrect. To mitigate this one has to specify the packages that are
applicable, e.g.: `libcrypto3,libssl3`.
dockle-accept-file:
description: |
Comma-separated file names that Dockle's CIS-DI-0010 check should accept,
e.g.: `settings.py`. Dockle flags a hard-coded list of file names as
suspicious (`settings.py`, `credentials`, `.env`, ...), which third-party
packages legitimately ship. `dockle-accept-key` cannot suppress these.
Dockle matches on the file name only, not the path, so an accepted name
is accepted anywhere in the image.
dockle-accept-file-extension:
description: |
Comma-separated file extensions that Dockle's CIS-DI-0010 check should
accept, e.g.: `pem`. Dockle matches on the extension only, not the path,
so an accepted extension is accepted anywhere in the image.
grype-version:
description: The grype version to be used by the anchore/scan-action.
images:
description: The name of the to be created image.
default: ghcr.io/${{ github.repository }}
dockerhub-username:
description: |
Docker Hub username. Required when push-to-container-registry is set to
'dockerhub'.
dockerhub-token:
description: |
Docker Hub access token. Required when push-to-container-registry is set
to 'dockerhub'.
platforms:
description: |
Comma separated list of target platforms to build the image for, e.g.
`linux/amd64,linux/arm64`. Set the value to `linux/amd64` to restore
single architecture builds. One platform is scanned per job, i.e. the
platform that the runner provides natively when it is in the list, else
the first entry.
default: linux/amd64,linux/arm64
push-to-container-registry:
description: |
Specify the container registry to which the image must be pushed. Set the
value to: 'ghcr' for GitHub Container Registry, 'dockerhub' for Docker
Hub, or '' to disable pushing to a container registry.
default: ghcr
token:
description: |
A token is required to allow the mcvs-docker-action to push the
image that it has been built, to the packages repository of the GitHub
repository where the action has been run.
runs:
using: "composite"
steps:
#
# Dockerfile linting (static).
#
- uses: hadolint/hadolint-action@06be81baf89a55ffd0e24b8f04a4185738dd3387 # v3.5.0
with:
dockerfile: ${{ inputs.context }}/Dockerfile
failure-threshold: style
#
# Only one image can be loaded into the docker image store, hence a single
# platform is picked to lint, detect waste in and scan. The platform that
# the runner provides natively is preferred as it requires no emulation. A
# consumer that wants every architecture scanned runs this action in a
# matrix with one platform per job, as each job then scans the platform
# that it builds.
#
- name: Determine the platforms to build and the platform to scan
id: platform
shell: bash
env:
PLATFORMS: ${{ inputs.platforms }}
run: |
platforms="${PLATFORMS//[[:space:]]/}"
native=linux/amd64
[[ "${RUNNER_ARCH:-}" == "ARM64" ]] && native=linux/arm64
scan_platform="${platforms%%,*}"
[[ ",$platforms," == *",$native,"* ]] && scan_platform="$native"
{
echo "platforms=$platforms"
echo "scan_platform=$scan_platform"
echo "qemu=$([[ "$platforms" == "$native" ]] && echo false || echo true)"
} >> "$GITHUB_OUTPUT"
#
# Prepare the builder. QEMU emulates the platforms that the runner does not
# provide natively, so it is skipped when the native platform is the only
# one that is built. Buildx is always set up so that all build steps in
# this job share one builder and therefore one layer cache.
#
- name: Set up QEMU
if: steps.platform.outputs.qemu == 'true'
uses: docker/setup-qemu-action@99012661954931238ded8c8b007157a8430204e1 # v4.4.0
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@f87e5991a6d7451dcb8d9637bfbc97413f497069 # v4.4.1
#
# Determine image name and tag.
#
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@dc802804100637a589fabce1cb79ff13a1411302 # v6.2.0
with:
flavor: |
latest=false
images: ${{ inputs.images }}
#
# Build a docker image.
#
- name: Set build-args
id: parse
shell: bash
env:
BUILD_ARGS: ${{ inputs.build-args }}
run: |
if [[ "$BUILD_ARGS" == *$'\n'* ]]; then
echo "Detected multiline build-args"
# A random delimiter prevents that a line in the input ends the
# heredoc early and injects other step outputs.
delimiter="EOF_$(openssl rand -hex 16)"
echo "build_args<<$delimiter" >> $GITHUB_OUTPUT
echo "$BUILD_ARGS" >> $GITHUB_OUTPUT
echo "$delimiter" >> $GITHUB_OUTPUT
else
echo "Detected single-line build-arg"
echo "build_args=APPLICATION=$BUILD_ARGS" >> $GITHUB_OUTPUT
fi
#
# Build, lint (dynamic), detect waste in and scan the image. Loading a non
# native image is fine as Dockle, Dive and Grype inspect the layers and the
# config, they never execute the image. steps.meta.outputs.tags is not used
# as the local tag since it can be multiline.
#
- name: Build an image from a dockerfile
uses: docker/build-push-action@c3c9e263c25d99ce0380d002d59b67737d91b0dc # v7.4.0
with:
build-args: ${{ steps.parse.outputs.build_args }}
context: ${{ inputs.context }}
labels: ${{ steps.meta.outputs.labels }}
load: true
platforms: ${{ steps.platform.outputs.scan_platform }}
push: false
tags: mcvs-docker-action:scan
#
# Docker image linting (dynamic).
#
- uses: goodwithtech/dockle-action@e30e6af832aad6ea7dca2a248d31a85eab6dbd68 # v0.4.15
with:
image: mcvs-docker-action:scan
# CIS-DI-0005: Enable Content trust for Docker as this cannot be
# achieved in public GitHub runners.
# CIS-DI-0006: Add HEALTHCHECK instruction to the container image as
# the decision was made that this is up to the consumer of this action
# to set a health check or not.
ignore: CIS-DI-0005,CIS-DI-0006
accept-key: ${{ inputs.dockle-accept-key }}
accept-file: ${{ inputs.dockle-accept-file }}
accept-file-extension: ${{ inputs.dockle-accept-file-extension }}
#
# Detect waste in the docker image.
#
- uses: docker://wagoodman/dive:v0.13.1@sha256:f1886e6c32c094fc41a623c1989f5cb3e48aa766da5f0be233f911fc1d85ce10
with:
args: mcvs-docker-action:scan --ci --ci-config .dive-ci
- name: Scan the image using Grype
uses: anchore/scan-action@27805bf3b4e84b4a5c980df22ed233c00390a439 # v7.4.2
with:
grype-version: ${{ inputs.grype-version }}
image: mcvs-docker-action:scan
only-fixed: false
output-format: table
severity-cutoff: high
#
# Code security scanning. Architecture independent, hence it runs once.
#
- name: Scan the code using Grype
uses: anchore/scan-action@27805bf3b4e84b4a5c980df22ed233c00390a439 # v7.4.2
with:
grype-version: ${{ inputs.grype-version }}
only-fixed: false
output-format: table
path: ${{ inputs.context }}
severity-cutoff: high
#
# Log in to the container registry and push the image. Logging in is
# skipped when the image is not pushed, so that credentials are not exposed
# to runs that do not need them, e.g. pull requests.
#
# workflow_dispatch on a tag ref is accepted too: a tag that a workflow
# creates with GITHUB_TOKEN, as mcvs-general-action's auto-release does,
# starts no push run, but that workflow may dispatch this one on the tag.
#
- name: Log in to GitHub Container Registry
if: inputs.push-to-container-registry == 'ghcr' &&
(github.event_name == 'push' ||
github.event_name == 'workflow_dispatch') &&
startsWith(github.ref, 'refs/tags/')
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ inputs.token }}
- name: Log in to Docker Hub
if: inputs.push-to-container-registry == 'dockerhub' &&
(github.event_name == 'push' ||
github.event_name == 'workflow_dispatch') &&
startsWith(github.ref, 'refs/tags/')
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
with:
username: ${{ inputs.dockerhub-username }}
password: ${{ inputs.dockerhub-token }}
#
# Every platform is built on every run, so that an architecture specific
# build failure surfaces on a pull request instead of on a tag. The
# scanned platform is a cache hit on the shared builder, hence only the
# remaining platforms cost time.
#
# A multi architecture image cannot be stored in the local docker image
# store, hence the manifest list is pushed by buildx instead of by
# `docker push`. Pushing is conditional, building is not.
#
# provenance is disabled to prevent that buildx adds attestation manifests
# that are displayed as `unknown/unknown` entries in a container registry.
#
- name: Build the image for every platform and push it on a tag
uses: docker/build-push-action@c3c9e263c25d99ce0380d002d59b67737d91b0dc # v7.4.0
with:
build-args: ${{ steps.parse.outputs.build_args }}
context: ${{ inputs.context }}
labels: ${{ steps.meta.outputs.labels }}
platforms: ${{ steps.platform.outputs.platforms }}
provenance: false
push: ${{ (github.event_name == 'push' ||
github.event_name == 'workflow_dispatch') &&
startsWith(github.ref, 'refs/tags/') &&
inputs.push-to-container-registry != '' }}
tags: ${{ steps.meta.outputs.tags }}