bb3e91
% CONTAINERS-POLICY.JSON 5 policy.json Man Page
bb3e91
% Miloslav Trmač
bb3e91
% September 2016
bb3e91
bb3e91
# NAME
bb3e91
containers-policy.json - syntax for the signature verification policy file
bb3e91
bb3e91
## DESCRIPTION
bb3e91
bb3e91
Signature verification policy files are used to specify policy, e.g. trusted keys,
bb3e91
applicable when deciding whether to accept an image, or individual signatures of that image, as valid.
bb3e91
bb3e91
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.
bb3e91
bb3e91
## FORMAT
bb3e91
bb3e91
The signature verification policy file, usually called `policy.json`,
bb3e91
uses a JSON format.  Unlike some other JSON files, its parsing is fairly strict:
bb3e91
unrecognized, duplicated or otherwise invalid fields cause the entire file,
bb3e91
and usually the entire operation, to be rejected.
bb3e91
bb3e91
The purpose of the policy file is to define a set of *policy requirements* for a container image,
bb3e91
usually depending on its location (where it is being pulled from) or otherwise defined identity.
bb3e91
bb3e91
Policy requirements can be defined for:
bb3e91
bb3e91
- An individual *scope* in a *transport*.
bb3e91
  The *transport* values are the same as the transport prefixes when pushing/pulling images (e.g. `docker:`, `atomic:`),
bb3e91
  and *scope* values are defined by each transport; see below for more details.
bb3e91
bb3e91
  Usually, a scope can be defined to match a single image, and various prefixes of
bb3e91
  such a most specific scope define namespaces of matching images.
bb3e91
- A default policy for a single transport, expressed using an empty string as a scope
bb3e91
- A global default policy.
bb3e91
bb3e91
If multiple policy requirements match a given image, only the requirements from the most specific match apply,
bb3e91
the more general policy requirements definitions are ignored.
bb3e91
bb3e91
This is expressed in JSON using the top-level syntax
bb3e91
```js
bb3e91
{
bb3e91
    "default": [/* policy requirements: global default */]
bb3e91
    "transports": {
bb3e91
        transport_name: {
bb3e91
            "": [/* policy requirements: default for transport $transport_name */],
bb3e91
            scope_1: [/* policy requirements: default for $scope_1 in $transport_name */],
bb3e91
            scope_2: [/*…*/]
bb3e91
            /*…*/
bb3e91
        },
bb3e91
        transport_name_2: {/*…*/}
bb3e91
        /*…*/
bb3e91
    }
bb3e91
}
bb3e91
```
bb3e91
bb3e91
The global `default` set of policy requirements is mandatory; all of the other fields
bb3e91
(`transports` itself, any specific transport, the transport-specific default, etc.) are optional.
bb3e91
bb3e91
bb3e91
## Supported transports and their scopes
bb3e91
bb3e91
### `atomic:`
bb3e91
bb3e91
The `atomic:` transport refers to images in an Atomic Registry.
bb3e91
bb3e91
Supported scopes use the form _hostname_[`:`_port_][`/`_namespace_[`/`_imagestream_ [`:`_tag_]]],
bb3e91
i.e. either specifying a complete name of a tagged image, or prefix denoting
bb3e91
a host/namespace/image stream or a wildcarded expression for matching all
bb3e91
subdomains. For wildcarded subdomain matching, `*.example.com` is a valid case, but `example*.*.com` is not.
bb3e91
bb3e91
*Note:* The _hostname_ and _port_ refer to the container registry host and port (the one used
bb3e91
e.g. for `docker pull`), _not_ to the OpenShift API host and port.
bb3e91
bb3e91
### `dir:`
bb3e91
bb3e91
The `dir:` transport refers to images stored in local directories.
bb3e91
bb3e91
Supported scopes are paths of directories (either containing a single image or
bb3e91
subdirectories possibly containing images).
bb3e91
bb3e91
*Note:* The paths must be absolute and contain no symlinks. Paths violating these requirements may be silently ignored.
bb3e91
bb3e91
The top-level scope `"/"` is forbidden; use the transport default scope `""`,
bb3e91
for consistency with other transports.
bb3e91
bb3e91
### `docker:`
bb3e91
bb3e91
The `docker:` transport refers to images in a registry implementing the "Docker Registry HTTP API V2".
bb3e91
bb3e91
Scopes matching individual images are named Docker references *in the fully expanded form*, either
bb3e91
using a tag or digest. For example, `docker.io/library/busybox:latest` (*not* `busybox:latest`).
bb3e91
bb3e91
More general scopes are prefixes of individual-image scopes, and specify a repository (by omitting the tag or digest),
bb3e91
a repository namespace, or a registry host (by only specifying the host name)
bb3e91
or a wildcarded expression for matching all subdomains. For wildcarded subdomain
bb3e91
matching, `*.example.com` is a valid case, but `example*.*.com` is not.
bb3e91
bb3e91
### `oci:`
bb3e91
bb3e91
The `oci:` transport refers to images in directories compliant with "Open Container Image Layout Specification".
bb3e91
bb3e91
Supported scopes use the form _directory_`:`_tag_, and _directory_ referring to
bb3e91
a directory containing one or more tags, or any of the parent directories.
bb3e91
bb3e91
*Note:* See `dir:` above for semantics and restrictions on the directory paths, they apply to `oci:` equivalently.
bb3e91
bb3e91
### `tarball:`
bb3e91
bb3e91
The `tarball:` transport refers to tarred up container root filesystems.
bb3e91
bb3e91
Scopes are ignored.
bb3e91
bb3e91
## Policy Requirements
bb3e91
bb3e91
Using the mechanisms above, a set of policy requirements is looked up.  The policy requirements
bb3e91
are represented as a JSON array of individual requirement objects.  For an image to be accepted,
bb3e91
*all* of the requirements must be satisfied simultaneously.
bb3e91
bb3e91
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);
bb3e91
in that case some requirements may apply only to some signatures, but each signature must be accepted by *at least one* requirement object.
bb3e91
bb3e91
The following requirement objects are supported:
bb3e91
bb3e91
### `insecureAcceptAnything`
bb3e91
bb3e91
A simple requirement with the following syntax
bb3e91
bb3e91
```json
bb3e91
{"type":"insecureAcceptAnything"}
bb3e91
```
bb3e91
bb3e91
This requirement accepts any image (but note that other requirements in the array still apply).
bb3e91
bb3e91
When deciding to accept an individual signature, this requirement does not have any effect; it does *not* cause the signature to be accepted, though.
bb3e91
bb3e91
This is useful primarily for policy scopes where no signature verification is required;
bb3e91
because the array of policy requirements must not be empty, this requirement is used
bb3e91
to represent the lack of requirements explicitly.
bb3e91
bb3e91
### `reject`
bb3e91
bb3e91
A simple requirement with the following syntax:
bb3e91
bb3e91
```json
bb3e91
{"type":"reject"}
bb3e91
```
bb3e91
bb3e91
This requirement rejects every image, and every signature.
bb3e91
bb3e91
### `signedBy`
bb3e91
6ca60b
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.
bb3e91
bb3e91
```js
bb3e91
{
bb3e91
    "type":    "signedBy",
bb3e91
    "keyType": "GPGKeys", /* The only currently supported value */
bb3e91
    "keyPath": "/path/to/local/keyring/file",
6ca60b
    "keyPaths": ["/path/to/local/keyring/file1","/path/to/local/keyring/file2"…],
bb3e91
    "keyData": "base64-encoded-keyring-data",
bb3e91
    "signedIdentity": identity_requirement
bb3e91
}
bb3e91
```
bb3e91
bb3e91
6ca60b
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.
bb3e91
bb3e91
The `signedIdentity` field, a JSON object, specifies what image identity the signature claims about the image.
bb3e91
One of the following alternatives are supported:
bb3e91
bb3e91
- 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.
bb3e91
bb3e91
  ```json
bb3e91
  {"type":"matchExact"}
bb3e91
  ```
bb3e91
- If the image identity carries a tag, the identity in the signature must exactly match;
bb3e91
  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).
bb3e91
bb3e91
  (Note that with images identified using digest references, the digest from the reference is validated even before signature verification starts.)
bb3e91
bb3e91
  ```json
bb3e91
  {"type":"matchRepoDigestOrExact"}
bb3e91
  ```
bb3e91
- 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.
bb3e91
bb3e91
  ```json
bb3e91
  {"type":"matchRepository"}
bb3e91
  ```
bb3e91
- The identity in the signature must exactly match a specified identity.
bb3e91
  This is useful e.g. when locally mirroring images signed using their public identity.
bb3e91
bb3e91
  ```js
bb3e91
  {
bb3e91
      "type": "exactReference",
bb3e91
      "dockerReference": docker_reference_value
bb3e91
  }
bb3e91
  ```
bb3e91
- The identity in the signature must be in the same repository as a specified identity.
bb3e91
  This combines the properties of `matchRepository` and `exactReference`.
bb3e91
bb3e91
  ```js
bb3e91
  {
bb3e91
      "type": "exactRepository",
bb3e91
      "dockerRepository": docker_repository_value
bb3e91
  }
bb3e91
  ```
bb3e91
- Prefix remapping:
bb3e91
bb3e91
  If the image identity matches the specified prefix, that prefix is replaced by the specified “signed prefix”
bb3e91
  (otherwise it is used as unchanged and no remapping takes place);
bb3e91
  matching then follows the `matchRepoDigestOrExact` semantics documented above
bb3e91
  (i.e. if the image identity carries a tag, the identity in the signature must exactly match,
bb3e91
  if it uses a digest reference, the repository must match).
bb3e91
bb3e91
  The `prefix` and `signedPrefix` values can be either host[:port] values
bb3e91
  (matching exactly the same host[:port], string),
bb3e91
  repository namespaces, or repositories (i.e. they must not contain tags/digests),
bb3e91
  and match as prefixes *of the fully expanded form*.
bb3e91
  For example, `docker.io/library/busybox` (*not* `busybox`) to specify that single repository,
bb3e91
  or `docker.io/library` (not an empty string) to specify the parent namespace of `docker.io/library/busybox`==`busybox`).
bb3e91
bb3e91
  The `prefix` value is usually the same as the scope containing the parent `signedBy` requirement.
bb3e91
bb3e91
  ```js
bb3e91
  {
bb3e91
      "type": "remapIdentity",
bb3e91
      "prefix": prefix,
bb3e91
      "signedPrefix": prefix,
bb3e91
  }
bb3e91
  ```
bb3e91
bb3e91
If the `signedIdentity` field is missing, it is treated as `matchRepoDigestOrExact`.
bb3e91
bb3e91
*Note*: `matchExact`, `matchRepoDigestOrExact` and `matchRepository` can be only used if a Docker-like image identity is
bb3e91
provided by the transport.  In particular, the `dir:` and `oci:` transports can be only
bb3e91
used with `exactReference` or `exactRepository`.
bb3e91
bb3e91
bb3e91
6ca60b
6ca60b
### `sigstoreSigned`
6ca60b
6ca60b
This requirement requires an image to be signed using a sigstore signature with an expected identity and key.
6ca60b
6ca60b
```js
6ca60b
{
6ca60b
    "type":    "sigstoreSigned",
6ca60b
    "keyPath": "/path/to/local/keyring/file",
6ca60b
    "keyData": "base64-encoded-keyring-data",
6ca60b
    "signedIdentity": identity_requirement
6ca60b
}
6ca60b
```
6ca60b
Exactly one of `keyPath` and `keyData` must be present, containing a sigstore public key.  Only signatures made by this key is accepted.
6ca60b
6ca60b
The `signedIdentity` field has the same semantics as in the `signedBy` requirement described above.
6ca60b
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).
6ca60b
6ca60b
To use this with images hosted on image registries, the relevant registry or repository must have the `use-sigstore-attachments` option enabled in containers-registries.d(5).
6ca60b
bb3e91
## Examples
bb3e91
bb3e91
It is *strongly* recommended to set the `default` policy to `reject`, and then
bb3e91
selectively allow individual transports and scopes as desired.
bb3e91
bb3e91
### A reasonably locked-down system
bb3e91
bb3e91
(Note that the `/*`…`*/` comments are not valid in JSON, and must not be used in real policies.)
bb3e91
bb3e91
```js
bb3e91
{
bb3e91
    "default": [{"type": "reject"}], /* Reject anything not explicitly allowed */
bb3e91
    "transports": {
bb3e91
        "docker": {
bb3e91
            /* Allow installing images from a specific repository namespace, without cryptographic verification.
bb3e91
               This namespace includes images like openshift/hello-openshift and openshift/origin. */
bb3e91
            "docker.io/openshift": [{"type": "insecureAcceptAnything"}],
bb3e91
            /* Similarly, allow installing the “official” busybox images.  Note how the fully expanded
bb3e91
               form, with the explicit /library/, must be used. */
6ca60b
            "docker.io/library/busybox": [{"type": "insecureAcceptAnything"}],
bb3e91
            /* Allow installing images from all subdomains */
6ca60b
            "*.temporary-project.example.com": [{"type": "insecureAcceptAnything"}],
6ca60b
            /* A sigstore-signed repository */
6ca60b
            "hostname:5000/myns/sigstore-signed-with-full-references": [
6ca60b
                {
6ca60b
                    "type": "sigstoreSigned",
6ca60b
                    "keyPath": "/path/to/sigstore-pubkey.pub"
6ca60b
                }
6ca60b
            ],
6ca60b
            /* A sigstore-signed repository, accepts signatures by /usr/bin/cosign */
6ca60b
            "hostname:5000/myns/sigstore-signed-allows-malicious-tag-substitution": [
6ca60b
                {
6ca60b
                    "type": "sigstoreSigned",
6ca60b
                    "keyPath": "/path/to/sigstore-pubkey.pub",
6ca60b
                    "signedIdentity": {"type": "matchRepository"}
6ca60b
                }
6ca60b
            ]
bb3e91
            /* Other docker: images use the global default policy and are rejected */
bb3e91
        },
bb3e91
        "dir": {
bb3e91
            "": [{"type": "insecureAcceptAnything"}] /* Allow any images originating in local directories */
bb3e91
        },
bb3e91
        "atomic": {
bb3e91
            /* The common case: using a known key for a repository or set of repositories */
bb3e91
            "hostname:5000/myns/official": [
bb3e91
                {
bb3e91
                    "type": "signedBy",
bb3e91
                    "keyType": "GPGKeys",
bb3e91
                    "keyPath": "/path/to/official-pubkey.gpg"
bb3e91
                }
bb3e91
            ],
bb3e91
            /* A more complex example, for a repository which contains a mirror of a third-party product,
bb3e91
               which must be signed-off by local IT */
bb3e91
            "hostname:5000/vendor/product": [
bb3e91
                { /* Require the image to be signed by the original vendor, using the vendor's repository location. */
bb3e91
                    "type": "signedBy",
bb3e91
                    "keyType": "GPGKeys",
bb3e91
                    "keyPath": "/path/to/vendor-pubkey.gpg",
bb3e91
                    "signedIdentity": {
bb3e91
                        "type": "exactRepository",
bb3e91
                        "dockerRepository": "vendor-hostname/product/repository"
bb3e91
                    }
bb3e91
                },
bb3e91
                { /* Require the image to _also_ be signed by a local reviewer. */
bb3e91
                    "type": "signedBy",
bb3e91
                    "keyType": "GPGKeys",
bb3e91
                    "keyPath": "/path/to/reviewer-pubkey.gpg"
bb3e91
                }
bb3e91
            ],
bb3e91
            /* A way to mirror many repositories from a single vendor */
bb3e91
            "private-mirror:5000/vendor-mirror": [
bb3e91
                { /* Require the image to be signed by the original vendor, using the vendor's repository location.
bb3e91
                     For example, private-mirror:5000/vendor-mirror/productA/image1:latest needs to be signed as
bb3e91
                     vendor.example/productA/image1:latest . */
bb3e91
                    "type": "signedBy",
bb3e91
                    "keyType": "GPGKeys",
bb3e91
                    "keyPath": "/path/to/vendor-pubkey.gpg",
bb3e91
                    "signedIdentity": {
bb3e91
                        "type": "remapIdentity",
bb3e91
                        "prefix": "private-mirror:5000/vendor-mirror",
6ca60b
                        "signedPrefix": "vendor.example.com"
bb3e91
                    }
bb3e91
                }
bb3e91
            ]
bb3e91
        }
bb3e91
    }
bb3e91
}
bb3e91
```
bb3e91
bb3e91
### Completely disable security, allow all images, do not trust any signatures
bb3e91
bb3e91
```json
bb3e91
{
bb3e91
    "default": [{"type": "insecureAcceptAnything"}]
bb3e91
}
bb3e91
```
bb3e91
## SEE ALSO
bb3e91
  atomic(1)
bb3e91
bb3e91
## HISTORY
bb3e91
August 2018, Rename to containers-policy.json(5) by Valentin Rothberg <vrothberg@suse.com>
bb3e91
bb3e91
September 2016, Originally compiled by Miloslav Trmač <mitr@redhat.com>