Provided by: golang-github-containers-image_5.29.2-2_all bug

NAME

       containers-policy.json - syntax for the signature verification policy file

DESCRIPTION

       Signature  verification  policy  files  are  used  to  specify  policy, e.g. trusted keys,
       applicable when deciding whether to accept an image,  or  individual  signatures  of  that
       image, as valid.

       By  default,  the  policy is read from $HOME/.config/containers/policy.json, if it exists,
       otherwise from  /etc/containers/policy.json;   applications  performing  verification  may
       allow using a different policy instead.

FORMAT

       The  signature  verification  policy file, usually called policy.json, uses a JSON format.
       Unlike some other JSON files, its parsing is fairly strict:  unrecognized,  duplicated  or
       otherwise  invalid  fields  cause the entire file, and usually the entire operation, to be
       rejected.

       The purpose of the policy file is to define a set of policy requirements for  a  container
       image,  usually  depending  on  its  location (where it is being pulled from) or otherwise
       defined identity.

       Policy requirements can be defined for:

              • An individual scope in a transport.  The transport values are  the  same  as  the
                transport prefixes when pushing/pulling images (e.g. docker:, atomic:), and scope
                values are defined by each transport; see below for more details.

       Usually, a scope can be defined to match a single image, and various prefixes of
         such a most specific scope define namespaces of matching images.

              • A default policy for a single transport, expressed using an  empty  string  as  a
                scope

              • A global default policy.

       If  multiple  policy requirements match a given image, only the requirements from the most
       specific match apply, the more general policy requirements definitions are ignored.

       This is expressed in JSON using the top-level syntax

       {
           "default": [/* policy requirements: global default */]
           "transports": {
               transport_name: {
                   "": [/* policy requirements: default for transport $transport_name */],
                   scope_1: [/* policy requirements: default for $scope_1 in $transport_name */],
                   scope_2: [/*…*/]
                   /*…*/
               },
               transport_name_2: {/*…*/}
               /*…*/
           }
       }

       The global default set of policy requirements  is  mandatory;  all  of  the  other  fields
       (transports  itself,  any  specific  transport,  the transport-specific default, etc.) are
       optional.

Supported transports and their scopes

       See containers-transports(5) for general documentation  about  the  transports  and  their
       reference syntax.

   atomic:
       The deprecated atomic: transport refers to images in an Atomic Registry.

       Supported  scopes  use  the  form  hostname[:port][/namespace[/imagestream  [:tag]]], i.e.
       either  specifying  a  complete  name  of  a  tagged   image,   or   prefix   denoting   a
       host/namespace/image  stream, or a wildcarded expression starting with *. for matching all
       subdomains. For  wildcarded  subdomain  matching,  *.example.com  is  a  valid  case,  but
       example*.*.com is not.

       Note:  The  hostname  and port refer to the container registry host and port (the one used
       e.g. for docker pull), not to the OpenShift API host and port.

   containers-storage:
       Supported scopes have the form [storage-specifier]image-scope.

       [storage-specifier]      is       usually       [graph-driver-name@graph-root],       e.g.
       [overlay@/var/lib/containers/storage].

       image-scope  matching  the  individual  image  is  - a named Docker reference in the fully
       expanded form, either using a tag or digest. For example, docker.io/library/busybox:latest
       (not busybox:latest) - and/or (depending on which one the user’s input provides) @image-id

       More general scopes are prefixes of individual-image scopes, and specify a less-precisely-
       specified image, or a repository (by omitting first the image ID, if any; then the digest,
       if  any;  and  finally a tag, if any), a repository namespace, or a registry host (by only
       specifying the host name and possibly a port number).

       Finally, two full-store specifiers matching all images in the store are  valid  scopes:  -
       [graph-driver-name@graph-root] and - [graph-root]

       Note  that  some  tools  like  Podman  and  Buildah  hard-code  overrides of the signature
       verification policy  for  “push”  operations,  allowing  these  operations  regardless  of
       configuration in policy.json.

   dir:
       The dir: transport refers to images stored in local directories.

       Supported   scopes  are  paths  of  directories  (either  containing  a  single  image  or
       subdirectories possibly containing images).

       Note: - The paths must  be  absolute  and  contain  no  symlinks.  Paths  violating  these
       requirements  may  be  silently  ignored.  - The top-level scope "/" is forbidden; use the
       transport default scope "",
         for consistency with other transports.

   docker:
       The docker: transport refers to images in a registry  implementing  the  "Docker  Registry
       HTTP API V2".

       Scopes  matching individual images are named Docker references in the fully expanded form,
       either  using  a  tag  or  digest.  For  example,  docker.io/library/busybox:latest   (not
       busybox:latest).

       More  general scopes are prefixes of individual-image scopes, and specify a repository (by
       omitting the tag or  digest),  a  repository  namespace,  or  a  registry  host  (by  only
       specifying  the  host name and possibly a port number) or a wildcarded expression starting
       with *., for matching all  subdomains  (not  including  a  port  number).  For  wildcarded
       subdomain matching, *.example.com is a valid case, but example*.*.com is not.

   docker-archive:
       Only the default "" scope is supported.

   docker-daemon:
       For  references  using the algo:digest format (referring to an image ID), only the default
       "" scope is used.

       For images using a named reference, scopes matching individual images  are  in  the  fully
       expanded form, either using a tag or digest. For example, docker.io/library/busybox:latest
       (not busybox:latest).

       More general  named  scopes  are  prefixes  of  individual-image  scopes,  and  specify  a
       repository (by omitting the tag or digest), a repository namespace, or a registry host (by
       only specifying the host name and possibly a  port  number)  or  a  wildcarded  expression
       starting  with  *.,  for  matching  all  subdomains  (not  including  a  port number). For
       wildcarded subdomain matching, *.example.com is a valid case, but example*.*.com is not.

   oci:
       The oci: transport refers to images in directories compliant with  "Open  Container  Image
       Layout Specification".

       Supported   scopes  are  paths  to  directories  (either  containing  an  OCI  layout,  or
       subdirectories possibly containing OCI  layout  directories).   The  reference  annotation
       value, if any, is not used.

       Note:  -  The  paths  must  be  absolute  and  contain  no symlinks. Paths violating these
       requirements may be silently ignored.  - The top-level scope "/"  is  forbidden;  use  the
       transport default scope "",
         for consistency with other transports.

   oci-archive:
       Supported  scopes  are  paths  to  OCI  archives,  and  their  parent  directories (either
       containing a  single  archive,  or  subdirectories  possibly  containing  archives).   The
       reference annotation value, if any, is not used.

       Note:  -  The  paths  must  be  absolute  and  contain  no symlinks. Paths violating these
       requirements may be silently ignored.  - The top-level scope "/"  is  forbidden;  use  the
       transport default scope "",
         for consistency with other transports.

   ostree:
       Supported  scopes have the form repo-path:image-scope; _repopath is the path to the OSTree
       repository.

       image-scope is the _dockerreference part of the reference, with with a :latest tag implied
       if no tag is present, and parent namespaces of the _dockerreference value (by omitting the
       tag, or a prefix specifying a higher-level namespace).

       Note: - The _repopath must be absolute and contain  no  symlinks.  Paths  violating  these
       requirements may be silently ignored.

   sif:
       Supported  scopes  are  paths  to Singularity images, and their parent directories (either
       containing images, or subdirectories possibly containing images).

       Note: - The paths must  be  absolute  and  contain  no  symlinks.  Paths  violating  these
       requirements  may  be  silently  ignored.  - The top-level scope "/" is forbidden; use the
       transport default scope "",
         for consistency with other transports.

   tarball:
       The tarball: transport is an implementation detail of  some  import  workflows.  Only  the
       default "" scope is supported.

Policy Requirements

       Using  the  mechanisms  above,  a  set  of  policy  requirements is looked up.  The policy
       requirements are represented as a JSON array of individual requirement  objects.   For  an
       image to be accepted, all of the requirements must be satisfied simultaneously.

       The  policy  requirements  can  also  be used to decide whether an individual signature is
       accepted (= is signed by  a  recognized  key  of  a  known  author);  in  that  case  some
       requirements  may apply only to some signatures, but each signature must be accepted by at
       least one requirement object.

       The following requirement objects are supported:

   insecureAcceptAnything
       A simple requirement with the following syntax

       {"type":"insecureAcceptAnything"}

       This requirement accepts any image (but note that other requirements in  the  array  still
       apply).

       When  deciding  to  accept  an  individual  signature,  this requirement does not have any
       effect; it does not cause the signature to be accepted, though.

       This is useful primarily for policy scopes where no signature  verification  is  required;
       because  the  array  of policy requirements must not be empty, this requirement is used to
       represent the lack of requirements explicitly.

   reject
       A simple requirement with the following syntax:

       {"type":"reject"}

       This requirement rejects every image, and every signature.

   signedBy
       This requirement requires an image to be signed using “simple signing”  with  an  expected
       identity, or accepts a signature if it is using an expected identity and key.

       {
           "type":    "signedBy",
           "keyType": "GPGKeys", /* The only currently supported value */
           "keyPath": "/path/to/local/keyring/file",
           "keyPaths": ["/path/to/local/keyring/file1","/path/to/local/keyring/file2"…],
           "keyData": "base64-encoded-keyring-data",
           "signedIdentity": identity_requirement
       }

       Exactly  one of keyPath, keyPaths and keyData must be present, containing a GPG keyring of
       one or more public keys.  Only signatures made by these keys are accepted.

       The signedIdentity field, a JSON object,  specifies  what  image  identity  the  signature
       claims about the image.  One of the following alternatives are supported:

              • The  identity  in the signature must exactly match the image identity.  Note that
                with  this,  referencing  an  image  by  digest  (with  a  signature  claiming  a
                repository:tag identity) will fail.

         {"type":"matchExact"}

              • If  the  image identity carries a tag, the identity in the signature must exactly
                match; if the image identity  uses  a  digest  reference,  the  identity  in  the
                signature must be in the same repository as the image identity (using any tag).

       (Note  that  with images identified using digest references, the digest from the reference
       is validated even before signature verification starts.)

         {"type":"matchRepoDigestOrExact"}

              • The identity in the signature must  be  in  the  same  repository  as  the  image
                identity.   This  is  useful e.g. to pull an image using the :latest tag when the
                image is signed with a tag specifying an exact image version.

         {"type":"matchRepository"}

              • The identity in the signature must exactly match a specified identity.   This  is
                useful e.g. when locally mirroring images signed using their public identity.

         {
             "type": "exactReference",
             "dockerReference": docker_reference_value
         }

              • The  identity  in  the  signature  must  be in the same repository as a specified
                identity.  This combines the properties of matchRepository and exactReference.

         {
             "type": "exactRepository",
             "dockerRepository": docker_repository_value
         }

              • Prefix remapping:

       If the image identity matches the  specified  prefix,  that  prefix  is  replaced  by  the
       specified “signed prefix”
         (otherwise it is used as unchanged and no remapping takes place);
         matching then follows the matchRepoDigestOrExact semantics documented above
         (i.e.  if  the  image identity carries a tag, the identity in the signature must exactly
       match,
         if it uses a digest reference, the repository must match).

       The prefix and signedPrefix values can be either host[:port] values
         (matching exactly the same host[:port], string),
         repository namespaces, or repositories (i.e. they must not contain tags/digests),
         and match as prefixes of the fully expanded form.
         For example, docker.io/library/busybox (not busybox) to specify that single repository,
         or  docker.io/library  (not  an  empty  string)  to  specify  the  parent  namespace  of
       docker.io/library/busybox==busybox).

       The  prefix  value  is  usually  the  same  as  the  scope  containing the parent signedBy
       requirement.

         {
             "type": "remapIdentity",
             "prefix": prefix,
             "signedPrefix": prefix,
         }

       If the signedIdentity field is missing, it is treated as matchRepoDigestOrExact.

       Note: matchExact, matchRepoDigestOrExact and matchRepository can be only used if a Docker-
       like  image  identity  is  provided  by  the  transport.  In particular, the dir: and oci:
       transports can be only used with exactReference or exactRepository.

   sigstoreSigned
       This requirement requires an image to  be  signed  using  a  sigstore  signature  with  an
       expected identity and key.

       {
           "type":    "sigstoreSigned",
           "keyPath": "/path/to/local/public/key/file",
           "keyData": "base64-encoded-public-key-data",
           "fulcio": {
               "caPath": "/path/to/local/CA/file",
               "caData": "base64-encoded-CA-data",
               "oidcIssuer": "https://expected.OIDC.issuer/",
               "subjectEmail", "expected-signing-user@example.com",
           },
           "rekorPublicKeyPath": "/path/to/local/public/key/file",
           "rekorPublicKeyData": "base64-encoded-public-key-data",
           "signedIdentity": identity_requirement
       }

       Exactly one of keyPath, keyData and fulcio must be present.

       If keyPath or keyData is present, it contains a sigstore public key.  Only signatures made
       by this key are accepted.

       If fulcio is present, the signature must be based on a Fulcio-issued certificate.  One  of
       caPath  and  caData  must  be specified, containing the public key of the Fulcio instance.
       Both oidcIssuer and subjectEmail are mandatory, exactly specifying the  expected  identity
       provider, and the identity of the user obtaining the Fulcio certificate.

       At  most  one of rekorPublicKeyPath and rekorPublicKeyData can be present; it is mandatory
       if fulcio is specified.  If a Rekor public key is specified, the signature must have  been
       uploaded  to a Rekor server and the signature must contain an (offline-verifiable) “signed
       entry timestamp” proving the existence of the Rekor log record,  signed  by  the  provided
       public key.

       The  signedIdentity  field has the same semantics as in the signedBy requirement described
       above.   Note  that  cosign-created  signatures  only  contain  a  repository,   so   only
       matchRepository  and exactRepository can be used to accept them (and that does not protect
       against substitution of a signed image with an unexpected tag).

       To use this with images hosted on image registries,  the  use-sigstore-attachments  option
       needs  to  be  enabled for the relevant registry or repository in the client's containers-
       registries.d(5).

Examples

       It is strongly recommended to set the default policy to reject, and then selectively allow
       individual transports and scopes as desired.

   A reasonably locked-down system
       (Note  that  the  /**/  comments  are  not  valid  in  JSON, and must not be used in real
       policies.)

       {
           "default": [{"type": "reject"}], /* Reject anything not explicitly allowed */
           "transports": {
               "docker": {
                   /* Allow installing images from a specific repository namespace, without cryptographic verification.
                      This namespace includes images like openshift/hello-openshift and openshift/origin. */
                   "docker.io/openshift": [{"type": "insecureAcceptAnything"}],
                   /* Similarly, allow installing the “official” busybox images.  Note how the fully expanded
                      form, with the explicit /library/, must be used. */
                   "docker.io/library/busybox": [{"type": "insecureAcceptAnything"}],
                   /* Allow installing images from all subdomains */
                   "*.temporary-project.example.com": [{"type": "insecureAcceptAnything"}],
                   /* A sigstore-signed repository */
                   "hostname:5000/myns/sigstore-signed-with-full-references": [
                       {
                           "type": "sigstoreSigned",
                           "keyPath": "/path/to/sigstore-pubkey.pub"
                       }
                   ],
                   /* A sigstore-signed repository using the community Fulcio+Rekor servers.

                      The community servers’ public keys can be obtained from
                      https://github.com/sigstore/sigstore/tree/main/pkg/tuf/repository/targets .  */
                   "hostname:5000/myns/sigstore-signed-fulcio-rekor": [
                       {
                           "type": "sigstoreSigned",
                           "fulcio": {
                               "caPath": "/path/to/fulcio_v1.crt.pem",
                               "oidcIssuer": "https://github.com/login/oauth",
                               "subjectEmail": "test-user@example.com"
                           },
                           "rekorPublicKeyPath": "/path/to/rekor.pub",
                       }
                   ],
                   /* A sigstore-signed repository, accepts signatures by /usr/bin/cosign */
                   "hostname:5000/myns/sigstore-signed-allows-malicious-tag-substitution": [
                       {
                           "type": "sigstoreSigned",
                           "keyPath": "/path/to/sigstore-pubkey.pub",
                           "signedIdentity": {"type": "matchRepository"}
                       }
                   ],
                   /* A sigstore-signed repository using the community Fulcio+Rekor servers,
                      accepts signatures by /usr/bin/cosign.

                      The community servers’ public keys can be obtained from
                      https://github.com/sigstore/sigstore/tree/main/pkg/tuf/repository/targets .  */
                   "hostname:5000/myns/sigstore-signed-fulcio-rekor- allows-malicious-tag-substitution": [
                       {
                           "type": "sigstoreSigned",
                           "fulcio": {
                               "caPath": "/path/to/fulcio_v1.crt.pem",
                               "oidcIssuer": "https://github.com/login/oauth",
                               "subjectEmail": "test-user@example.com"
                           },
                           "rekorPublicKeyPath": "/path/to/rekor.pub",
                           "signedIdentity": { "type": "matchRepository" }
                       }
                   ]
                     /* Other docker: images use the global default policy and are rejected */
               },
               "dir": {
                   "": [{"type": "insecureAcceptAnything"}] /* Allow any images originating in local directories */
               },
               "atomic": {
                   /* The common case: using a known key for a repository or set of repositories */
                   "hostname:5000/myns/official": [
                       {
                           "type": "signedBy",
                           "keyType": "GPGKeys",
                           "keyPath": "/path/to/official-pubkey.gpg"
                       }
                   ],
                   /* A more complex example, for a repository which contains a mirror of a third-party product,
                      which must be signed-off by local IT */
                   "hostname:5000/vendor/product": [
                       { /* Require the image to be signed by the original vendor, using the vendor's repository location. */
                           "type": "signedBy",
                           "keyType": "GPGKeys",
                           "keyPath": "/path/to/vendor-pubkey.gpg",
                           "signedIdentity": {
                               "type": "exactRepository",
                               "dockerRepository": "vendor-hostname/product/repository"
                           }
                       },
                       { /* Require the image to _also_ be signed by a local reviewer. */
                           "type": "signedBy",
                           "keyType": "GPGKeys",
                           "keyPath": "/path/to/reviewer-pubkey.gpg"
                       }
                   ],
                   /* A way to mirror many repositories from a single vendor */
                   "private-mirror:5000/vendor-mirror": [
                       { /* Require the image to be signed by the original vendor, using the vendor's repository location.
                            For example, private-mirror:5000/vendor-mirror/productA/image1:latest needs to be signed as
                            vendor.example/productA/image1:latest . */
                           "type": "signedBy",
                           "keyType": "GPGKeys",
                           "keyPath": "/path/to/vendor-pubkey.gpg",
                           "signedIdentity": {
                               "type": "remapIdentity",
                               "prefix": "private-mirror:5000/vendor-mirror",
                               "signedPrefix": "vendor.example.com"
                           }
                       }
                   ]
               }
           }
       }

   Completely disable security, allow all images, do not trust any signatures
       {
           "default": [{"type": "insecureAcceptAnything"}]
       }

SEE ALSO

       atomic(1)

HISTORY

       August 2018, Rename to containers-policy.json(5) by Valentin  Rothberg  vrothberg@suse.commailto:vrothberg@suse.com⟩

       September    2016,    Originally    compiled    by    Miloslav    Trmač    mitr@redhat.commailto:mitr@redhat.com