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