mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Merge pull request #16894 from diogomonica/renaming-trust-keys
Renaming trust keys
This commit is contained in:
commit
bf80adeee4
8 changed files with 181 additions and 80 deletions
|
@ -185,16 +185,30 @@ func convertTarget(t client.Target) (target, error) {
|
|||
|
||||
func (cli *DockerCli) getPassphraseRetriever() passphrase.Retriever {
|
||||
aliasMap := map[string]string{
|
||||
"root": "offline",
|
||||
"snapshot": "tagging",
|
||||
"targets": "tagging",
|
||||
"root": "root",
|
||||
"snapshot": "repository",
|
||||
"targets": "repository",
|
||||
}
|
||||
baseRetriever := passphrase.PromptRetrieverWithInOut(cli.in, cli.out, aliasMap)
|
||||
env := map[string]string{
|
||||
"root": os.Getenv("DOCKER_CONTENT_TRUST_OFFLINE_PASSPHRASE"),
|
||||
"snapshot": os.Getenv("DOCKER_CONTENT_TRUST_TAGGING_PASSPHRASE"),
|
||||
"targets": os.Getenv("DOCKER_CONTENT_TRUST_TAGGING_PASSPHRASE"),
|
||||
"root": os.Getenv("DOCKER_CONTENT_TRUST_ROOT_PASSPHRASE"),
|
||||
"snapshot": os.Getenv("DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE"),
|
||||
"targets": os.Getenv("DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE"),
|
||||
}
|
||||
|
||||
// Backwards compatibility with old env names. We should remove this in 1.10
|
||||
if env["root"] == "" {
|
||||
env["root"] = os.Getenv("DOCKER_CONTENT_TRUST_OFFLINE_PASSPHRASE")
|
||||
fmt.Fprintf(cli.err, "[DEPRECATED] The environment variable DOCKER_CONTENT_TRUST_OFFLINE_PASSPHRASE has been deprecated and will be removed in v1.10. Please use DOCKER_CONTENT_TRUST_ROOT_PASSPHRASE\n")
|
||||
|
||||
}
|
||||
if env["snapshot"] == "" || env["targets"] == "" {
|
||||
env["snapshot"] = os.Getenv("DOCKER_CONTENT_TRUST_TAGGING_PASSPHRASE")
|
||||
env["targets"] = os.Getenv("DOCKER_CONTENT_TRUST_TAGGING_PASSPHRASE")
|
||||
fmt.Fprintf(cli.err, "[DEPRECATED] The environment variable DOCKER_CONTENT_TRUST_TAGGING_PASSPHRASE has been deprecated and will be removed in v1.10. Please use DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE\n")
|
||||
|
||||
}
|
||||
|
||||
return func(keyName string, alias string, createNew bool, numAttempts int) (string, bool, error) {
|
||||
if v := env[alias]; v != "" {
|
||||
return v, numAttempts > 1, nil
|
||||
|
|
|
@ -105,4 +105,9 @@ the path does not exist.
|
|||
|
||||
Version 1.9 adds a flag (`--disable-legacy-registry=false`) which prevents the docker daemon from `pull`, `push`, and `login` operations against v1 registries. Though disabled by default, this signals the intent to deprecate the v1 protocol.
|
||||
|
||||
### Docker Content Trust ENV passphrase variables name change
|
||||
|
||||
As of 1.9, Docker Content Trust Offline key will be renamed to Root key and the Tagging key will be renamed to Repository key. Due to this renaming, we're also changing the corresponding environment variables
|
||||
|
||||
- DOCKER_CONTENT_TRUST_OFFLINE_PASSPHRASE will now be named DOCKER_CONTENT_TRUST_ROOT_PASSPHRASE
|
||||
- DOCKER_CONTENT_TRUST_TAGGING_PASSPHRASE will now be named DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE
|
|
@ -110,8 +110,8 @@ trust makes use of four different keys:
|
|||
|
||||
| Key | Description |
|
||||
|---------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| offline key | Root of content trust for a image tag. When content trust is enabled, you create the offline key once. |
|
||||
| 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. |
|
||||
| root key | Root of content trust for a image tag. When content trust is enabled, you create the root key once. |
|
||||
| target and snapshot | These two keys are known together as the "repository" key. When content trust is enabled, you create this key when you add a new image repository. If you have the root key, you can export the repository key and allow other publishers to sign the image tags. |
|
||||
| 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. |
|
||||
|
||||
With the exception of the timestamp, all the keys are generated and stored locally
|
||||
|
@ -123,13 +123,13 @@ The following image depicts the various signing keys and their relationships:
|
|||
|
||||
![Content trust components](../images/trust_components.png)
|
||||
|
||||
>**WARNING**: Loss of the offline key is **very difficult** to recover from.
|
||||
>**WARNING**: Loss of the root key is **very difficult** to recover from.
|
||||
>Correcting this loss requires intervention from [Docker
|
||||
>Support](https://support.docker.com) to reset the repository state. This loss
|
||||
>also requires **manual intervention** from every consumer that used a signed
|
||||
>tag from this repository prior to the loss.
|
||||
|
||||
You should backup the offline key somewhere safe. Given that it is only required
|
||||
You should backup the root key somewhere safe. Given that it is only required
|
||||
to create new repositories, it is a good idea to store it offline. Make sure you
|
||||
read [Manage keys for content trust](/security/trust/trust_key_mng) information
|
||||
for details on securing, and backing up your keys.
|
||||
|
@ -185,27 +185,27 @@ The push refers to a repository [docker.io/docker/trusttest] (len: 1)
|
|||
902b87aaaec9: Image already exists
|
||||
latest: digest: sha256:d02adacee0ac7a5be140adb94fa1dae64f4e71a68696e7f8e7cbf9db8dd49418 size: 3220
|
||||
Signing and pushing trust metadata
|
||||
You are about to create a new offline signing key passphrase. This passphrase
|
||||
You are about to create a new root signing key passphrase. This passphrase
|
||||
will be used to protect the most sensitive key in your signing system. Please
|
||||
choose a long, complex passphrase and be careful to keep the password and the
|
||||
key file itself secure and backed up. It is highly recommended that you use a
|
||||
password manager to generate the passphrase and keep it safe. There will be no
|
||||
way to recover this key. You can find the key in your config directory.
|
||||
Enter passphrase for new offline key with id a1d96fb:
|
||||
Repeat passphrase for new offline key with id a1d96fb:
|
||||
Enter passphrase for new tagging key with id docker.io/docker/trusttest (3a932f1):
|
||||
Repeat passphrase for new tagging key with id docker.io/docker/trusttest (3a932f1):
|
||||
Enter passphrase for new root key with id a1d96fb:
|
||||
Repeat passphrase for new root key with id a1d96fb:
|
||||
Enter passphrase for new repository key with id docker.io/docker/trusttest (3a932f1):
|
||||
Repeat passphrase for new repository key with id docker.io/docker/trusttest (3a932f1):
|
||||
Finished initializing "docker.io/docker/trusttest"
|
||||
```
|
||||
When you push your first tagged image with content trust enabled, the `docker`
|
||||
client recognizes this is your first push and:
|
||||
|
||||
- alerts you that it will create a new offline key
|
||||
- alerts you that it will create a new root key
|
||||
- requests a passphrase for the key
|
||||
- generates an offline key in the `~/.docker/trust` directory
|
||||
- generates a tagging key for in the `~/.docker/trust` directory
|
||||
- generates a root key in the `~/.docker/trust` directory
|
||||
- generates a repository key for in the `~/.docker/trust` directory
|
||||
|
||||
The passphrase you chose for both the offline key and your content key-pair
|
||||
The passphrase you chose for both the root key and your content key-pair
|
||||
should be randomly generated and stored in a *password manager*.
|
||||
|
||||
> **NOTE**: If you omit the `latest` tag, content trust is skipped. This is true
|
||||
|
@ -223,8 +223,8 @@ No tag specified, skipping trust metadata push
|
|||
It is skipped because as the message states, you did not supply an image `TAG`
|
||||
value. In Docker content trust, signatures are associated with tags.
|
||||
|
||||
Once you have an offline key on your system, subsequent images repositories
|
||||
you create can use that same offline key:
|
||||
Once you have a root key on your system, subsequent images repositories
|
||||
you create can use that same root key:
|
||||
|
||||
```bash
|
||||
$ docker push docker.io/docker/seaside:latest
|
||||
|
@ -233,13 +233,13 @@ a9539b34a6ab: Image successfully pushed
|
|||
b3dbab3810fc: Image successfully pushed
|
||||
latest: digest: sha256:d2ba1e603661a59940bfad7072eba698b79a8b20ccbb4e3bfb6f9e367ea43939 size: 3346
|
||||
Signing and pushing trust metadata
|
||||
Enter key passphrase for offline key with id a1d96fb:
|
||||
Enter passphrase for new tagging key with id docker.io/docker/seaside (bb045e3):
|
||||
Repeat passphrase for new tagging key with id docker.io/docker/seaside (bb045e3):
|
||||
Enter key passphrase for root key with id a1d96fb:
|
||||
Enter passphrase for new repository key with id docker.io/docker/seaside (bb045e3):
|
||||
Repeat passphrase for new repository key with id docker.io/docker/seaside (bb045e3):
|
||||
Finished initializing "docker.io/docker/seaside"
|
||||
```
|
||||
|
||||
The new image has its own tagging key and timestamp key. The `latest` tag is signed with both of
|
||||
The new image has its own repository key and timestamp key. The `latest` tag is signed with both of
|
||||
these.
|
||||
|
||||
|
||||
|
|
|
@ -18,16 +18,16 @@ To allow tools to wrap docker and push trusted content, there are two
|
|||
environment variables that allow you to provide the passphrases without an
|
||||
expect script, or typing them in:
|
||||
|
||||
- `DOCKER_CONTENT_TRUST_OFFLINE_PASSPHRASE`
|
||||
- `DOCKER_CONTENT_TRUST_TAGGING_PASSPHRASE`
|
||||
- `DOCKER_CONTENT_TRUST_ROOT_PASSPHRASE`
|
||||
- `DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE`
|
||||
|
||||
Docker attempts to use the contents of these environment variables as passphrase
|
||||
for the keys. For example, an image publisher can export the repository `target`
|
||||
and `snapshot` passphrases:
|
||||
|
||||
```bash
|
||||
$ export DOCKER_CONTENT_TRUST_OFFLINE_PASSPHRASE="u7pEQcGoebUHm6LHe6"
|
||||
$ export DOCKER_CONTENT_TRUST_TAGGING_PASSPHRASE="l7pEQcTKJjUHm6Lpe4"
|
||||
$ export DOCKER_CONTENT_TRUST_ROOT_PASSPHRASE="u7pEQcGoebUHm6LHe6"
|
||||
$ export DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE="l7pEQcTKJjUHm6Lpe4"
|
||||
```
|
||||
|
||||
Then, when pushing a new tag the Docker client does not request these values but signs automatically:
|
||||
|
|
|
@ -15,8 +15,8 @@ trust makes use four different keys:
|
|||
|
||||
| Key | Description |
|
||||
|---------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| offline key | Root of content trust for a image tag. When content trust is enabled, you create the offline key once. |
|
||||
| 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. |
|
||||
| root key | Root of content trust for a image tag. When content trust is enabled, you create the root key once. |
|
||||
| target and snapshot | These two keys are known together as the "repository" key. When content trust is enabled, you create this key when you add a new image repository. If you have the root key, you can export the repository key and allow other publishers to sign the image tags. |
|
||||
| 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. |
|
||||
|
||||
With the exception of the timestamp, all the keys are generated and stored locally
|
||||
|
@ -26,8 +26,8 @@ service that isn't directly exposed to the internet and are encrypted at rest.
|
|||
|
||||
## Choosing a passphrase
|
||||
|
||||
The passphrases you chose for both the offline key and your tagging key should
|
||||
be randomly generated and stored in a password manager. Having the tagging key
|
||||
The passphrases you chose for both the root key and your repository key should
|
||||
be randomly generated and stored in a password manager. Having the repository key
|
||||
allow users to sign image tags on a repository. Passphrases are used to encrypt
|
||||
your keys at rest and ensures that a lost laptop or an unintended backup doesn't
|
||||
put the private key material at risk.
|
||||
|
@ -39,7 +39,7 @@ on creation. Even so, you should still take care of the location where you back
|
|||
Good practice is to create two encrypted USB keys.
|
||||
|
||||
It is very important that you backup your keys to a safe, secure location. Loss
|
||||
of the tagging key is recoverable; loss of the offline key is not.
|
||||
of the repository key is recoverable; loss of the root key is not.
|
||||
|
||||
The Docker client stores the keys in the `~/.docker/trust/private` directory.
|
||||
Before backing them up, you should `tar` them into an archive:
|
||||
|
|
|
@ -48,7 +48,7 @@ The sandbox uses the Docker daemon on your local system. Within the `notarysandb
|
|||
you interact with a local registry rather than the Docker Hub. This means
|
||||
your everyday image repositories are not used. They are protected while you play.
|
||||
|
||||
When you play in the sandbox, you'll also create root and tagging keys. The
|
||||
When you play in the sandbox, you'll also create root and repository keys. The
|
||||
sandbox is configured to store all the keys and files inside the `notarysandbox`
|
||||
container. Since the keys you create in the sandbox are for play only,
|
||||
destroying the container destroys them as well.
|
||||
|
@ -247,10 +247,10 @@ Now, you'll pull some images.
|
|||
key file itself secure and backed up. It is highly recommended that you use a
|
||||
password manager to generate the passphrase and keep it safe. There will be no
|
||||
way to recover this key. You can find the key in your config directory.
|
||||
Enter passphrase for new offline key with id 8c69e04:
|
||||
Repeat passphrase for new offline key with id 8c69e04:
|
||||
Enter passphrase for new tagging key with id sandboxregistry:5000/test/trusttest (93c362a):
|
||||
Repeat passphrase for new tagging key with id sandboxregistry:5000/test/trusttest (93c362a):
|
||||
Enter passphrase for new root key with id 8c69e04:
|
||||
Repeat passphrase for new root key with id 8c69e04:
|
||||
Enter passphrase for new repository key with id sandboxregistry:5000/test/trusttest (93c362a):
|
||||
Repeat passphrase for new repository key with id sandboxregistry:5000/test/trusttest (93c362a):
|
||||
Finished initializing "sandboxregistry:5000/test/trusttest"
|
||||
latest: digest: sha256:d149ab53f8718e987c3a3024bb8aa0e2caadf6c0328f1d9d850b2a2a67f2819a size: 3355
|
||||
Signing and pushing trust metadata
|
||||
|
|
|
@ -142,6 +142,40 @@ func (s *DockerTrustSuite) TestTrustedPush(c *check.C) {
|
|||
}
|
||||
}
|
||||
|
||||
func (s *DockerTrustSuite) TestTrustedPushWithEnvPasswords(c *check.C) {
|
||||
repoName := fmt.Sprintf("%v/dockercli/trusted:latest", privateRegistryURL)
|
||||
// tag the image and upload it to the private registry
|
||||
dockerCmd(c, "tag", "busybox", repoName)
|
||||
|
||||
pushCmd := exec.Command(dockerBinary, "push", repoName)
|
||||
s.trustedCmdWithPassphrases(pushCmd, "12345678", "12345678")
|
||||
out, _, err := runCommandWithOutput(pushCmd)
|
||||
if err != nil {
|
||||
c.Fatalf("Error running trusted push: %s\n%s", err, out)
|
||||
}
|
||||
if !strings.Contains(string(out), "Signing and pushing trust metadata") {
|
||||
c.Fatalf("Missing expected output on trusted push:\n%s", out)
|
||||
}
|
||||
}
|
||||
|
||||
// This test ensures backwards compatibility with old ENV variables. Should be
|
||||
// deprecated by 1.10
|
||||
func (s *DockerTrustSuite) TestTrustedPushWithDeprecatedEnvPasswords(c *check.C) {
|
||||
repoName := fmt.Sprintf("%v/dockercli/trusteddeprecated:latest", privateRegistryURL)
|
||||
// tag the image and upload it to the private registry
|
||||
dockerCmd(c, "tag", "busybox", repoName)
|
||||
|
||||
pushCmd := exec.Command(dockerBinary, "push", repoName)
|
||||
s.trustedCmdWithDeprecatedEnvPassphrases(pushCmd, "12345678", "12345678")
|
||||
out, _, err := runCommandWithOutput(pushCmd)
|
||||
if err != nil {
|
||||
c.Fatalf("Error running trusted push: %s\n%s", err, out)
|
||||
}
|
||||
if !strings.Contains(string(out), "Signing and pushing trust metadata") {
|
||||
c.Fatalf("Missing expected output on trusted push:\n%s", out)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *DockerTrustSuite) TestTrustedPushWithFaillingServer(c *check.C) {
|
||||
repoName := fmt.Sprintf("%v/dockercli/trusted:latest", privateRegistryURL)
|
||||
// tag the image and upload it to the private registry
|
||||
|
@ -268,6 +302,38 @@ func (s *DockerTrustSuite) TestTrustedPushWithIncorrectPassphraseForNonRoot(c *c
|
|||
}
|
||||
}
|
||||
|
||||
// This test ensures backwards compatibility with old ENV variables. Should be
|
||||
// deprecated by 1.10
|
||||
func (s *DockerTrustSuite) TestTrustedPushWithIncorrectDeprecatedPassphraseForNonRoot(c *check.C) {
|
||||
repoName := fmt.Sprintf("%v/dockercliincorretdeprecatedpwd/trusted:latest", privateRegistryURL)
|
||||
// tag the image and upload it to the private registry
|
||||
dockerCmd(c, "tag", "busybox", repoName)
|
||||
|
||||
// Push with default passphrases
|
||||
pushCmd := exec.Command(dockerBinary, "push", repoName)
|
||||
s.trustedCmd(pushCmd)
|
||||
out, _, err := runCommandWithOutput(pushCmd)
|
||||
if err != nil {
|
||||
c.Fatalf("trusted push failed: %s\n%s", err, out)
|
||||
}
|
||||
|
||||
if !strings.Contains(string(out), "Signing and pushing trust metadata") {
|
||||
c.Fatalf("Missing expected output on trusted push:\n%s", out)
|
||||
}
|
||||
|
||||
// Push with wrong passphrases
|
||||
pushCmd = exec.Command(dockerBinary, "push", repoName)
|
||||
s.trustedCmdWithDeprecatedEnvPassphrases(pushCmd, "12345678", "87654321")
|
||||
out, _, err = runCommandWithOutput(pushCmd)
|
||||
if err == nil {
|
||||
c.Fatalf("Error missing from trusted push with short targets passphrase: \n%s", out)
|
||||
}
|
||||
|
||||
if !strings.Contains(string(out), "password invalid, operation has failed") {
|
||||
c.Fatalf("Missing expected output on trusted push with short targets/snapsnot passphrase:\n%s", out)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *DockerTrustSuite) TestTrustedPushWithExpiredSnapshot(c *check.C) {
|
||||
c.Skip("Currently changes system time, causing instability")
|
||||
repoName := fmt.Sprintf("%v/dockercliexpiredsnapshot/trusted:latest", privateRegistryURL)
|
||||
|
|
|
@ -124,11 +124,27 @@ func (s *DockerTrustSuite) trustedCmdWithServer(cmd *exec.Cmd, server string) {
|
|||
trustCmdEnv(cmd, server, pwd, pwd)
|
||||
}
|
||||
|
||||
func (s *DockerTrustSuite) trustedCmdWithPassphrases(cmd *exec.Cmd, offlinePwd, taggingPwd string) {
|
||||
trustCmdEnv(cmd, notaryURL, offlinePwd, taggingPwd)
|
||||
func (s *DockerTrustSuite) trustedCmdWithPassphrases(cmd *exec.Cmd, rootPwd, repositoryPwd string) {
|
||||
trustCmdEnv(cmd, notaryURL, rootPwd, repositoryPwd)
|
||||
}
|
||||
|
||||
func trustCmdEnv(cmd *exec.Cmd, server, offlinePwd, taggingPwd string) {
|
||||
func (s *DockerTrustSuite) trustedCmdWithDeprecatedEnvPassphrases(cmd *exec.Cmd, offlinePwd, taggingPwd string) {
|
||||
trustCmdDeprecatedEnv(cmd, notaryURL, offlinePwd, taggingPwd)
|
||||
}
|
||||
|
||||
func trustCmdEnv(cmd *exec.Cmd, server, rootPwd, repositoryPwd string) {
|
||||
env := []string{
|
||||
"DOCKER_CONTENT_TRUST=1",
|
||||
fmt.Sprintf("DOCKER_CONTENT_TRUST_SERVER=%s", server),
|
||||
fmt.Sprintf("DOCKER_CONTENT_TRUST_ROOT_PASSPHRASE=%s", rootPwd),
|
||||
fmt.Sprintf("DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE=%s", repositoryPwd),
|
||||
}
|
||||
cmd.Env = append(os.Environ(), env...)
|
||||
}
|
||||
|
||||
// Helper method to test the old env variables OFFLINE and TAGGING that will
|
||||
// be deprecated by 1.10
|
||||
func trustCmdDeprecatedEnv(cmd *exec.Cmd, server, offlinePwd, taggingPwd string) {
|
||||
env := []string{
|
||||
"DOCKER_CONTENT_TRUST=1",
|
||||
fmt.Sprintf("DOCKER_CONTENT_TRUST_SERVER=%s", server),
|
||||
|
|
Loading…
Reference in a new issue