1CONTAINERS-POLICY.JSON(5) Page CONTAINERS-POLICY.JSON(5)
2
3
4
5Miloslav Trmač September 2016
6
7
9 containers-policy.json - syntax for the signature verification policy
10 file
11
12
14 Signature verification policy files are used to specify policy, e.g.
15 trusted keys, applicable when deciding whether to accept an image, or
16 individual signatures of that image, as valid.
17
18
19 By default, the policy is read from $HOME/.config/containers/pol‐
20 icy.json, if it exists, otherwise from /etc/containers/policy.json;
21 applications performing verification may allow using a different policy
22 instead.
23
24
26 The signature verification policy file, usually called policy.json,
27 uses a JSON format. Unlike some other JSON files, its parsing is
28 fairly strict: unrecognized, duplicated or otherwise invalid fields
29 cause the entire file, and usually the entire operation, to be re‐
30 jected.
31
32
33 The purpose of the policy file is to define a set of policy require‐
34 ments for a container image, usually depending on its location (where
35 it is being pulled from) or otherwise defined identity.
36
37
38 Policy requirements can be defined for:
39
40
41 • An individual scope in a transport. The transport values are
42 the same as the transport prefixes when pushing/pulling images
43 (e.g. docker:, atomic:), and scope values are defined by each
44 transport; see below for more details.
45
46
47
48 Usually, a scope can be defined to match a single image, and various
49 prefixes of
50 such a most specific scope define namespaces of matching images. - A
51 default policy for a single transport, expressed using an empty string
52 as a scope - A global default policy.
53
54
55 If multiple policy requirements match a given image, only the require‐
56 ments from the most specific match apply, the more general policy re‐
57 quirements definitions are ignored.
58
59
60 This is expressed in JSON using the top-level syntax
61
62
63 {
64 "default": [/* policy requirements: global default */]
65 "transports": {
66 transport_name: {
67 "": [/* policy requirements: default for transport $transport_name */],
68 scope_1: [/* policy requirements: default for $scope_1 in $transport_name */],
69 scope_2: [/*…*/]
70 /*…*/
71 },
72 transport_name_2: {/*…*/}
73 /*…*/
74 }
75 }
76
77
78
79 The global default set of policy requirements is mandatory; all of the
80 other fields (transports itself, any specific transport, the transport-
81 specific default, etc.) are optional.
82
83
85 atomic:
86 The atomic: transport refers to images in an Atomic Registry.
87
88
89 Supported scopes use the form hostname[:port][/namespace[/imagestream
90 [:tag]]], i.e. either specifying a complete name of a tagged image, or
91 prefix denoting a host/namespace/image stream or a wildcarded expres‐
92 sion for matching all subdomains. For wildcarded subdomain matching,
93 *.example.com is a valid case, but example*.*.com is not.
94
95
96 Note: The hostname and port refer to the container registry host and
97 port (the one used e.g. for docker pull), not to the OpenShift API host
98 and port.
99
100
101 dir:
102 The dir: transport refers to images stored in local directories.
103
104
105 Supported scopes are paths of directories (either containing a single
106 image or subdirectories possibly containing images).
107
108
109 Note: The paths must be absolute and contain no symlinks. Paths violat‐
110 ing these requirements may be silently ignored.
111
112
113 The top-level scope "/" is forbidden; use the transport default scope
114 "", for consistency with other transports.
115
116
117 docker:
118 The docker: transport refers to images in a registry implementing the
119 "Docker Registry HTTP API V2".
120
121
122 Scopes matching individual images are named Docker references in the
123 fully expanded form, either using a tag or digest. For example,
124 docker.io/library/busybox:latest (not busybox:latest).
125
126
127 More general scopes are prefixes of individual-image scopes, and spec‐
128 ify a repository (by omitting the tag or digest), a repository name‐
129 space, or a registry host (by only specifying the host name) or a wild‐
130 carded expression for matching all subdomains. For wildcarded subdomain
131 matching, *.example.com is a valid case, but example*.*.com is not.
132
133
134 oci:
135 The oci: transport refers to images in directories compliant with "Open
136 Container Image Layout Specification".
137
138
139 Supported scopes use the form directory:tag, and directory referring to
140 a directory containing one or more tags, or any of the parent directo‐
141 ries.
142
143
144 Note: See dir: above for semantics and restrictions on the directory
145 paths, they apply to oci: equivalently.
146
147
148 tarball:
149 The tarball: transport refers to tarred up container root filesystems.
150
151
152 Scopes are ignored.
153
154
156 Using the mechanisms above, a set of policy requirements is looked up.
157 The policy requirements are represented as a JSON array of individual
158 requirement objects. For an image to be accepted, all of the require‐
159 ments must be satisfied simultaneously.
160
161
162 The policy requirements can also be used to decide whether an individ‐
163 ual signature is accepted (= is signed by a recognized key of a known
164 author); in that case some requirements may apply only to some signa‐
165 tures, but each signature must be accepted by at least one requirement
166 object.
167
168
169 The following requirement objects are supported:
170
171
172 insecureAcceptAnything
173 A simple requirement with the following syntax
174
175
176 {"type":"insecureAcceptAnything"}
177
178
179
180 This requirement accepts any image (but note that other requirements in
181 the array still apply).
182
183
184 When deciding to accept an individual signature, this requirement does
185 not have any effect; it does not cause the signature to be accepted,
186 though.
187
188
189 This is useful primarily for policy scopes where no signature verifica‐
190 tion is required; because the array of policy requirements must not be
191 empty, this requirement is used to represent the lack of requirements
192 explicitly.
193
194
195 reject
196 A simple requirement with the following syntax:
197
198
199 {"type":"reject"}
200
201
202
203 This requirement rejects every image, and every signature.
204
205
206 signedBy
207 This requirement requires an image to be signed with an expected iden‐
208 tity, or accepts a signature if it is using an expected identity and
209 key.
210
211
212 {
213 "type": "signedBy",
214 "keyType": "GPGKeys", /* The only currently supported value */
215 "keyPath": "/path/to/local/keyring/file",
216 "keyData": "base64-encoded-keyring-data",
217 "signedIdentity": identity_requirement
218 }
219
220
221
222 Exactly one of keyPath and keyData must be present, containing a GPG
223 keyring of one or more public keys. Only signatures made by these keys
224 are accepted.
225
226
227 The signedIdentity field, a JSON object, specifies what image identity
228 the signature claims about the image. One of the following alterna‐
229 tives are supported:
230
231
232 • The identity in the signature must exactly match the image
233 identity. Note that with this, referencing an image by digest
234 (with a signature claiming a repository:tag identity) will
235 fail.
236
237
238
239 {"type":"matchExact"}
240
241
242
243 • If the image identity carries a tag, the identity in the sig‐
244 nature must exactly match; if the image identity uses a digest
245 reference, the identity in the signature must be in the same
246 repository as the image identity (using any tag).
247
248
249
250 (Note that with images identified using digest references, the digest
251 from the reference is validated even before signature verification
252 starts.)
253
254
255 {"type":"matchRepoDigestOrExact"}
256
257
258
259 • The identity in the signature must be in the same repository
260 as the image identity. This is useful e.g. to pull an image
261 using the :latest tag when the image is signed with a tag
262 specifying an exact image version.
263
264
265
266 {"type":"matchRepository"}
267
268
269
270 • The identity in the signature must exactly match a specified
271 identity. This is useful e.g. when locally mirroring images
272 signed using their public identity.
273
274
275
276 {
277 "type": "exactReference",
278 "dockerReference": docker_reference_value
279 }
280
281
282
283 • The identity in the signature must be in the same repository
284 as a specified identity. This combines the properties of
285 matchRepository and exactReference.
286
287
288
289 {
290 "type": "exactRepository",
291 "dockerRepository": docker_repository_value
292 }
293
294
295
296 • Prefix remapping:
297
298
299
300 If the image identity matches the specified prefix, that prefix is re‐
301 placed by the specified “signed prefix”
302 (otherwise it is used as unchanged and no remapping takes place);
303 matching then follows the matchRepoDigestOrExact semantics documented
304 above
305 (i.e. if the image identity carries a tag, the identity in the signa‐
306 ture must exactly match,
307 if it uses a digest reference, the repository must match).
308
309
310 The prefix and signedPrefix values can be either host[:port] values
311 (matching exactly the same host[:port], string),
312 repository namespaces, or repositories (i.e. they must not contain
313 tags/digests),
314 and match as prefixes of the fully expanded form.
315 For example, docker.io/library/busybox (not busybox) to specify that
316 single repository,
317 or docker.io/library (not an empty string) to specify the parent
318 namespace of docker.io/library/busybox==busybox).
319
320
321 The prefix value is usually the same as the scope containing the parent
322 signedBy requirement.
323
324
325 {
326 "type": "remapIdentity",
327 "prefix": prefix,
328 "signedPrefix": prefix,
329 }
330
331
332
333 If the signedIdentity field is missing, it is treated as matchRepoDige‐
334 stOrExact.
335
336
337 Note: matchExact, matchRepoDigestOrExact and matchRepository can be
338 only used if a Docker-like image identity is provided by the transport.
339 In particular, the dir: and oci: transports can be only used with exac‐
340 tReference or exactRepository.
341
342
344 It is strongly recommended to set the default policy to reject, and
345 then selectively allow individual transports and scopes as desired.
346
347
348 A reasonably locked-down system
349 (Note that the /*…*/ comments are not valid in JSON, and must not be
350 used in real policies.)
351
352
353 {
354 "default": [{"type": "reject"}], /* Reject anything not explicitly allowed */
355 "transports": {
356 "docker": {
357 /* Allow installing images from a specific repository namespace, without cryptographic verification.
358 This namespace includes images like openshift/hello-openshift and openshift/origin. */
359 "docker.io/openshift": [{"type": "insecureAcceptAnything"}],
360 /* Similarly, allow installing the “official” busybox images. Note how the fully expanded
361 form, with the explicit /library/, must be used. */
362 "docker.io/library/busybox": [{"type": "insecureAcceptAnything"}]
363 /* Allow installing images from all subdomains */
364 "*.temporary-project.example.com": [{"type": "insecureAcceptAnything"}]
365 /* Other docker: images use the global default policy and are rejected */
366 },
367 "dir": {
368 "": [{"type": "insecureAcceptAnything"}] /* Allow any images originating in local directories */
369 },
370 "atomic": {
371 /* The common case: using a known key for a repository or set of repositories */
372 "hostname:5000/myns/official": [
373 {
374 "type": "signedBy",
375 "keyType": "GPGKeys",
376 "keyPath": "/path/to/official-pubkey.gpg"
377 }
378 ],
379 /* A more complex example, for a repository which contains a mirror of a third-party product,
380 which must be signed-off by local IT */
381 "hostname:5000/vendor/product": [
382 { /* Require the image to be signed by the original vendor, using the vendor's repository location. */
383 "type": "signedBy",
384 "keyType": "GPGKeys",
385 "keyPath": "/path/to/vendor-pubkey.gpg",
386 "signedIdentity": {
387 "type": "exactRepository",
388 "dockerRepository": "vendor-hostname/product/repository"
389 }
390 },
391 { /* Require the image to _also_ be signed by a local reviewer. */
392 "type": "signedBy",
393 "keyType": "GPGKeys",
394 "keyPath": "/path/to/reviewer-pubkey.gpg"
395 }
396 ],
397 /* A way to mirror many repositories from a single vendor */
398 "private-mirror:5000/vendor-mirror": [
399 { /* Require the image to be signed by the original vendor, using the vendor's repository location.
400 For example, private-mirror:5000/vendor-mirror/productA/image1:latest needs to be signed as
401 vendor.example/productA/image1:latest . */
402 "type": "signedBy",
403 "keyType": "GPGKeys",
404 "keyPath": "/path/to/vendor-pubkey.gpg",
405 "signedIdentity": {
406 "type": "remapIdentity",
407 "prefix": "private-mirror:5000/vendor-mirror",
408 "signedPrefix": "vendor.example.com",
409 }
410 }
411 ]
412 }
413 }
414 }
415
416
417
418 Completely disable security, allow all images, do not trust any signatures
419 {
420 "default": [{"type": "insecureAcceptAnything"}]
421 }
422
423
424
426 atomic(1)
427
428
430 August 2018, Rename to containers-policy.json(5) by Valentin Rothberg
431 vrothberg@suse.com ⟨mailto:vrothberg@suse.com⟩
432
433
434 September 2016, Originally compiled by Miloslav Trmač mitr@redhat.com
435 ⟨mailto:mitr@redhat.com⟩
436
437
438
439Man policy.json CONTAINERS-POLICY.JSON(5)