1CONTAINERS-POLICY.JSON(5)(policy.json)  CONTAINERS-POLICY.JSON(5)(policy.json)
2
3
4
5Miloslav Trmač September 2016
6
7

NAME

9       containers-policy.json  -  syntax for the signature verification policy
10       file
11
12

DESCRIPTION

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

FORMAT

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

Supported transports and their scopes

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

Policy Requirements

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

Examples

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

SEE ALSO

426       atomic(1)
427
428

HISTORY

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
439Page                                  ManCONTAINERS-POLICY.JSON(5)(policy.json)
Impressum