-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathverifying_red_hat_container_image_signatures
352 lines (323 loc) · 12.1 KB
/
verifying_red_hat_container_image_signatures
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
Verifying Red Hat container image signatures in OpenShift Container Platform 4
Red Hat delivers signatures for the images in the Red Hat Container Registries. Those signatures can be automatically verified when being pulled to OpenShift Container Platform (OCP) 4 clusters using Machine Config.
Most of the images that make OCP 4 are shipped from quay.io, and only the release image is signed. The release images refers to the rest of the OCP 4 images by digest making supply chain attacks harder to pull off. However some extensions to OCP 4 such as Logging, Monitoring, and Service Mesh are shipped as operators from the Operator Lifecycle Manager. Those images ship from the Red Hat Container Registry (registry.redhat.io). In order to verify the integrity of those images between Red Hat registries and your infrastructure it's a good idea to enable signature verification by following the instructions that follow.
Here are the commands to enable signature verification on OCP 4:
1) Create the files which link the registry URLs to the sigstore, and specifies the key to verify the images with:
# cat > policy.json <<EOF
{
"default": [
{
"type": "insecureAcceptAnything"
}
],
"transports": {
"docker": {
"registry.access.redhat.com": [
{
"type": "signedBy",
"keyType": "GPGKeys",
"keyPath": "/etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release"
}
],
"registry.redhat.io": [
{
"type": "signedBy",
"keyType": "GPGKeys",
"keyPath": "/etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release"
}
]
},
"docker-daemon": {
"": [
{
"type": "insecureAcceptAnything"
}
]
}
}
}
EOF
# cat <<EOF > registry.access.redhat.com.yaml
docker:
registry.access.redhat.com:
sigstore: https://access.redhat.com/webassets/docker/content/sigstore
EOF
# cat <<EOF > registry.redhat.io.yaml
docker:
registry.redhat.io:
sigstore: https://registry.redhat.io/containers/sigstore
EOF
2) Base64 encode those files ready to be feed into the machine config template
# export ARC_REG=$( cat registry.access.redhat.com.yaml | base64 -w0 )
# export RIO_REG=$( cat registry.redhat.io.yaml | base64 -w0 )
# export POLICY_CONFIG=$( cat policy.json | base64 -w0 )
3) Create a machine config which writes those files to disk on the worker nodes:
cat > 51-worker-rh-registry-trust.yaml <<EOF
apiVersion: machineconfiguration.openshift.io/v1
kind: MachineConfig
metadata:
labels:
machineconfiguration.openshift.io/role: worker
name: 51-worker-rh-registry-trust
spec:
config:
ignition:
config: {}
security:
tls: {}
timeouts: {}
version: 2.2.0
networkd: {}
passwd: {}
storage:
files:
- contents:
source: data:text/plain;charset=utf-8;base64,${ARC_REG}
verification: {}
filesystem: root
mode: 420
path: /etc/containers/registries.d/registry.access.redhat.com.yaml
- contents:
source: data:text/plain;charset=utf-8;base64,${RIO_REG}
verification: {}
filesystem: root
mode: 420
path: /etc/containers/registries.d/registry.redhat.io.yaml
- contents:
source: data:text/plain;charset=utf-8;base64,${POLICY_CONFIG}
verification: {}
filesystem: root
mode: 420
path: /etc/containers/policy.json
osImageURL: ""
EOF
5) Apply the worker Machine Config changes to the cluster:
oc apply -f 51-worker-rh-registry-trust.yaml
NOTE: Usually the master nodes won't be running Operators or other workload pods from the OLM, but it doesn't hurt to also apply the configuration to the master Machine Config. If you are using oc debug master/<node> for example that pulls an image for the Red Hat Container registry
6) Repeat a similar command on the master Machine Config:
cat > 51-master-rh-registry-trust.yaml <<EOF
apiVersion: machineconfiguration.openshift.io/v1
kind: MachineConfig
metadata:
labels:
machineconfiguration.openshift.io/role: master
name: 51-master-rh-registry-trust
spec:
config:
ignition:
config: {}
security:
tls: {}
timeouts: {}
version: 2.2.0
networkd: {}
passwd: {}
storage:
files:
- contents:
source: data:text/plain;charset=utf-8;base64,${ARC_REG}
verification: {}
filesystem: root
mode: 420
path: /etc/containers/registries.d/registry.access.redhat.com.yaml
- contents:
source: data:text/plain;charset=utf-8;base64,${RIO_REG}
verification: {}
filesystem: root
mode: 420
path: /etc/containers/registries.d/registry.redhat.io.yaml
- contents:
source: data:text/plain;charset=utf-8;base64,${POLICY_CONFIG}
verification: {}
filesystem: root
mode: 420
path: /etc/containers/policy.json
osImageURL: ""
EOF
7) Apply the machine Machine Config changes to the cluster:
oc apply -f 51-master-rh-registry-trust.yaml
8) The machine-config-controller will notice the new MachineConfig and generate a new "rendered" version that looks like rendered-worker-(hash). Use oc describe machineconfigpool/worker to monitor the status of the rollout of the new rendered config to each node.
Example
---
$ oc describe machineconfigpool/worker
Name: worker
Namespace:
Labels: machineconfiguration.openshift.io/mco-built-in=
Annotations: <none>
API Version: machineconfiguration.openshift.io/v1
Kind: MachineConfigPool
Metadata:
Creation Timestamp: 2019-12-19T02:02:12Z
Generation: 3
Resource Version: 16229
Self Link: /apis/machineconfiguration.openshift.io/v1/machineconfigpools/worker
UID: 92697796-2203-11ea-b48c-fa163e3940e5
Spec:
Configuration:
Name: rendered-worker-f6819366eb455a401c42f8d96ab25c02
Source:
API Version: machineconfiguration.openshift.io/v1
Kind: MachineConfig
Name: 00-worker
API Version: machineconfiguration.openshift.io/v1
Kind: MachineConfig
Name: 01-worker-container-runtime
API Version: machineconfiguration.openshift.io/v1
Kind: MachineConfig
Name: 01-worker-kubelet
API Version: machineconfiguration.openshift.io/v1
Kind: MachineConfig
Name: 51-worker-rh-registry-trust
API Version: machineconfiguration.openshift.io/v1
Kind: MachineConfig
Name: 99-worker-92697796-2203-11ea-b48c-fa163e3940e5-registries
API Version: machineconfiguration.openshift.io/v1
Kind: MachineConfig
Name: 99-worker-ssh
Machine Config Selector:
Match Labels:
machineconfiguration.openshift.io/role: worker
Node Selector:
Match Labels:
node-role.kubernetes.io/worker:
Paused: false
Status:
Conditions:
Last Transition Time: 2019-12-19T02:03:27Z
Message:
Reason:
Status: False
Type: RenderDegraded
Last Transition Time: 2019-12-19T02:03:43Z
Message:
Reason:
Status: False
Type: NodeDegraded
Last Transition Time: 2019-12-19T02:03:43Z
Message:
Reason:
Status: False
Type: Degraded
Last Transition Time: 2019-12-19T02:28:23Z
Message:
Reason:
Status: False
Type: Updated
Last Transition Time: 2019-12-19T02:28:23Z
Message: All nodes are updating to rendered-worker-f6819366eb455a401c42f8d96ab25c02
Reason:
Status: True
Type: Updating
Configuration:
Name: rendered-worker-d9b3f4ffcfd65c30dcf591a0e8cf9b2e
Source:
API Version: machineconfiguration.openshift.io/v1
Kind: MachineConfig
Name: 00-worker
API Version: machineconfiguration.openshift.io/v1
Kind: MachineConfig
Name: 01-worker-container-runtime
API Version: machineconfiguration.openshift.io/v1
Kind: MachineConfig
Name: 01-worker-kubelet
API Version: machineconfiguration.openshift.io/v1
Kind: MachineConfig
Name: 99-worker-92697796-2203-11ea-b48c-fa163e3940e5-registries
API Version: machineconfiguration.openshift.io/v1
Kind: MachineConfig
Name: 99-worker-ssh
Degraded Machine Count: 0
Machine Count: 1
Observed Generation: 3
Ready Machine Count: 0
Unavailable Machine Count: 1
Updated Machine Count: 0
Events: <none>
---
Which will be later updated:
$ oc describe machineconfigpool/worker
...
Last Transition Time: 2019-12-19T04:53:09Z
Message:
Reason:
Status: False
Type: Updated
Last Transition Time: 2019-12-19T04:53:09Z
Message: All nodes are updating to rendered-worker-44d515bcc439808af36f591f3e3ef117
Reason:
Status: True
Type: Updating
Configuration:
Name: rendered-worker-f6819366eb455a401c42f8d96ab25c02
Source:
API Version: machineconfiguration.openshift.io/v1
Kind: MachineConfig
Name: 00-worker
API Version: machineconfiguration.openshift.io/v1
Kind: MachineConfig
Name: 01-worker-container-runtime
API Version: machineconfiguration.openshift.io/v1
Kind: MachineConfig
Name: 01-worker-kubelet
API Version: machineconfiguration.openshift.io/v1
Kind: MachineConfig
Name: 51-worker-rh-registry-trust
API Version: machineconfiguration.openshift.io/v1
Kind: MachineConfig
Name: 99-worker-92697796-2203-11ea-b48c-fa163e3940e5-registries
API Version: machineconfiguration.openshift.io/v1
Kind: MachineConfig
Name: 99-worker-ssh
Degraded Machine Count: 0
Machine Count: 1
Observed Generation: 4
...
Notice the Observed Generation count has been incremented and the Configuration Source now includes 51-worker-rh-registry-trust
9) To verify the files have changed on disk you can use:
$ oc debug node/<node> -- chroot /host cat /etc/containers/policy.json
Starting pod/<node>-debug ...
To use host binaries, run `chroot /host`
{
"default": [
{
"type": "insecureAcceptAnything"
}
],
"transports": {
"docker": {
"registry.access.redhat.com": [
{
"type": "signedBy",
"keyType": "GPGKeys",
"keyPath": "/etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release"
}
],
"registry.redhat.io": [
{
"type": "signedBy",
"keyType": "GPGKeys",
"keyPath": "/etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release"
}
]
},
"docker-daemon": {
"": [
{
"type": "insecureAcceptAnything"
}
]
}
}
}
$ oc debug node/<node> -- chroot /host cat /etc/containers/registries.d/registry.redhat.io.yaml
Starting pod/<node>-debug ...
To use host binaries, run `chroot /host`
docker:
registry.redhat.io:
sigstore: https://registry.redhat.io/containers/sigstore
$ oc debug node/<node> -- chroot /host cat /etc/containers/registries.d/registry.access.redhat.com.yaml
Starting pod/<node>-debug ...
To use host binaries, run `chroot /host`
docker:
registry.access.redhat.com:
sigstore: https://access.redhat.com/webassets/docker/content/sigstore