diff --git a/_data/toc.yaml b/_data/toc.yaml index a68af7677e..e1094da3a7 100644 --- a/_data/toc.yaml +++ b/_data/toc.yaml @@ -1269,6 +1269,14 @@ manuals: title: Web-based access - path: /datacenter/ucp/2.1/guides/user/access-ucp/cli-based-access/ title: CLI-based access + - sectiontitle: Content trust + section: + - path: /datacenter/ucp/2.1/guides/user/content-trust/ + title: Run only images you trust + - path: /datacenter/ucp/2.1/guides/user/content-trust/manage-trusted-repositories/ + title: Manage trusted repositories + - path: /datacenter/ucp/2.1/guides/user/content-trust/continuous-integration/ + title: Use trusted images for continuous integration - sectiontitle: Deploy an application section: - path: /datacenter/ucp/2.1/guides/user/services/deploy-a-service/ diff --git a/datacenter/ucp/2.1/guides/user/content-trust/continuous-integration.md b/datacenter/ucp/2.1/guides/user/content-trust/continuous-integration.md new file mode 100644 index 0000000000..5b4c41be67 --- /dev/null +++ b/datacenter/ucp/2.1/guides/user/content-trust/continuous-integration.md @@ -0,0 +1,149 @@ +--- +description: Set up and configure content trust and signing policy for use with a continuous integration system +keywords: ucp, trust, notary, security, continuous integration +title: Use trusted images for continuous integration +--- + +The document provides a minimal example on setting up Docker Content Trust (DCT) in +Universal Control Plane (UCP) for use with a Continuous Integration (CI) system. It +covers setting up the necessary accounts and trust delegations to restrict only those +images built by your CI system to be deployed to your UCP managed cluster. + +## Set up UCP accounts and teams + +The first step is to create a user account for your CI system. For the purposes of +this document we will assume you are using Jenkins as your CI system and will therefore +name the account "jenkins". As an admin user logged in to UCP, navigate to "User Management" +and select "Add User". Create a user with the name "jenkins" and set a strong password. + +Next, create a team called "CI" and add the "jenkins" user to this team. All signing +policy is team based, so if we want only a single user to be able to sign images +destined to be deployed on the cluster, we must create a team for this one user. + +## Set up the signing policy + +While still logged in as an admin, navigate to "Admin Settings" and select the "Content Trust" +subsection. Select the checkbox to enable content trust and in the select box that appears, +select the "CI" team we have just created. Save the settings. + +This policy will require that every image that referenced in a `docker pull`, `docker run`, +or `docker service create` must be signed by a key corresponding to a member of the "CI" team. +In this case, the only member is the "jenkins" user. + +## Create keys for the Jenkins user + +The signing policy implementation uses the certificates issued in user client bundles +to connect a signature to a user. Using an incognito browser window (or otherwise), +log in to the "jenkins" user account you created earlier. Download a client bundle for +this user. It is also recommended to change the description associated with the public +key stored in UCP such that you can identify in the future which key is being used for +signing. + +N.B. each time a user retrieves a new client bundle, a new keypair is generated. It is therefore +necessary to keep track of a specific bundle that a user chooses to designate as their signing bundle. + +Once you have decompressed the client bundle, the only two files you need for the purposes +of signing are `cert.pem` and `key.pem`. These represent the public and private parts of +the user's signing identity respectively. We will load the `key.pem` file onto the Jenkins +servers, and user `cert.pem` to create delegations for the "jenkins" user in our +Trusted Collection. + +## Prepare the Jenkins server + +### Load `key.pem` on Jenkins + +You will need to use the notary client to load keys onto your Jenkins server. Simply run +`notary -d /path/to/.docker/trust key import /path/to/key.pem`. You will be asked to set +a password to encrypt the key on disk. For automated signing, this password can be configured +into the environment under the variable name `DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE`. The `-d` +flag to the command specifies the path to the `trust` subdirectory within the server's `docker` +configuration directory. Typically this is found at `~/.docker/trust`. + +### Enable content trust + +There are two ways to enable content trust: globally, and per operation. To enabled content +trust globally, set the environment variable `DOCKER_CONTENT_TRUST=1`. To enable on a per +operation basis, wherever you run `docker push` in your Jenkins scripts, add the flag +`--disable-content-trust=false`. You may wish to use this second option if you only want +to sign some images. + +The Jenkins server is now prepared to sign images, but we need to create delegations referencing +the key to give it the necessary permissions. + +## Initialize a repository + +Any commands displayed in this section should _not_ be run from the Jenkins server. You +will most likely want to run them from your local system. + +If this is a new repository, create it in Docker Trusted Registry (DTR) or Docker Hub, +depending on which you use to store your images, before proceeding further. + +We will now initialize the trust data and create the delegation that provides the Jenkins +key with permissions to sign content. The following commands initialize the trust data and +rotate snapshotting responsibilities to the server. This is necessary to ensure human involvement +it not required to publish new content. + +``` +notary -s https://my_notary_server.com -d ~/.docker/trust init my_repository +notary -s https://my_notary_server.com -d ~/.docker/trust key rotate my_repository snapshot -r +notary -s https://my_notary_server.com -d ~/.docker/trust publish my_repository +``` + +N.B. the `-s` flag provides the server hosting a notary service. If you are operating against +Docker Hub, this will be `https://notary.docker.io`. If you are operating against your own DTR +instance, this will be the same hostname you use in image names when running docker commands preceded +by the `https://` scheme. For example, if you would run `docker push my_dtr:4443/me/an_image` the value +of the `-s` flag would be expected to be `https://my_dtr:4443`. + +N.B. if you are using DTR, the name of the repository should be identical to the full name you use +in a `docker push` command. If however you use Docker Hub, the name you use in a `docker push` +must be preceded by `docker.io/`. i.e. if you ran `docker push me/alpine`, you would +`notary init docker.io/me/alpine`. + +For brevity, we will exclude the `-s` and `-d` flags from subsequent command, but be aware you +will still need to provide them for the commands to work correctly. + +Now that the repository is initialized, we need to create the delegations for Jenkins. Docker +Content Trust treats a delegation role called `targets/releases` specially. It considers this +delegation to contain the canonical list of published images for the repository. It is therefore +generally desiable to add all users to this delegation with the following command: + +``` +notary delegation add my_repository targets/releases --all-paths /path/to/cert.pem +``` + +This solves a number of prioritization problems that would result from needing to determine +which delegation should ultimately be trusted for a specific image. However, because it +is anticipated that any user will be able to sign the `targets/releases` role it is not trusted +in determining if a signing policy has been met. Therefore it is also necessary to create a +delegation specifically for Jenkins: + +``` +notary delegation add my_repository targets/jenkins --all-paths /path/to/cert.pem +``` + +We will then publish both these updates (remember to add the correct `-s` and `-d` flags): + +``` +notary publish my_repository +``` + +Informational (Advanced): If we included the `targets/releases` role in determining if a signing policy +had been met, we would run into the situation of images being opportunistically deployed when +an appropriate user signs. In the scenario we have described so far, only images signed by +the "CI" team (containing only the "jenkins" user) should be deployable. If a user "Moby" could +also sign images but was not part of the "CI" team, they might sign and publish a new `targets/releases` +that contained their image. UCP would refuse to deploy this image because it was not signed +by the "CI" team. However, the next time Jenkins published an image, it would update and sign +the `targets/releases` role as whole, enabling "Moby" to deploy their image. + +## Conclusion + +With the Trusted Collection initialized, and delegations created, the Jenkins server will +now use the key we imported to sign any images we push to this repository. + +Through either the Docker CLI, or the UCP browser interface, we will find that any images +that do not meet our signing policy cannot be used. The signing policy we set up requires +that the "CI" team must have signed any image we attempt to `docker pull`, `docker run`, +or `docker service create`, and the only member of that team is the "jenkins" user. This +restricts us to only running images that were published by our Jenkins CI system. diff --git a/datacenter/ucp/2.1/guides/user/content-trust/index.md b/datacenter/ucp/2.1/guides/user/content-trust/index.md new file mode 100644 index 0000000000..59bfb4423e --- /dev/null +++ b/datacenter/ucp/2.1/guides/user/content-trust/index.md @@ -0,0 +1,179 @@ +--- +description: Configure a Docker Universal Plane cluster to only allow running applications + that use images you trust. +keywords: docker, ucp, backup, restore, recovery +title: Run only the images you trust +--- + +With Docker Universal Control Plane (UCP) you can enforce applications to only use +Docker images signed by UCP users you trust. When a user tries to deploy an +application to the cluster, UCP checks if the application uses a Docker image +that is not trusted, and won't continue with the deployment if that's the case. + +By signing and verifying the Docker images, you ensure that the images being +used in your cluster are the ones you trust and haven't been altered either +in the image registry or on their way from the image registry to your UCP +cluster. + +## Configure UCP + +To configure UCP to only allow running applications that use Docker images you +trust, go to the **UCP web UI**, navigate to the **Settings** page, and click +the **Content Trust** tab. + + + +Select the **Run only signed images** option to only allow deploying +applications if they use images you trust. + +Then, in the **Require signature from** field, you can specify all the teams +that need sign the image, before it is trusted to run in the UCP cluster. If +you specify multiple teams, the image needs to be signed by a member of each +team, or someone that is a member of all those teams. +If you don't specify any team, the image will be trusted as long as it is signed +by any UCP user whose keys are trusted in a Notary delegation role. + +## Set up the Docker Notary CLI client + +Once you've configured UCP to only run applications that use Docker images you +trust, you'll need to specify which Docker images can be trusted. This is done +by using the Docker Notary server that is built into Docker Trusted Registry. +You'll configure the Notary server to store signed metadata about the Docker +images you trust. + +To interact with the Notary server, you need to +[install the Notary CLI client](https://github.com/docker/notary/releases). + +Once you've installed the Notary client, you need to configure it to talk to +the Notary server that is built into Docker Trusted Registry. This can be done +using a [Notary configuration file](/notary/reference/client-config.md) +or by running: + +```bash +# Create an alias to always have the notary client talking to the right server +$ alias notary="notary -s https:// -d ~/.docker/trust" +``` + +Where `-s` specifies the notary server to talk to, and `-d` specifies the +directory to store private keys and cache data. + +If your Docker Trusted Registry is not using certificates signed by a globally +trusted certificate authority, you'll also need to configure notary to use the +certificate of the DTR CA: + +```bash +$ alias notary="notary -s https:// -d ~/.docker/trust --tlscacert " +``` + +## Set up a trusted image repository + +Once your Docker Notary CLI client is configured, you can check if Notary has +information about a specific repository: + +```bash +# // is also known as a Globally Unique Name (GUN) +$ notary list // +``` + +If notary has information about the repository it returns the list of +image tags it knows about, their expected digests, and the role of the private +key used to sign the metadata. + +If Notary doesn't know yet about an image repository, run: + +```bash +$ notary init -p // +``` + +The Notary CLI client generates public and private key pairs, prompts you for +a passphrase to encrypt the private key, and stores the key pair in the +directory you've specified with the `notary -d` flag. +You should ensure you create backups for these keys, and that they are kept +securely and offline. +[Learn more about the keys used by Docker Notary.](/engine/security/trust/trust_key_mng.md) + +## Sign and push an image + +Now you can sign your images before pushing them to Docker Trusted Registry: + +```bash +# Setting Docker content trust makes the Docker CLI client sign images before pushing them +$ export DOCKER_CONTENT_TRUST=1 +# Push the image +$ docker push //: +``` + +The Docker CLI client will prompt you for the passphrase you used to encrypt the +private keys, sign the image, and push it to the registry. + + +## Delegate image signing + +Instead of signing the Docker images yourself, you can delegate that task +to other users. + +Delegation roles simplify collaborator workflows in Notary trusted collections, +and also allow for fine-grained permissions within a collection's contents +across delegations. +Delegation roles act as signers in Notary that are managed by the targets key +and can be configured to use external signing keys. Keys can be dynamically +added to or removed from delegation roles as collaborators join and leave +trusted repositories. +[Learn more about Notary delegation roles.](/notary/advanced_usage.md) + +Every change to the repository now needs to be signed by the snapshot key that +was generated with the `notary init` command. +To avoid having to distribute this key to other members so that they can also +sign images with this key, you can rotate the key and make it be managed by +the Notary server. + +This operation only needs to be done once for the repository. + +```bash +# This only needs to be done once for the repository +$ notary key rotate // snapshot --server-managed +``` + +Then ask the users you want to delegate the image signing to share with you +the `cert.pem` files that are included in their client bundles. These files +should be shared using a trusted channel. + +Then run the following command to create a new Notary delegation role, using the +user certificates: + +```bash +$ notary delegation add -p // targets/releases --all-paths user1.pem user2.pem +``` + +The above command adds the the `targets/releases` delegation role to a trusted +repository. +This role is treated as an actual release branch for Docker Content Trust, +since `docker pull` commands with trust enabled will pull directly from this +role, if data exists. +All users that can release images should be added to this role. +[Learn more about the targets/releases role](/engine/security/trust/trust_delegation.md). + +Notary has no limit on how many delegation roles can exist, so you can add more +delegation roles such as `targets/qa_team` or `targets/security_team` to the +trusted repository. + +Valid delegation roles take the form of `targets/`, where +`` does not include further slashes. + +You will need to add the key to at least one delegation in addition to the `targets/releases` delegation in order for UCP to honor the signed content: + +```bash +$ notary delegation add -p // targets/devops --all-paths user1.pem user2.pem +``` + +Before delegation role users can publish signed content with Notary or +Docker Content Trust, they must import the private key associated with the user certificate: + +```bash +$ notary key import key.pem +``` + +## Where to go next + +* [Manage trusted repositories](manage-trusted-repositories.md) +* [Get started with Notary](/notary/getting_started.md) diff --git a/datacenter/ucp/2.1/guides/user/content-trust/manage-trusted-repositories.md b/datacenter/ucp/2.1/guides/user/content-trust/manage-trusted-repositories.md new file mode 100644 index 0000000000..5db99fd55e --- /dev/null +++ b/datacenter/ucp/2.1/guides/user/content-trust/manage-trusted-repositories.md @@ -0,0 +1,126 @@ +--- +description: Learn how to use the Notary CLI client to manage trusted repositories +keywords: UCP, trust, notary, registry, security +title: Manage trusted repositories +--- + +Once you install the Notary CLI client, you can use it to manage your signing +keys, authorize other team members to sign images, and rotate the keys if +a private key has been compromised. + +When using the Notary CLI client you need to specify where is Notary server +you want to communicate with, and where to store the private keys and cache for +the CLI client. + +```bash +# Create an alias to always have the notary client talking to the right server +$ alias notary="notary -s https:// -d ~/.docker/trust" +``` + +## Manage staged changes + +The Notary CLI client stages changes before publishing them to the server. +You can manage the changes that are staged by running: + +```bash +# Check what changes are staged +$ notary status // + +# Unstage a specific change +$ notary status // --unstage 0 + +# Alternatively, unstage all changes +$ notary status // --reset +``` + +When you're ready to publish your chages to the Notary server, run: + +```bash +$ notary publish // +``` + +## Delete trust data + +Administrator users can remove all signatures from a trusted repository by +running: + +```bash +$ notary delete // --remote +``` + +If you don't include the `--remote` flag, Notary deletes local cached content +but will not delete data from the Notary server. + + +## Change the passphrase for a key + +The Notary CLI client manages the keys used to sign the image metadata. To +list all the keys managed by the Notary CLI client, run: + +```bash +$ notary key list +``` + +To chance the passphrase used to encrypt one of the keys, run: + +```bash +$ notary key passwd +``` + +## Rotate keys + +If one of the private keys is compromised you can rotate that key, so that +images that were signed with those keys stop being trusted. + +For keys that are kept offline and managed by the Notary CLI client, such the +keys with the root, targets, and snapshot roles, you can rotate them with: + +```bash +$ notary key rotate // +``` + +The Notary CLI client generates a new key for the role you specified, and +prompts you for a passphrase to encrypt it. +Then you're prompted for the passphrase for the key you're rotating, and if it +is correct, the Notary CLI client contacts the Notary server to publish the +change. + +You can also rotate keys that are stored in the Notary server, such as the keys +with the snapshot or timestamp role. For that, run: + +```bash +$ notary key rotate // --server-managed +``` + +## Manage keys for delegation roles + +To delegate image signing to other UCP users, get the `cert.pem` file that's +included in their client bundle and run: + +```bash +$ notary delegation add -p // targets/ --all-paths user1.pem user2.pem +``` + +You can also remove keys from a delegation role: + +```bash +# Remove the given keys from a delegation role +$ notary delegation remove -p // targets/ + +# Alternatively, you can remove keys from all delegation roles +$ notary delegation purge // --key --key +``` + +## Troubleshooting + +Notary CLI has a `-D` flag that you can use to increase the logging level. You +can use this for troubleshooting. + +Usually most problems are fixed by ensuring you're communicating with the +correct Notary server, using the `-s` flag, and that you're using the correct +directory where your private keys are stored, with the `-d` flag. + +## Where to go next + +* [Run only the images you trust](index.md) +* [Get started with Notary](/notary/getting_started.md)