From 6bce49d51d7381b74262e9d87a948e088c2c225a Mon Sep 17 00:00:00 2001 From: Mary Anthony Date: Tue, 12 Apr 2016 16:14:33 -0700 Subject: [PATCH] Updated per conversation with Richard Removing draft Richard's comments and some fixes Signed-off-by: Mary Anthony --- docs/insecure.md | 93 +++++++++++++++++++++++--------------- docs/spec/manifest-v2-1.md | 70 ++++++++++++++-------------- docs/spec/manifest-v2-2.md | 42 +++++++++-------- 3 files changed, 117 insertions(+), 88 deletions(-) diff --git a/docs/insecure.md b/docs/insecure.md index 201946bbf..88055d51a 100644 --- a/docs/insecure.md +++ b/docs/insecure.md @@ -8,83 +8,104 @@ keywords = ["registry, on-prem, images, tags, repository, distribution, insecure # Insecure Registry -While it's highly recommended to secure your registry using a TLS certificate issued by a known CA, you may alternatively decide to use self-signed certificates, or even use your registry over plain http. +While it's highly recommended to secure your registry using a TLS certificate +issued by a known CA, you may alternatively decide to use self-signed +certificates, or even use your registry over plain http. -You have to understand the downsides in doing so, and the extra burden in configuration. +You have to understand the downsides in doing so, and the extra burden in +configuration. ## Deploying a plain HTTP registry -> **Warning**: it's not possible to use an insecure registry with basic authentication +> **Warning**: it's not possible to use an insecure registry with basic authentication. This basically tells Docker to entirely disregard security for your registry. +While this is relatively easy to configure the daemon in this way, it is +**very** insecure. It does expose your registry to trivial MITM. Only use this +solution for isolated testing or in a tightly controlled, air-gapped +environment. -1. edit the file `/etc/default/docker` so that there is a line that reads: `DOCKER_OPTS="--insecure-registry myregistrydomain.com:5000"` (or add that to existing `DOCKER_OPTS`) -2. restart your Docker daemon: on ubuntu, this is usually `service docker stop && service docker start` +1. Open the `/etc/default/docker` file or `/etc/sysconfig/docker` for editing. + + Depending on your operating system, your Engine daemon start options. + +2. Edit (or add) the `DOCKER_OPTS` line and add the `--insecure-registry` flag. + + This flag takes the URL of your registry, for example. + + `DOCKER_OPTS="--insecure-registry myregistrydomain.com:5000"` + +3. Close and save the configuration file. + +4. Restart your Docker daemon + + The command you use to restart the daemon depends on your operating system. + For example, on Ubuntu, this is usually the `service docker stop` and `service + docker start` command. + +5. Repeat this configuration on every Engine host that wants to access your registry. -**Pros:** - - relatively easy to configure - -**Cons:** - - - this is **very** insecure: you are basically exposing yourself to trivial MITM, and this solution should only be used for isolated testing or in a tightly controlled, air-gapped environment - - you have to configure every docker daemon that wants to access your registry - ## Using self-signed certificates > **Warning**: using this along with basic authentication requires to **also** trust the certificate into the OS cert store for some versions of docker (see below) -Generate your own certificate: +This is more secure than the insecure registry solution. You must configure every docker daemon that wants to access your registry + +1. Generate your own certificate: mkdir -p certs && openssl req \ -newkey rsa:4096 -nodes -sha256 -keyout certs/domain.key \ -x509 -days 365 -out certs/domain.crt -Be sure to use the name `myregistrydomain.com` as a CN. +2. Be sure to use the name `myregistrydomain.com` as a CN. -Use the result to [start your registry with TLS enabled](https://github.com/docker/distribution/blob/master/docs/deploying.md#get-a-certificate) +3. Use the result to [start your registry with TLS enabled](https://github.com/docker/distribution/blob/master/docs/deploying.md#get-a-certificate) -Then you have to instruct every docker daemon to trust that certificate. This is done by copying the `domain.crt` file to `/etc/docker/certs.d/myregistrydomain.com:5000/ca.crt`. +4. Instruct every docker daemon to trust that certificate. -Don't forget to restart docker after doing so. + This is done by copying the `domain.crt` file to `/etc/docker/certs.d/myregistrydomain.com:5000/ca.crt`. -**Pros:** +5. Don't forget to restart the Engine daemon. - - more secure than the insecure registry solution +## Troubleshooting insecure registry -**Cons:** +This sections lists some common failures and how to recover from them. - - you have to configure every docker daemon that wants to access your registry +### Failing... -## Failing... - -Failing to configure docker and trying to pull from a registry that is not using TLS will result in the following message: +Failing to configure the Engine daemon and trying to pull from a registry that is not using +TLS will results in the following message: ``` FATA[0000] Error response from daemon: v1 ping attempt failed with error: -Get https://myregistrydomain.com:5000/v1/_ping: tls: oversized record received with length 20527. -If this private registry supports only HTTP or HTTPS with an unknown CA certificate,please add +Get https://myregistrydomain.com:5000/v1/_ping: tls: oversized record received with length 20527. +If this private registry supports only HTTP or HTTPS with an unknown CA certificate,please add `--insecure-registry myregistrydomain.com:5000` to the daemon's arguments. In the case of HTTPS, if you have access to the registry's CA certificate, no need for the flag; simply place the CA certificate at /etc/docker/certs.d/myregistrydomain.com:5000/ca.crt ``` -## Docker still complains about the certificate when using authentication? +### Docker still complains about the certificate when using authentication? -When using authentication, some versions of docker also require you to trust the certificate at the OS level. +When using authentication, some versions of docker also require you to trust the certificate at the OS level. Usually, on Ubuntu this is done with: -Usually, on Ubuntu this is done with: - - cp certs/domain.crt /usr/local/share/ca-certificates/myregistrydomain.com.crt - update-ca-certificates +```bash +$ cp certs/domain.crt /usr/local/share/ca-certificates/myregistrydomain.com.crt +update-ca-certificates +``` ... and on Red Hat (and its derivatives) with: - cp certs/domain.crt /etc/pki/ca-trust/source/anchors/myregistrydomain.com.crt - update-ca-trust +```bash +cp certs/domain.crt /etc/pki/ca-trust/source/anchors/myregistrydomain.com.crt +update-ca-trust +``` ... On some distributions, e.g. Oracle Linux 6, the Shared System Certificates feature needs to be manually enabled: - update-ca-trust enable +```bash +$ update-ca-trust enable +``` Now restart docker (`service docker stop && service docker start`, or any other way you use to restart docker). diff --git a/docs/spec/manifest-v2-1.md b/docs/spec/manifest-v2-1.md index 418bca5d7..056f4bc66 100644 --- a/docs/spec/manifest-v2-1.md +++ b/docs/spec/manifest-v2-1.md @@ -1,10 +1,14 @@ -# Image Manifest Version 2, Schema 1 +# Image Manifest Version 2, Schema 1 This document outlines the format of of the V2 image manifest. The image manifest described herein was introduced in the Docker daemon in the [v1.3.0 @@ -25,9 +29,9 @@ signed manifest | "application/vnd.docker.distribution.manifest.v1+prettyjws" *Note that "application/json" will also be accepted for schema 1.* -References: - - - [Proposal: JSON Registry API V2.1](https://github.com/docker/docker/issues/9015) +References: + + - [Proposal: JSON Registry API V2.1](https://github.com/docker/docker/issues/9015) - [Proposal: Provenance step 1 - Transform images for validation and verification](https://github.com/docker/docker/issues/8093) ## *Manifest* Field Descriptions @@ -40,47 +44,47 @@ Manifest provides the base accessible fields for working with V2 image format name is the name of the image's repository - **`tag`** *string* - + tag is the tag of the image - + - **`architecture`** *string* - architecture is the host architecture on which this image is intended to + architecture is the host architecture on which this image is intended to run. This is for information purposes and not currently used by the engine - + - **`fsLayers`** *array* - + fsLayers is a list of filesystem layer blob sums contained in this image. - + An fsLayer is a struct consisting of the following fields - **`blobSum`** *digest.Digest* - - blobSum is the digest of the referenced filesystem image layer. A + + blobSum is the digest of the referenced filesystem image layer. A digest must be a sha256 hash. - - + + - **`history`** *array* - - history is a list of unstructured historical data for v1 compatibility. It + + history is a list of unstructured historical data for v1 compatibility. It contains ID of the image layer and ID of the layer's parent layers. - + history is a struct consisting of the following fields - **`v1Compatibility`** string - - V1Compatibility is the raw V1 compatibility information. This will + + V1Compatibility is the raw V1 compatibility information. This will contain the JSON object describing the V1 of this image. - + - **`schemaVersion`** *int* - + SchemaVersion is the image manifest schema that this image follows. - ->**Note**:the length of `history` must be equal to the length of `fsLayers` and + +>**Note**:the length of `history` must be equal to the length of `fsLayers` and >entries in each are correlated by index. ## Signed Manifests -Signed manifests provides an envelope for a signed image manifest. A signed -manifest consists of an image manifest along with an additional field +Signed manifests provides an envelope for a signed image manifest. A signed +manifest consists of an image manifest along with an additional field containing the signature of the manifest. The docker client can verify signed manifests and displays a message to the user. @@ -88,10 +92,10 @@ The docker client can verify signed manifests and displays a message to the user ### Signing Manifests Image manifests can be signed in two different ways: with a *libtrust* private - key or an x509 certificate chain. When signing with an x509 certificate chain, - the public key of the first element in the chain must be the public key + key or an x509 certificate chain. When signing with an x509 certificate chain, + the public key of the first element in the chain must be the public key corresponding with the sign key. - + ### Signed Manifest Field Description Signed manifests include an image manifest and a list of signatures generated @@ -99,7 +103,7 @@ by *libtrust*. A signature consists of the following fields: - **`header`** *[JOSE](http://tools.ietf.org/html/draft-ietf-jose-json-web-signature-31#section-2)* - + A [JSON Web Signature](http://self-issued.info/docs/draft-ietf-jose-json-web-signature.html) - **`signature`** *string* @@ -107,9 +111,9 @@ by *libtrust*. A signature consists of the following fields: A signature for the image manifest, signed by a *libtrust* private key - **`protected`** *string* - + The signed protected header - + ## Example Manifest *Example showing the official 'hello-world' image manifest.* @@ -159,5 +163,5 @@ by *libtrust*. A signature consists of the following fields: } ] } - + ``` diff --git a/docs/spec/manifest-v2-2.md b/docs/spec/manifest-v2-2.md index 904366ed8..316314541 100644 --- a/docs/spec/manifest-v2-2.md +++ b/docs/spec/manifest-v2-2.md @@ -1,6 +1,10 @@ @@ -10,7 +14,7 @@ This document outlines the format of of the V2 image manifest, schema version 2. The original (and provisional) image manifest for V2 (schema 1), was introduced in the Docker daemon in the [v1.3.0 release](https://github.com/docker/docker/commit/9f482a66ab37ec396ac61ed0c00d59122ac07453) -and is specified in the [schema 1 manifest definition](./manifest-v2-1.md) +and is specified in the [schema 1 manifest definition](manifest-v2-1.md) This second schema version has two primary goals. The first is to allow multi-architecture images, through a "fat manifest" which references image @@ -40,7 +44,7 @@ image manifest based on the Content-Type returned in the HTTP response. ## *Manifest List* Field Descriptions - **`schemaVersion`** *int* - + This field specifies the image manifest schema version as an integer. This schema uses the version `2`. @@ -54,21 +58,21 @@ image manifest based on the Content-Type returned in the HTTP response. The manifests field contains a list of manifests for specific platforms. Fields of a object in the manifests list are: - + - **`mediaType`** *string* - + The MIME type of the referenced object. This will generally be `application/vnd.docker.image.manifest.v2+json`, but it could also be `application/vnd.docker.image.manifest.v1+json` if the manifest list references a legacy schema-1 manifest. - + - **`size`** *int* - + The size in bytes of the object. This field exists so that a client will have an expected size for the content before validating. If the length of the retrieved content does not match the specified length, the content should not be trusted. - + - **`digest`** *string* The digest of the content, as defined by the @@ -153,7 +157,7 @@ image. It's the direct replacement for the schema-1 manifest. ## *Image Manifest* Field Descriptions - **`schemaVersion`** *int* - + This field specifies the image manifest schema version as an integer. This schema uses version `2`. @@ -171,19 +175,19 @@ image. It's the direct replacement for the schema-1 manifest. daemon side. Fields of a config object are: - + - **`mediaType`** *string* - + The MIME type of the referenced object. This should generally be `application/vnd.docker.container.image.v1+json`. - + - **`size`** *int* - + The size in bytes of the object. This field exists so that a client will have an expected size for the content before validating. If the length of the retrieved content does not match the specified length, the content should not be trusted. - + - **`digest`** *string* The digest of the content, as defined by the @@ -194,19 +198,19 @@ image. It's the direct replacement for the schema-1 manifest. The layer list is ordered starting from the base image (opposite order of schema1). Fields of an item in the layers list are: - + - **`mediaType`** *string* - + The MIME type of the referenced object. This should generally be `application/vnd.docker.image.rootfs.diff.tar.gzip`. - + - **`size`** *int* - + The size in bytes of the object. This field exists so that a client will have an expected size for the content before validating. If the length of the retrieved content does not match the specified length, the content should not be trusted. - + - **`digest`** *string* The digest of the content, as defined by the