1
+ <?xml version =' 1.1' encoding =' UTF-8' ?>
2
+ <
org .jenkinsci.plugins.configfiles.GlobalConfigFiles
plugin =
" [email protected] _4518b_" >
3
+ <configs class =" sorted-set" >
4
+ <comparator class =" org.jenkinsci.plugins.configfiles.ConfigByIdComparator" />
5
+ <org .jenkinsci.plugins.configfiles.custom.CustomConfig>
6
+ <id >create.att.predicate.sh</id >
7
+ <name >create.att.predicate.sh</name >
8
+ <comment ></comment >
9
+ <content >#
10
+ # Create attestation predicate for RHTAP Jenkins builds
11
+ #
12
+ # Useful references:
13
+ # - https://slsa.dev/spec/v1.0/provenance
14
+ # - https://www.jenkins.io/doc/book/pipeline/jenkinsfile/#using-environment-variables
15
+ # - http://localhost:8080/env-vars.html/
16
+ # (Replace localhost with your Jenkins instance)
17
+ #
18
+ yq -o=json -I=0 << EOT
19
+ ---
20
+ buildDefinition:
21
+ buildType: " https://redhat.com/rhtap/slsa-build-types/${CI_TYPE}-build/v1"
22
+ externalParameters: {}
23
+ internalParameters: {}
24
+ resolvedDependencies:
25
+ - uri: " git+${GIT_URL}"
26
+ digest:
27
+ gitCommit: " ${GIT_COMMIT}"
28
+
29
+ runDetails:
30
+ builder:
31
+ id: " ${NODE_NAME}"
32
+ builderDependencies: []
33
+ version:
34
+ # Not sure if this is the right place for these...
35
+ buildNumber: " ${BUILD_NUMBER}"
36
+ jobName: " ${JOB_NAME}"
37
+ executorNumber: " ${EXECUTOR_NUMBER}"
38
+ jenkinsHome: " ${JENKINS_HOME}"
39
+ buildUrl: " ${BUILD_URL}"
40
+ jobUrl: " ${JOB_URL}"
41
+
42
+ metadata:
43
+ invocationID: " ${BUILD_TAG}"
44
+ startedOn: " $(cat $RESULTS/init/START_TIME)"
45
+ # Inaccurate, but maybe close enough
46
+ finishedOn: " $(date +%Y-%m-%dT%H:%M:%SZ)"
47
+
48
+ byproducts:
49
+ - name: SBOM_BLOB
50
+ uri: " $(cat " $BASE_RESULTS" /buildah-rhtap/SBOM_BLOB_URL)"
51
+
52
+ EOT</content >
53
+ <providerId >org.jenkinsci.plugins.configfiles.custom.CustomConfig</providerId >
54
+ <customizedCredentialMappings />
55
+ </org .jenkinsci.plugins.configfiles.custom.CustomConfig>
56
+ <org .jenkinsci.plugins.configfiles.custom.CustomConfig>
57
+ <id >merge.sboms.py</id >
58
+ <name >merge.sboms.py</name >
59
+ <comment ></comment >
60
+ <content >#!/bin/python3
61
+ import hashlib
62
+ import json
63
+ import os
64
+ import re
65
+
66
+ ### load SBOMs ###
67
+
68
+ with open(os.getenv(" TEMP_DIR" ) + " /files/sbom-image.json" ) as f:
69
+ image_sbom = json.load(f)
70
+
71
+ with open(os.getenv(" TEMP_DIR" ) + " /files/sbom-source.json" ) as f:
72
+ source_sbom = json.load(f)
73
+
74
+
75
+ ### attempt to deduplicate components ###
76
+
77
+ component_list = image_sbom.get(" components" , [])
78
+ existing_purls = [c[" purl" ] for c in component_list if " purl" in c]
79
+
80
+ for component in source_sbom.get(" components" , []):
81
+ if " purl" in component:
82
+ if component[" purl" ] not in existing_purls:
83
+ component_list.append(component)
84
+ existing_purls.append(component[" purl" ])
85
+ else:
86
+ # We won' t try to deduplicate components that lack a purl.
87
+ # This should only happen with operating-system type components,
88
+ # which are only reported in the image SBOM.
89
+ component_list.append(component)
90
+
91
+ component_list.sort(key=lambda c: c[" type" ] + c[" name" ])
92
+ image_sbom[" components" ] = component_list
93
+
94
+
95
+ ### write the CycloneDX unified SBOM ###
96
+
97
+ with open(os.getenv(" TEMP_DIR" ) + " /files/sbom-cyclonedx.json" , " w" ) as f:
98
+ json.dump(image_sbom, f, indent=4)
99
+
100
+
101
+ ### write the SBOM blob URL result ###
102
+
103
+ with open(os.getenv(" TEMP_DIR" ) + " /files/sbom-cyclonedx.json" , " rb" ) as f:
104
+ sbom_digest = hashlib.file_digest(f, " sha256" ).hexdigest()
105
+
106
+ # https://github.com/opencontainers/distribution-spec/blob/main/spec.md?plain=1#L160
107
+ tag_regex = " [a-zA-Z0-9_][a-zA-Z0-9._-]{0,127}"
108
+
109
+ # the tag must be after a colon, but always at the end of the string
110
+ # this avoids conflict with port numbers
111
+ image_without_tag = re.sub(f" :{tag_regex}\$" , "" , os.getenv(" IMAGE" ))
112
+
113
+ sbom_blob_url = f" {image_without_tag}@sha256:{sbom_digest}"
114
+
115
+ with open(os.getenv(" RESULT_PATH" ), " w" ) as f:
116
+ f.write(sbom_blob_url)</content >
117
+ <providerId >org.jenkinsci.plugins.configfiles.custom.CustomConfig</providerId >
118
+ <customizedCredentialMappings />
119
+ </org .jenkinsci.plugins.configfiles.custom.CustomConfig>
120
+ </configs >
121
+ </org .jenkinsci.plugins.configfiles.GlobalConfigFiles>
0 commit comments