-
Notifications
You must be signed in to change notification settings - Fork 84
/
buildah.yaml
487 lines (441 loc) · 19 KB
/
buildah.yaml
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
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
apiVersion: tekton.dev/v1
kind: Task
metadata:
labels:
app.kubernetes.io/version: "0.1"
build.appstudio.redhat.com/build_type: "docker"
annotations:
tekton.dev/pipelines.minVersion: "0.12.1"
tekton.dev/tags: "image-build, appstudio, hacbs"
name: buildah
spec:
description: |-
Buildah task builds source code into a container image and pushes the image into container registry using buildah tool.
In addition it generates a SBOM file, injects the SBOM file into final container image and pushes the SBOM file as separate image using cosign tool.
When [Java dependency rebuild](https://redhat-appstudio.github.io/docs.stonesoup.io/Documentation/main/cli/proc_enabled_java_dependencies.html) is enabled it triggers rebuilds of Java artifacts.
When prefetch-dependencies task was activated it is using its artifacts to run build in hermetic environment.
params:
- description: Reference of the image buildah will produce.
name: IMAGE
type: string
- default: ""
description: Deprecated. Has no effect. Will be removed in the future.
name: BUILDER_IMAGE
type: string
- default: ./Dockerfile
description: Path to the Dockerfile to build.
name: DOCKERFILE
type: string
- default: .
description: Path to the directory to use as context.
name: CONTEXT
type: string
- default: "true"
description: Verify the TLS on the registry endpoint (for push/pull to a non-TLS registry)
name: TLSVERIFY
type: string
- description: unused, should be removed in next task version
name: DOCKER_AUTH
type: string
default: ""
- default: "false"
description: Determines if build will be executed without network access.
name: HERMETIC
type: string
- default: ""
description: In case it is not empty, the prefetched content should be made available to the build.
name: PREFETCH_INPUT
type: string
- default: ""
description: Delete image tag after specified time. Empty means to keep the image tag. Time values could be something like 1h, 2d, 3w for hours, days, and weeks, respectively.
name: IMAGE_EXPIRES_AFTER
type: string
- name: COMMIT_SHA
description: The image is built from this commit.
type: string
default: ""
- name: YUM_REPOS_D_SRC
description: Path in the git repository in which yum repository files are stored
default: repos.d
- name: YUM_REPOS_D_FETCHED
description: Path in source workspace where dynamically-fetched repos are present
default: fetched.repos.d
- name: YUM_REPOS_D_TARGET
description: Target path on the container in which yum repository files should be made available
default: /etc/yum.repos.d
- name: TARGET_STAGE
description: Target stage in Dockerfile to build. If not specified, the Dockerfile is processed entirely to (and including) its last stage.
type: string
default: ""
- name: ENTITLEMENT_SECRET
description: Name of secret which contains the entitlement certificates
type: string
default: "etc-pki-entitlement"
- name: BUILD_ARGS
description: Array of --build-arg values ("arg=value" strings)
type: array
default: []
- name: BUILD_ARGS_FILE
description: Path to a file with build arguments, see https://www.mankier.com/1/buildah-build#--build-arg-file
type: string
default: ""
- name: caTrustConfigMapName
type: string
description: The name of the ConfigMap to read CA bundle data from.
default: trusted-ca
- name: caTrustConfigMapKey
type: string
description: The name of the key in the ConfigMap that contains the CA bundle data.
default: ca-bundle.crt
results:
- description: Digest of the image just built
name: IMAGE_DIGEST
- description: Image repository where the built image was pushed
name: IMAGE_URL
- description: Digests of the base images used for build
name: BASE_IMAGES_DIGESTS
- name: SBOM_JAVA_COMPONENTS_COUNT
description: The counting of Java components by publisher in JSON format
type: string
- name: JAVA_COMMUNITY_DEPENDENCIES
description: The Java dependencies that came from community sources such as Maven central.
stepTemplate:
env:
- name: BUILDAH_FORMAT
value: oci
- name: STORAGE_DRIVER
value: vfs
- name: HERMETIC
value: $(params.HERMETIC)
- name: CONTEXT
value: $(params.CONTEXT)
- name: DOCKERFILE
value: $(params.DOCKERFILE)
- name: IMAGE
value: $(params.IMAGE)
- name: TLSVERIFY
value: $(params.TLSVERIFY)
- name: IMAGE_EXPIRES_AFTER
value: $(params.IMAGE_EXPIRES_AFTER)
- name: YUM_REPOS_D_SRC
value: $(params.YUM_REPOS_D_SRC)
- name: YUM_REPOS_D_FETCHED
value: $(params.YUM_REPOS_D_FETCHED)
- name: YUM_REPOS_D_TARGET
value: $(params.YUM_REPOS_D_TARGET)
- name: TARGET_STAGE
value: $(params.TARGET_STAGE)
- name: PARAM_BUILDER_IMAGE
value: $(params.BUILDER_IMAGE)
- name: ENTITLEMENT_SECRET
value: $(params.ENTITLEMENT_SECRET)
- name: BUILD_ARGS_FILE
value: $(params.BUILD_ARGS_FILE)
steps:
- image: quay.io/redhat-appstudio/buildah:v1.31.0@sha256:34f12c7b72ec2c28f1ded0c494b428df4791c909f1f174dd21b8ed6a57cf5ddb
name: build
computeResources:
limits:
memory: 4Gi
requests:
memory: 512Mi
cpu: 250m
env:
- name: COMMIT_SHA
value: $(params.COMMIT_SHA)
args:
- $(params.BUILD_ARGS[*])
script: |
if [ -n "${PARAM_BUILDER_IMAGE}" ]; then
echo "WARNING: provided deprecated BUILDER_IMAGE parameter has no effect."
fi
ca_bundle=/mnt/trusted-ca/ca-bundle.crt
if [ -f "$ca_bundle" ]; then
echo "INFO: Using mounted CA bundle: $ca_bundle"
cp -vf $ca_bundle /etc/pki/ca-trust/source/anchors
update-ca-trust
fi
SOURCE_CODE_DIR=source
if [ -e "$SOURCE_CODE_DIR/$CONTEXT/$DOCKERFILE" ]; then
dockerfile_path="$(pwd)/$SOURCE_CODE_DIR/$CONTEXT/$DOCKERFILE"
elif [ -e "$SOURCE_CODE_DIR/$DOCKERFILE" ]; then
dockerfile_path="$(pwd)/$SOURCE_CODE_DIR/$DOCKERFILE"
elif echo "$DOCKERFILE" | grep -q "^https\?://"; then
echo "Fetch Dockerfile from $DOCKERFILE"
dockerfile_path=$(mktemp --suffix=-Dockerfile)
http_code=$(curl -s -L -w "%{http_code}" --output "$dockerfile_path" "$DOCKERFILE")
if [ $http_code != 200 ]; then
echo "No Dockerfile is fetched. Server responds $http_code"
exit 1
fi
http_code=$(curl -s -L -w "%{http_code}" --output "$dockerfile_path.dockerignore.tmp" "$DOCKERFILE.dockerignore")
if [ $http_code = 200 ]; then
echo "Fetched .dockerignore from $DOCKERFILE.dockerignore"
mv "$dockerfile_path.dockerignore.tmp" $SOURCE_CODE_DIR/$CONTEXT/.dockerignore
fi
else
echo "Cannot find Dockerfile $DOCKERFILE"
exit 1
fi
if [ -n "$JVM_BUILD_WORKSPACE_ARTIFACT_CACHE_PORT_80_TCP_ADDR" ] && grep -q '^\s*RUN \(./\)\?mvn' "$dockerfile_path"; then
sed -i -e "s|^\s*RUN \(\(./\)\?mvn\)\(.*\)|RUN echo \"<settings><mirrors><mirror><id>mirror.default</id><url>http://$JVM_BUILD_WORKSPACE_ARTIFACT_CACHE_PORT_80_TCP_ADDR/v1/cache/default/0/</url><mirrorOf>*</mirrorOf></mirror></mirrors></settings>\" > /tmp/settings.yaml; \1 -s /tmp/settings.yaml \3|g" "$dockerfile_path"
touch /var/lib/containers/java
fi
# Fixing group permission on /var/lib/containers
chown root:root /var/lib/containers
sed -i 's/^\s*short-name-mode\s*=\s*.*/short-name-mode = "disabled"/' /etc/containers/registries.conf
# Setting new namespace to run buildah - 2^32-2
echo 'root:1:4294967294' | tee -a /etc/subuid >> /etc/subgid
BUILDAH_ARGS=()
BASE_IMAGES=$(grep -i '^\s*FROM' "$dockerfile_path" | sed 's/--platform=\S*//' | awk '{print $2}')
if [ "${HERMETIC}" == "true" ]; then
BUILDAH_ARGS+=("--pull=never")
UNSHARE_ARGS="--net"
for image in $BASE_IMAGES; do
if [ "${image}" != "scratch" ]; then
unshare -Ufp --keep-caps -r --map-users 1,1,65536 --map-groups 1,1,65536 -- buildah pull $image
fi
done
echo "Build will be executed with network isolation"
fi
if [ -n "${TARGET_STAGE}" ]; then
BUILDAH_ARGS+=("--target=${TARGET_STAGE}")
fi
if [ -n "${BUILD_ARGS_FILE}" ]; then
BUILDAH_ARGS+=("--build-arg-file=$(pwd)/$SOURCE_CODE_DIR/${BUILD_ARGS_FILE}")
fi
for build_arg in "$@"; do
BUILDAH_ARGS+=("--build-arg=$build_arg")
done
if [ -f "$(workspaces.source.path)/cachi2/cachi2.env" ]; then
cp -r "$(workspaces.source.path)/cachi2" /tmp/
chmod -R go+rwX /tmp/cachi2
VOLUME_MOUNTS="--volume /tmp/cachi2:/cachi2"
sed -i 's|^\s*run |RUN . /cachi2/cachi2.env \&\& \\\n |i' "$dockerfile_path"
echo "Prefetched content will be made available"
prefetched_repo_for_my_arch="/tmp/cachi2/output/deps/rpm/$(uname -m)/repos.d/cachi2.repo"
if [ -f "$prefetched_repo_for_my_arch" ]; then
echo "Adding $prefetched_repo_for_my_arch to $YUM_REPOS_D_FETCHED"
mkdir -p "$YUM_REPOS_D_FETCHED"
cp --no-clobber "$prefetched_repo_for_my_arch" "$YUM_REPOS_D_FETCHED"
fi
fi
# if yum repofiles stored in git, copy them to mount point outside the source dir
if [ -d "${SOURCE_CODE_DIR}/${YUM_REPOS_D_SRC}" ]; then
mkdir -p ${YUM_REPOS_D_FETCHED}
cp -r ${SOURCE_CODE_DIR}/${YUM_REPOS_D_SRC}/* ${YUM_REPOS_D_FETCHED}
fi
# if anything in the repofiles mount point (either fetched or from git), mount it
if [ -d "${YUM_REPOS_D_FETCHED}" ]; then
chmod -R go+rwX ${YUM_REPOS_D_FETCHED}
mount_point=$(realpath ${YUM_REPOS_D_FETCHED})
VOLUME_MOUNTS="${VOLUME_MOUNTS} --volume ${mount_point}:${YUM_REPOS_D_TARGET}"
fi
LABELS=(
"--label" "build-date=$(date -u +'%Y-%m-%dT%H:%M:%S')"
"--label" "architecture=$(uname -m)"
"--label" "vcs-type=git"
)
[ -n "$COMMIT_SHA" ] && LABELS+=("--label" "vcs-ref=$COMMIT_SHA")
[ -n "$IMAGE_EXPIRES_AFTER" ] && LABELS+=("--label" "quay.expires-after=$IMAGE_EXPIRES_AFTER")
ENTITLEMENT_PATH="/entitlement"
if [ -d "$ENTITLEMENT_PATH" ]; then
cp -r --preserve=mode "$ENTITLEMENT_PATH" /tmp/entitlement
VOLUME_MOUNTS="${VOLUME_MOUNTS} --volume /tmp/entitlement:/etc/pki/entitlement"
echo "Adding the entitlement to the build"
fi
unshare -Uf $UNSHARE_ARGS --keep-caps -r --map-users 1,1,65536 --map-groups 1,1,65536 -w ${SOURCE_CODE_DIR}/$CONTEXT -- buildah build \
$VOLUME_MOUNTS \
"${BUILDAH_ARGS[@]}" \
"${LABELS[@]}" \
--tls-verify=$TLSVERIFY --no-cache \
--ulimit nofile=4096:4096 \
-f "$dockerfile_path" -t $IMAGE .
container=$(buildah from --pull-never $IMAGE)
buildah mount $container | tee /workspace/container_path
echo $container > /workspace/container_name
# Save the SBOM produced by Cachi2 so it can be merged into the final SBOM later
if [ -f "/tmp/cachi2/output/bom.json" ]; then
cp /tmp/cachi2/output/bom.json ./sbom-cachi2.json
fi
# Expose base image digests
for image in $BASE_IMAGES; do
if [ "${image}" != "scratch" ]; then
buildah images --format '{{ .Name }}:{{ .Tag }}@{{ .Digest }}' --filter reference="$image" >> $(results.BASE_IMAGES_DIGESTS.path)
fi
done
# Needed to generate base images SBOM
echo "$BASE_IMAGES" > $(workspaces.source.path)/base_images_from_dockerfile
securityContext:
capabilities:
add:
- SETFCAP
volumeMounts:
- mountPath: /var/lib/containers
name: varlibcontainers
- mountPath: "/entitlement"
name: etc-pki-entitlement
- name: trusted-ca
mountPath: /mnt/trusted-ca
readOnly: true
workingDir: $(workspaces.source.path)
- name: sbom-syft-generate
image: quay.io/redhat-appstudio/syft:v0.105.1@sha256:1910b829997650c696881e5fc2fc654ddf3184c27edb1b2024e9cb2ba51ac431
# Respect Syft configuration if the user has it in the root of their repository
# (need to set the workdir, see https://github.com/anchore/syft/issues/2465)
workingDir: $(workspaces.source.path)/source
script: |
echo "Running syft on the source directory"
syft dir:$(workspaces.source.path)/source --output cyclonedx-json=$(workspaces.source.path)/sbom-source.json
find $(cat /workspace/container_path) -xtype l -delete
echo "Running syft on the image filesystem"
syft dir:$(cat /workspace/container_path) --output cyclonedx-json=$(workspaces.source.path)/sbom-image.json
volumeMounts:
- mountPath: /var/lib/containers
name: varlibcontainers
- name: analyse-dependencies-java-sbom
image: quay.io/redhat-appstudio/hacbs-jvm-build-request-processor:127ee0c223a2b56a9bd20a6f2eaeed3bd6015f77
script: |
if [ -f /var/lib/containers/java ]; then
/opt/jboss/container/java/run/run-java.sh analyse-dependencies path $(cat /workspace/container_path) -s $(workspaces.source.path)/sbom-image.json --task-run-name $(context.taskRun.name) --publishers $(results.SBOM_JAVA_COMPONENTS_COUNT.path)
sed -i 's/^/ /' $(results.SBOM_JAVA_COMPONENTS_COUNT.path) # Workaround for SRVKP-2875
else
touch $(results.JAVA_COMMUNITY_DEPENDENCIES.path)
fi
volumeMounts:
- mountPath: /var/lib/containers
name: varlibcontainers
securityContext:
runAsUser: 0
- name: merge-syft-sboms
image: registry.access.redhat.com/ubi9/python-39:1-172.1712567222@sha256:c96f839e927c52990143df4efb2872946fcd5de9e1ed2014947bb2cf3084c27a
script: |
#!/bin/python3
import json
# load SBOMs
with open("./sbom-image.json") as f:
image_sbom = json.load(f)
with open("./sbom-source.json") as f:
source_sbom = json.load(f)
# fetch unique components from available SBOMs
def get_identifier(component):
return component["name"] + '@' + component.get("version", "")
image_sbom_components = image_sbom.get("components", [])
existing_components = [get_identifier(component) for component in image_sbom_components]
source_sbom_components = source_sbom.get("components", [])
for component in source_sbom_components:
if get_identifier(component) not in existing_components:
image_sbom_components.append(component)
existing_components.append(get_identifier(component))
image_sbom_components.sort(key=lambda c: get_identifier(c))
# write the CycloneDX unified SBOM
with open("./sbom-cyclonedx.json", "w") as f:
json.dump(image_sbom, f, indent=4)
workingDir: $(workspaces.source.path)
securityContext:
runAsUser: 0
- name: merge-cachi2-sbom
image: quay.io/redhat-appstudio/cachi2:0.7.0@sha256:1fc772aa3636fd0b43d62120d832e5913843e028e8cac42814b487c3a0a32bd8
script: |
if [ -f "sbom-cachi2.json" ]; then
echo "Merging contents of sbom-cachi2.json into sbom-cyclonedx.json"
/src/utils/merge_syft_sbom.py sbom-cachi2.json sbom-cyclonedx.json > sbom-temp.json
mv sbom-temp.json sbom-cyclonedx.json
else
echo "Skipping step since no Cachi2 SBOM was produced"
fi
workingDir: $(workspaces.source.path)
securityContext:
runAsUser: 0
- name: create-purl-sbom
image: registry.access.redhat.com/ubi9/python-39:1-172.1712567222@sha256:c96f839e927c52990143df4efb2872946fcd5de9e1ed2014947bb2cf3084c27a
script: |
#!/bin/python3
import json
with open("./sbom-cyclonedx.json") as f:
cyclonedx_sbom = json.load(f)
purls = [{"purl": component["purl"]} for component in cyclonedx_sbom.get("components", []) if "purl" in component]
purl_content = {"image_contents": {"dependencies": purls}}
with open("sbom-purl.json", "w") as output_file:
json.dump(purl_content, output_file, indent=4)
workingDir: $(workspaces.source.path)
securityContext:
runAsUser: 0
- name: create-base-images-sbom
image: quay.io/redhat-appstudio/base-images-sbom-script@sha256:667669e3def018f9dbb8eaf8868887a40bc07842221e9a98f6787edcff021840
env:
- name: BASE_IMAGES_DIGESTS_PATH
value: $(results.BASE_IMAGES_DIGESTS.path)
script: |
python3 /app/base_images_sbom_script.py --sbom=sbom-cyclonedx.json --base-images-from-dockerfile=base_images_from_dockerfile --base-images-digests=$BASE_IMAGES_DIGESTS_PATH
workingDir: $(workspaces.source.path)
securityContext:
runAsUser: 0
- name: inject-sbom-and-push
image: quay.io/redhat-appstudio/buildah:v1.31.0@sha256:34f12c7b72ec2c28f1ded0c494b428df4791c909f1f174dd21b8ed6a57cf5ddb
computeResources: {}
script: |
if [ -n "${PARAM_BUILDER_IMAGE}" ]; then
echo "WARNING: provided deprecated BUILDER_IMAGE parameter has no effect."
fi
base_image_name=$(buildah inspect --format '{{ index .ImageAnnotations "org.opencontainers.image.base.name"}}' $IMAGE | cut -f1 -d'@')
base_image_digest=$(buildah inspect --format '{{ index .ImageAnnotations "org.opencontainers.image.base.digest"}}' $IMAGE)
container=$(buildah from --pull-never $IMAGE)
buildah copy $container sbom-cyclonedx.json sbom-purl.json /root/buildinfo/content_manifests/
buildah config -a org.opencontainers.image.base.name=${base_image_name} -a org.opencontainers.image.base.digest=${base_image_digest} $container
buildah commit $container $IMAGE
status=-1
max_run=5
sleep_sec=10
for run in $(seq 1 $max_run); do
status=0
[ "$run" -gt 1 ] && sleep $sleep_sec
echo "Pushing sbom image to registry"
buildah push \
--tls-verify=$TLSVERIFY \
--digestfile $(workspaces.source.path)/image-digest $IMAGE \
docker://$IMAGE && break || status=$?
done
if [ "$status" -ne 0 ]; then
echo "Failed to push sbom image to registry after ${max_run} tries"
exit 1
fi
cat "$(workspaces.source.path)"/image-digest | tee $(results.IMAGE_DIGEST.path)
echo -n "$IMAGE" | tee $(results.IMAGE_URL.path)
securityContext:
runAsUser: 0
capabilities:
add:
- SETFCAP
volumeMounts:
- mountPath: /var/lib/containers
name: varlibcontainers
workingDir: $(workspaces.source.path)
- name: upload-sbom
image: quay.io/redhat-appstudio/cosign:v2.1.1@sha256:c883d6f8d39148f2cea71bff4622d196d89df3e510f36c140c097b932f0dd5d5
args:
- attach
- sbom
- --sbom
- sbom-cyclonedx.json
- --type
- cyclonedx
- $(params.IMAGE)
workingDir: $(workspaces.source.path)
volumes:
- name: varlibcontainers
emptyDir: {}
- name: etc-pki-entitlement
secret:
secretName: $(params.ENTITLEMENT_SECRET)
optional: true
- name: trusted-ca
configMap:
name: $(params.caTrustConfigMapName)
items:
- key: $(params.caTrustConfigMapKey)
path: ca-bundle.crt
optional: true
workspaces:
- name: source
description: Workspace containing the source code to build.