-
-
Notifications
You must be signed in to change notification settings - Fork 1
207 lines (182 loc) · 11.7 KB
/
validate-cdxa.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
# ********************************************************************************
# Copyright (c) 2024 Contributors to the Eclipse Foundation
#
# See the NOTICE file(s) with this work for additional
# information regarding copyright ownership.
#
# This program and the accompanying materials are made
# available under the terms of the Apache Software License 2.0
# which is available at https://www.apache.org/licenses/LICENSE-2.0.
#
# SPDX-License-Identifier: Apache-2.0
# ********************************************************************************
---
name: Validate CycloneDX CDXA
on:
pull_request:
branches: [main]
paths:
- ".github/workflows/validate-cdxa.yml"
- "**/*.xml"
# Cancel existing runs if user makes another push.
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
jobs:
validate_cyclonedx_cdxa:
name: validate_cdxa
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Download cyclonedx-cli
run: |
curl -L -O https://github.com/CycloneDX/cyclonedx-cli/releases/latest/download/cyclonedx-linux-x64
chmod +x cyclonedx-linux-x64
- name: Install libxml-xpath-perl
run: |
sudo apt-get update
sudo apt-get install libxml-xpath-perl
- name: Validate CDXA documents using cyclonedx-cli
run: |
XML_FILES=$(gh pr view "$PR_NUMBER" --repo "$REPOSITORY" --json files | jq -r '.files[] | .path' | grep "\.xml$" || true)
if [[ -n "$XML_FILES" ]]; then
echo "$XML_FILES" | while read XML_FILE; do
echo "CycloneDX validating file: $XML_FILE"
./cyclonedx-linux-x64 validate --input-file "$XML_FILE" --fail-on-errors --input-version v1_6
echo "Verifying Signature of file: $XML_FILE using public key $XML_FILE.sign.pub"
./cyclonedx-linux-x64 verify all "$XML_FILE" --key-file "$XML_FILE.sign.pub"
done
fi
env:
REPOSITORY: ${{ github.repository }}
PR_NUMBER: ${{ github.event.pull_request.number }}
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
- name: Validate CDXA content meets Temurin attestation requirements
run: |
XML_FILES=$(gh pr view "$PR_NUMBER" --repo "$REPOSITORY" --json files | jq -r '.files[] | .path' | grep "\.xml$" || true)
if [[ -n "$XML_FILES" ]]; then
echo "$XML_FILES" | while read XML_FILE; do
# Validate filename
if [[ "$XML_FILE" =~ ^([0-9]+)/jdk_([0-9]+)_0_([0-9]+)_([0-9]+)_([^_]+)_([^_]+)_([^\._]+)\.xml$ ]]; then
echo "Valid CDXA file name for update version $XML_FILE"
MAJOR_FOLDER=${BASH_REMATCH[1]}
MAJOR_VERSION=${BASH_REMATCH[2]}
UPDATE_VERSION=${BASH_REMATCH[3]}
BUILD_NUM=${BASH_REMATCH[4]}
PLATFORM_ARCH=${BASH_REMATCH[5]}
PLATFORM_OS=${BASH_REMATCH[6]}
ORG=${BASH_REMATCH[7]}
JDK_BUILD="jdk-$MAJOR_VERSION.0.$UPDATE_VERSION+$BUILD_NUM"
elif [[ "$XML_FILE" =~ ^([0-9]+)/jdk_([0-9]+)_([0-9]+)_([^_]+)_([^_]+)_([^\._]+)\.xml$ ]]; then
echo "Valid CDXA file name for new version $XML_FILE"
MAJOR_FOLDER=${BASH_REMATCH[1]}
MAJOR_VERSION=${BASH_REMATCH[2]}
UPDATE_VERSION="0"
BUILD_NUM=${BASH_REMATCH[3]}
PLATFORM_ARCH=${BASH_REMATCH[4]}
PLATFORM_OS=${BASH_REMATCH[5]}
ORG=${BASH_REMATCH[6]}
JDK_BUILD="jdk-$MAJOR_VERSION+$BUILD_NUM"
else
echo "$XML_FILE file name is not of the correct format:"
echo " N/jdk_M_0_U_B_(Arch)_(OS)_(Your Organisation).xml"
echo " or N/jdk_M_B_(Arch)_(OS)_(Your Organisation).xml"
exit 1
fi
# Print bom content
xpath -q -e '/bom' "$XML_FILE"
# Ensure 1 VERIFIED_REPRODUCIBLE_BUILD
if ! [ $(xpath -q -e 'count(/bom/declarations/claims/claim/predicate[text()="VERIFIED_REPRODUCIBLE_BUILD"])' "$XML_FILE") -eq 1 ]; then
echo "ERROR: $XML_FILE CDXA document does not contain a /bom/declarations/claims/claim/predicate with value VERIFIED_REPRODUCIBLE_BUILD"
exit 1
fi
# Verify claim target with bom-ref exists
TARGET_BOM_REF=$(xpath -q -e '/bom/declarations/claims/claim/predicate[text()="VERIFIED_REPRODUCIBLE_BUILD"]/../target/text()' "$XML_FILE")
if ! [ $(xpath -q -e 'count(/bom/declarations/targets/components/component[@bom-ref="'$TARGET_BOM_REF'"])' "$XML_FILE") -eq 1 ]; then
echo "ERROR: $XML_FILE CDXA document does not contain a /bom/declarations/targets/components/component with 'bom-ref' == $TARGET_BOM_REF"
exit 1
fi
# Verify Component.name of format: Temurin <JDK_BUILD> <PLATFORM_ARCH>_<PLATFORM_OS>
COMPONENT_NAME=$(xpath -q -e '/bom/declarations/targets/components/component[@bom-ref="'$TARGET_BOM_REF'"]/name/text()' "$XML_FILE")
VALID_VALUE="Temurin ${JDK_BUILD} ${PLATFORM_ARCH}_${PLATFORM_OS}"
if [[ ! "$COMPONENT_NAME" = "$VALID_VALUE" ]]; then
echo "ERROR: $XML_FILE CDXA document /bom/declarations/targets/components/component/name($COMPONENT_NAME) is not the correct format: $VALID_VALUE"
exit 1
fi
# Verify Component.version of format: <JDK_BUILD>
COMPONENT_VERSION=$(xpath -q -e '/bom/declarations/targets/components/component[@bom-ref="'$TARGET_BOM_REF'"]/version/text()' "$XML_FILE")
VALID_VALUE="${JDK_BUILD}"
if [[ ! "$COMPONENT_VERSION" = "$VALID_VALUE" ]]; then
echo "ERROR: $XML_FILE CDXA document /bom/declarations/targets/components/component/version($COMPONENT_VERSION) is not the correct value: $VALID_VALUE"
exit 1
fi
# Verify Component.property(platform) of format: <PLATFORM_ARCH>_<PLATFORM_OS>
COMPONENT_PLATFORM=$(xpath -q -e '/bom/declarations/targets/components/component[@bom-ref="'$TARGET_BOM_REF'"]/properties/property[@name="platform"]/text()' "$XML_FILE")
VALID_VALUE="${PLATFORM_ARCH}_${PLATFORM_OS}"
if [[ ! "$COMPONENT_PLATFORM" = "$VALID_VALUE" ]]; then
echo "ERROR: $XML_FILE CDXA document /bom/declarations/targets/components/component/properties/property[@name='platform']($COMPONENT_PLATFORM) is not the correct value: $VALID_VALUE"
exit 1
fi
# Verify Component.externalReferences.reference(distribution).url matches https://api.adoptium.net/v3/binary/version/<release>/<os>/<arch>/jdk/hotspot/normal/eclipse
EXT_REF_URL=$(xpath -q -e '/bom/declarations/targets/components/component[@bom-ref="'$TARGET_BOM_REF'"]/externalReferences/reference[@type="distribution"]/url/text()' "$XML_FILE")
VALID_VALUE="https://api.adoptium.net/v3/binary/version/${JDK_BUILD}/${PLATFORM_OS}/${PLATFORM_ARCH}/jdk/hotspot/normal/eclipse"
if [[ ! "$EXT_REF_URL" = "$VALID_VALUE" ]]; then
echo "ERROR: $XML_FILE CDXA document /bom/declarations/targets/components/component/externalReferences/reference[@type='distribution']/url($EXT_REF_URL) is not the correct value: $VALID_VALUE"
exit 1
fi
# Verify hash matches Adoptium published hash for the given release
ADOPTIUM_HASH=$(curl -L https://api.adoptium.net/v3/checksum/version/${JDK_BUILD}/${PLATFORM_OS}/${PLATFORM_ARCH}/jdk/hotspot/normal/eclipse | cut -d' ' -f1)
CDXA_HASH=$(xpath -q -e '/bom/declarations/targets/components/component[@bom-ref="'$TARGET_BOM_REF'"]/externalReferences/reference[@type="distribution"]/hashes/hash[@alg="SHA-256"]/text()' "$XML_FILE")
if [[ ! "$ADOPTIUM_HASH" = "$CDXA_HASH" ]]; then
echo "ERROR: $XML_FILE CDXA document /bom/declarations/targets/components/component/externalReferences/reference[@type='distribution']/hashes/hash[SHA-256]($CDXA_HASH) is not the correct value: $ADOPTIUM_HASH"
exit 1
fi
# Verify one assessor exists
if ! [ $(xpath -q -e 'count(/bom/declarations/assessors/assessor)' "$XML_FILE") -eq 1 ]; then
echo "ERROR: $XML_FILE CDXA document does not contain a single /bom/declarations/assessors/assessor"
exit 1
fi
# Verify assessor is thirdParty
ASSESSOR_THIRD_PARTY=$(xpath -q -e '/bom/declarations/assessors/assessor[1]/thirdParty/text()' "$XML_FILE")
VALID_VALUE="true"
if [[ ! "$ASSESSOR_THIRD_PARTY" = "$VALID_VALUE" ]]; then
echo "ERROR: $XML_FILE CDXA document /bom/declarations/assessors/assessor[1]/thirdParty($ASSESSOR_THIRD_PARTY) is not the correct value: $VALID_VALUE"
exit 1
fi
# Verify assessor has an organization name
ASSESSOR_ORG_NAME=$(xpath -q -e '/bom/declarations/assessors/assessor[1]/organization/name/text()' "$XML_FILE")
if [[ -z "$ASSESSOR_ORG_NAME" ]]; then
echo "ERROR: $XML_FILE CDXA document /bom/declarations/assessors/assessor/organization/name is not specified"
exit 1
fi
# Verify assessor bom-ref against attestation
ASSESSOR_BOM_REF=$(xpath -q -e 'string(/bom/declarations/assessors/assessor[1]/@bom-ref)' "$XML_FILE")
ATTESTATION_ASSESSOR=$(xpath -q -e '/bom/declarations/attestations/attestation[1]/assessor/text()' "$XML_FILE")
if [[ ! "$ATTESTATION_ASSESSOR" = "$ASSESSOR_BOM_REF" ]]; then
echo "ERROR: $XML_FILE CDXA document /bom/declarations/attestations/attestations/assessor($ATTESTATION_ASSESSOR) does not match /bom/declarations/assessors/assessor/@bom-ref($ASSESSOR_BOM_REF)"
exit 1
fi
# Verify claim bom-ref against attestation
CLAIM_BOM_REF=$(xpath -q -e 'string(/bom/declarations/claims/claim/predicate[text()="VERIFIED_REPRODUCIBLE_BUILD"]/../@bom-ref)' "$XML_FILE")
ATTESTATION_CLAIM=$(xpath -q -e '/bom/declarations/attestations/attestation[1]/map/claims/claim[1]/text()' "$XML_FILE")
if [[ ! "$ATTESTATION_CLAIM" = "$CLAIM_BOM_REF" ]]; then
echo "ERROR: $XML_FILE CDXA document /bom/declarations/attestations/attestations/map/claims/claim($ATTESTATION_CLAIM) does not match /bom/declarations/claims/claim/@bom-ref($CLAIM_BOM_REF)"
exit 1
fi
# Verify an affirmation exists
if ! [ $(xpath -q -e 'count(/bom/declarations/affirmation)' "$XML_FILE") -eq 1 ]; then
echo "ERROR: $XML_FILE CDXA document does not contain a /bom/declarations/affirmation"
exit 1
fi
# Verify affirmation has a statement
AFFIRMATION_STMT=$(xpath -q -e '/bom/declarations/affirmation/statement' "$XML_FILE")
if [[ -z "$AFFIRMATION_STMT" ]]; then
echo "ERROR: $XML_FILE CDXA document /bom/declarations/affirmation/statement is not specified"
exit 1
fi
done
fi
env:
REPOSITORY: ${{ github.repository }}
PR_NUMBER: ${{ github.event.pull_request.number }}
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}