|
| 1 | +<!--[metadata]> |
| 2 | ++++ |
| 3 | +title = "Content trust in Docker" |
| 4 | +description = "Enabling content trust in Docker" |
| 5 | +keywords = ["content, trust, security, docker, documentation"] |
| 6 | +[menu.main] |
| 7 | +parent= "smn_content_trust" |
| 8 | +weight=-1 |
| 9 | ++++ |
| 10 | +<![end-metadata]--> |
| 11 | + |
| 12 | +# Content trust in Docker |
| 13 | + |
| 14 | +When transferring data among networked systems, *trust* is a central concern. In |
| 15 | +particular, when communicating over an untrusted medium such as the internet, it |
| 16 | +is critical to ensure the integrity and publisher of all the data a system |
| 17 | +operates on. You use Docker to push and pull images (data) to a registry. Content trust |
| 18 | +gives you the ability to both verify the integrity and the publisher of all the |
| 19 | +data received from a registry over any channel. |
| 20 | + |
| 21 | +Content trust is currently only available for users of the public Docker Hub. It |
| 22 | +is currently not available for the Docker Trusted Registry or for private |
| 23 | +registries. |
| 24 | + |
| 25 | +## Understand trust in Docker |
| 26 | + |
| 27 | +Content trust allows operations with a remote Docker registry to enforce |
| 28 | +client-side signing and verification of image tags. Content trust provides the |
| 29 | +ability to use digital signatures for data sent to and received from remote |
| 30 | +Docker registries. These signatures allow client-side verification of the |
| 31 | +integrity and publisher of specific image tags. |
| 32 | + |
| 33 | +Currently, content trust is disabled by default. You must enabled it by setting |
| 34 | +the `DOCKER_CONTENT_TRUST` environment variable. |
| 35 | + |
| 36 | +Once content trust is enabled, image publishers can sign their images. Image consumers can |
| 37 | +ensure that the images they use are signed. publishers and consumers can be |
| 38 | +individuals alone or in organizations. Docker's content trust supports users and |
| 39 | +automated processes such as builds. |
| 40 | + |
| 41 | +### Image tags and content trust |
| 42 | + |
| 43 | +An individual image record has the following identifier: |
| 44 | + |
| 45 | +``` |
| 46 | +[REGISTRY_HOST[:REGISTRY_PORT]/]REPOSITORY[:TAG] |
| 47 | +``` |
| 48 | + |
| 49 | +A particular image `REPOSITORY` can have multiple tags. For example, `latest` and |
| 50 | + `3.1.2` are both tags on the `mongo` image. An image publisher can build an image |
| 51 | + and tag combination many times changing the image with each build. |
| 52 | + |
| 53 | +Content trust is associated with the `TAG` portion of an image. Each image |
| 54 | +repository has a set of keys that image publishers use to sign an image tag. |
| 55 | +Image publishers have discretion on which tags they sign. |
| 56 | + |
| 57 | +An image repository can contain an image with one tag that is signed and another |
| 58 | +tag that is not. For example, consider [the Mongo image |
| 59 | +repository](https://hub.docker.com/r/library/mongo/tags/). The `latest` |
| 60 | +tag could be unsigned while the `3.1.6` tag could be signed. It is the |
| 61 | +responsibility of the image publisher to decide if an image tag is signed or |
| 62 | +not. In this representation, some image tags are signed, others are not: |
| 63 | + |
| 64 | + |
| 65 | + |
| 66 | +Publishers can choose to sign a specific tag or not. As a result, the content of |
| 67 | +an unsigned tag and that of a signed tag with the same name may not match. For |
| 68 | +example, a publisher can push a tagged image `someimage:latest` and sign it. |
| 69 | +Later, the same publisher can push an unsigned `someimage:latest` image. This second |
| 70 | +push replaces the last unsigned tag `latest` but does not affect the signed `latest` version. |
| 71 | +The ability to choose which tags they can sign, allows publishers to iterate over |
| 72 | +the unsigned version of an image before officially signing it. |
| 73 | + |
| 74 | +Image consumers can enable content trust to ensure that images they use were |
| 75 | +signed. If a consumer enables content trust, they can only pull, run, or build |
| 76 | +with trusted images. Enabling content trust is like wearing a pair of |
| 77 | +rose-colored glasses. Consumers "see" only signed images tags and the less |
| 78 | +desirable, unsigned image tags are "invisible" to them. |
| 79 | + |
| 80 | + |
| 81 | + |
| 82 | +To the consumer who does not enabled content trust, nothing about how they |
| 83 | +work with Docker images changes. Every image is visible regardless of whether it |
| 84 | +is signed or not. |
| 85 | + |
| 86 | + |
| 87 | +### Content trust operations and keys |
| 88 | + |
| 89 | +When content trust is enabled, `docker` CLI commands that operate on tagged images must |
| 90 | +either have content signatures or explicit content hashes. The commands that |
| 91 | +operate with content trust are: |
| 92 | + |
| 93 | +* `push` |
| 94 | +* `build` |
| 95 | +* `create` |
| 96 | +* `pull` |
| 97 | +* `run` |
| 98 | + |
| 99 | +For example, with content trust enabled a `docker pull someimage:latest` only |
| 100 | +succeeds if `someimage:latest` is signed. However, an operation with an explicit |
| 101 | +content hash always succeeds as long as the hash exists: |
| 102 | + |
| 103 | +```bash |
| 104 | +$ docker pull someimage@sha256:d149ab53f8718e987c3a3024bb8aa0e2caadf6c0328f1d9d850b2a2a67f2819a |
| 105 | +``` |
| 106 | + |
| 107 | +Trust for an image tag is managed through the use of signing keys. Docker's content |
| 108 | +trust makes use four different keys: |
| 109 | + |
| 110 | +| Key | Description | |
| 111 | +|---------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------| |
| 112 | +| offline key | Root of content trust for a image tag. When content trust is enabled, you create the offline key once. | |
| 113 | +| target and snapshot | These two keys are known together as the "tagging" key. When content trust is enabled, you create this key when you add a new image repository. If you have the offline key, you can export the tagging key and allow other publishers to sign the image tags. | |
| 114 | +| timestamp | This key applies to a repository. It allows Docker repositories to have freshness security guarantees without requiring periodic content refreshes on the client's side. | |
| 115 | + |
| 116 | +With the exception of the timestamp, all the keys are generated and stored locally |
| 117 | +client-side. The timestamp is safely generated and stored in a signing server that |
| 118 | +is deployed alongside the Docker registry. All keys are generated in a backend |
| 119 | +service that isn't directly exposed to the internet and are encrypted at rest. |
| 120 | + |
| 121 | +The following image depicts the various signing keys and their relationships: |
| 122 | + |
| 123 | + |
| 124 | + |
| 125 | +>**WARNING**: Loss of the offline key is **very difficult** to recover from. |
| 126 | +>Correcting this loss requires intervention from [Docker |
| 127 | +>Support](https://support.docker.com) to reset the repository state. This loss |
| 128 | +>also requires **manual intervention** from every consumer that used a signed |
| 129 | +>tag from this repository prior to the loss. |
| 130 | +
|
| 131 | +You should backup the offline key somewhere safe. Given that it is only required |
| 132 | +to create new repositories, it is a good idea to store it offline. Make sure you |
| 133 | +read [Manage keys for content trust](/security/trust/trust_key_mng) information |
| 134 | +for details on creating, securing, and backing up your keys. |
| 135 | + |
| 136 | +## Survey of typical content trust operations |
| 137 | + |
| 138 | +This section surveys the typical trusted operations users perform with Docker |
| 139 | +images. |
| 140 | + |
| 141 | +### Enable content trust |
| 142 | + |
| 143 | +Enable content trust by setting the `DOCKER_CONTENT_TRUST` environment variable. |
| 144 | +Enabling per-shell is useful because you can have one shell configured for |
| 145 | +trusted operations and another terminal shell for untrusted operations. You can |
| 146 | +also add this declaration to your shell profile to have it turned on always by |
| 147 | +default. |
| 148 | + |
| 149 | +To enable content trust in a `bash` shell enter the following command: |
| 150 | + |
| 151 | +```bash |
| 152 | +export DOCKER_CONTENT_TRUST=1 |
| 153 | +``` |
| 154 | + |
| 155 | +Once set, each of the "tag" operations require key for trusted tag. All of these |
| 156 | +commands also support the `--disable-content-trust` flag. This flag allows |
| 157 | +publishers to run individual operations on tagged images without content trust on an |
| 158 | +as-needed basis. |
| 159 | + |
| 160 | + |
| 161 | +### Push trusted content |
| 162 | + |
| 163 | +To create signed content for a specific image tag, simply enable content trust and push |
| 164 | +a tagged image. If this is the first time you have pushed an image using content trust |
| 165 | +on your system, the session looks like this: |
| 166 | + |
| 167 | +```bash |
| 168 | +$ docker push docker/trusttest:latest |
| 169 | +The push refers to a repository [docker.io/docker/trusttest] (len: 1) |
| 170 | +9a61b6b1315e: Image already exists |
| 171 | +902b87aaaec9: Image already exists |
| 172 | +latest: digest: sha256:d02adacee0ac7a5be140adb94fa1dae64f4e71a68696e7f8e7cbf9db8dd49418 size: 3220 |
| 173 | +Signing and pushing trust metadata |
| 174 | +You are about to create a new offline signing key passphrase. This passphrase |
| 175 | +will be used to protect the most sensitive key in your signing system. Please |
| 176 | +choose a long, complex passphrase and be careful to keep the password and the |
| 177 | +key file itself secure and backed up. It is highly recommended that you use a |
| 178 | +password manager to generate the passphrase and keep it safe. There will be no |
| 179 | +way to recover this key. You can find the key in your config directory. |
| 180 | +Enter passphrase for new offline key with id a1d96fb: |
| 181 | +Repeat passphrase for new offline key with id a1d96fb: |
| 182 | +Enter passphrase for new tagging key with id docker.io/docker/trusttest (3a932f1): |
| 183 | +Repeat passphrase for new tagging key with id docker.io/docker/trusttest (3a932f1): |
| 184 | +Finished initializing "docker.io/docker/trusttest" |
| 185 | +``` |
| 186 | +When you push your first tagged image with content trust enabled, the `docker` client |
| 187 | +recognizes this is your first push and: |
| 188 | + |
| 189 | + - alerts you that it will create a new offline key |
| 190 | + - requests a passphrase for the key |
| 191 | + - generates an offline key in the `~/.docker/trust` directory |
| 192 | + - generates a tagging key for in the `~/.docker/trust` directory |
| 193 | + |
| 194 | +The passphrase you chose for both the offline key and your content key-pair should |
| 195 | +be randomly generated and stored in a *password manager*. |
| 196 | + |
| 197 | +It is important to note, if you had left off the `latest` tag, content trust is skipped. |
| 198 | +This is true even if content trust is enabled and even if this is your first push. |
| 199 | + |
| 200 | +```bash |
| 201 | +$ docker push docker/trusttest |
| 202 | +The push refers to a repository [docker.io/docker/trusttest] (len: 1) |
| 203 | +9a61b6b1315e: Image successfully pushed |
| 204 | +902b87aaaec9: Image successfully pushed |
| 205 | +latest: digest: sha256:a9a9c4402604b703bed1c847f6d85faac97686e48c579bd9c3b0fa6694a398fc size: 3220 |
| 206 | +No tag specified, skipping trust metadata push |
| 207 | +``` |
| 208 | + |
| 209 | +It is skipped because as the message states, you did not supply an image `TAG` |
| 210 | +value. In Docker content trust, signatures are associated with tags. |
| 211 | + |
| 212 | +Once you have an offline key on your system, subsequent images repositories |
| 213 | +you create can use that same offline key: |
| 214 | + |
| 215 | +```bash |
| 216 | +$ docker push docker.io/docker/seaside:latest |
| 217 | +The push refers to a repository [docker.io/docker/seaside] (len: 1) |
| 218 | +a9539b34a6ab: Image successfully pushed |
| 219 | +b3dbab3810fc: Image successfully pushed |
| 220 | +latest: digest: sha256:d2ba1e603661a59940bfad7072eba698b79a8b20ccbb4e3bfb6f9e367ea43939 size: 3346 |
| 221 | +Signing and pushing trust metadata |
| 222 | +Enter key passphrase for offline key with id a1d96fb: |
| 223 | +Enter passphrase for new tagging key with id docker.io/docker/seaside (bb045e3): |
| 224 | +Repeat passphrase for new tagging key with id docker.io/docker/seaside (bb045e3): |
| 225 | +Finished initializing "docker.io/docker/seaside" |
| 226 | +``` |
| 227 | + |
| 228 | +The new image has its own tagging key and timestamp key. The `latest` tag is signed with both of |
| 229 | +these. |
| 230 | + |
| 231 | + |
| 232 | +### Pull image content |
| 233 | + |
| 234 | +A common way to consume an image is to `pull` it. With content trust enabled, the Docker |
| 235 | +client only allows `docker pull` to retrieve signed images. |
| 236 | + |
| 237 | +``` |
| 238 | +$ docker pull docker/seaside |
| 239 | +Using default tag: latest |
| 240 | +Pull (1 of 1): docker/trusttest:latest@sha256:d149ab53f871 |
| 241 | +... |
| 242 | +Tagging docker/trusttest@sha256:d149ab53f871 as docker/trusttest:latest |
| 243 | +``` |
| 244 | + |
| 245 | +The `seaside:latest` image is signed. In the following example, the command does not specify a tag, so the system uses |
| 246 | +the `latest` tag by default again and the `docker/cliffs:latest` tag is not signed. |
| 247 | + |
| 248 | +```bash |
| 249 | +$ docker pull docker/cliffs |
| 250 | +Using default tag: latest |
| 251 | +no trust data available |
| 252 | +``` |
| 253 | + |
| 254 | +Because the tag `docker/cliffs:latest` is not trusted, the `pull` fails. |
| 255 | + |
| 256 | + |
| 257 | +### Disable content trust for specific operations |
| 258 | + |
| 259 | +A user that wants to disable content trust for a particular operation can use the |
| 260 | +`--disable-content-trust` flag. **Warning: this flag disables content trust for |
| 261 | +this operation**. With this flag, Docker will ignore content-trust and allow all |
| 262 | +operations to be done without verifying any signatures. If we wanted the |
| 263 | +previous untrusted build to succeed we could do: |
| 264 | + |
| 265 | +``` |
| 266 | +$ cat Dockerfile |
| 267 | +FROM docker/trusttest:notrust |
| 268 | +RUN echo |
| 269 | +$ docker build --disable-content-trust -t docker/trusttest:testing . |
| 270 | +Sending build context to Docker daemon 42.84 MB |
| 271 | +... |
| 272 | +Successfully built f21b872447dc |
| 273 | +``` |
| 274 | + |
| 275 | +The same is true for all the other commands, such as `pull` and `push`: |
| 276 | + |
| 277 | +``` |
| 278 | +$ docker pull --disable-content-trust docker/trusttest:untrusted |
| 279 | +... |
| 280 | +$ docker push --disable-content-trust docker/trusttest:untrusted |
| 281 | +... |
| 282 | +``` |
| 283 | + |
| 284 | +## Related information |
| 285 | + |
| 286 | +* [Manage keys for content trust](/security/trust/trust_key_mng) |
| 287 | +* [Automation with content trust](/security/trust/trust_automation) |
| 288 | +* [Play in a content trust sandbox](/security/trust/trust_sandbox) |
| 289 | + |
| 290 | + |
| 291 | + |
0 commit comments