Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Import key and cert #821

Closed
wants to merge 4 commits into from
Closed

Conversation

dnwake
Copy link

@dnwake dnwake commented Jul 8, 2016

This addresses docker#731 by allowing the import of root certs in addition to root keys, using the command-line argument --rootcert. It builds on top of the pre-existing pull request at #801

This allows us to ensure that we only ever pull values from Notary that have been pushed by trusted clients (who had access to a secret trust-pinning private key). (See worked example below).

Synopsis:

notary init [--rootkey PRIVATE_KEY] [--rootcert CERT] GUN

Behavior:

  --rootcert   | --rootkey    |
   specified?  |  specified?  |     
               |              |
---------------+--------------+-----------------------------------------------------
               |              |
      NO       |     NO       |    Both key and cert are generated by Notary
               |              |               (current behavior)
               |              |
---------------+--------------+-----------------------------------------------------
               |              |
      NO       |     YES      |    The key is imported, and the cert is generated
               |              |             by Notary from the key
               |              |
---------------+--------------+-----------------------------------------------------
               |              |
      YES      |     NO       |                   Error
               |              |
---------------+--------------+-----------------------------------------------------
               |              |
               |              |    The private key is compared with the public
               |              |      key of the cert.  If they do not form a
      YES      |     YES      |      valid keypair, an Error is thrown.
               |              |    Otherwise, the key and cert are used to
               |              |      initialize the collection.
               |              |
---------------+--------------+-----------------------------------------------------

Notes:

The PRIVATE_KEY specified as the argument to --rootkey must be encrypted.
If the environment variable NOTARY_DELEGATION_PASSPHRASE is set, its
value will be used as the passphrase to decrypt the key.  Otherwise, the 
passphrase will be requested interactively.  

Known issues:

The environment variable used to decrypt the private key should be 
NOTARY_ROOT_PASSPHRASE rather than 
NOTARY_DELEGATION_PASSPHRASE

Example of usage (combined with trust-pinning):

## Generate trust_pinning keypair that will sign all other GUN keypairs
##  the private key will be distributed only to clients authorized to push to Notary.
##  the public key will be distributed to any clients authorized to pull from Notary
> cd /root
> openssl genrsa -out trust_pinning.key 2048
> openssl req -new -sha256 -key trust_pinning.key -out trust_pinning.csr -subj "/C=XX/ST=XX/L=XX/O=XX/OU=XX/CN=XX"
> openssl x509 -req -days 1000 -in trust_pinning.csr -signkey trust_pinning.key -out trust_pinning.crt

## Generate a new child keypair to initialize Notary for this new GUN
###  Sign the cert with the trust_pinning keypair.
> openssl genrsa -aes128 -passout pass:my_passphrase 2048 > /tmp/new_gun.key
> openssl req -sha256 -passin pass:my_passphrase -new -key /tmp/new_gun.key -out /tmp/new_gun.csr -subj '/C=XX/ST=XX/L=XX/O=XX/OU=XX/CN=GUN_FROM_TRUSTED_CLIENT'
> openssl x509 -passin pass:my_passphrase -req -days 1000 -sha256 -in /tmp/new_gun.csr -out /tmp/new_gun.crt -CAkey /root/trust_pinning.key -CA /root/trust_pinning.crt -CAserial /root/trust_pinning.srl -CAcreateserial

## Create a GUN that uses the keypair we've just created, then publish to Notary
> NOTARY_DELEGATION_PASSPHRASE=my_passphrase  \
notary init --rootkey /tmp/new_gun.key --rootcert /tmp/new_gun.crt GUN_FROM_TRUSTED_CLIENT
> echo foo > /tmp/foo
> notary add GUN_FROM_TRUSTED_CLIENT foo /tmp/foo
> NOTARY_DELEGATION_PASSPHRASE=my_passphrase \
notary -s https://notary-server:4443 publish GUN_FROM_TRUSTED_CLIENT

## For comparison, create and publish another GUN that has an automatically generated keypair.
##  This GUN could have been created by an untrusted client that did not have access to the 
##   secret trust-pinning key
> NOTARY_ROOT_PASSPHRASE=my_passphrase \
NOTARY_TARGETS_PASSPHRASE=targets \
NOTARY_SNAPSHOT_PASSPHRASE=shapshot \
notary init GUN_FROM_UNTRUSTED_CLIENT
> notary add GUN_FROM_UNTRUSTED_CLIENT foo /tmp/foo
> NOTARY_TARGETS_PASSPHRASE=targets \
NOTARY_SNAPSHOT_PASSPHRASE=shapshot \
notary -s https://notary-server:4443 publish GUN_FROM_UNTRUSTED_CLIENT

## Now set up trust pinning to require that all root certs be signed by the
##  master trust_pinning cert we created earlier
> echo '{ "trust_pinning": { "disable_tofu": "true","ca": { "":"/root/trust_pinning.crt" } } }' > /root/.notary/config.json

## Verify that read is successful on GUN_FROM_TRUSTED_CLIENT
> rm -fr /tmp/empty_dir; mkdir -p /tmp/empty_dir
> notary -s https://notary-server:4443 -d /tmp/empty_dir list GUN_FROM_TRUSTED_CLIENT
  NAME                                DIGEST                                SIZE (BYTES)    ROLE
----------------------------------------------------------------------------------------------------
  foo    b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c   4              targets

## Verify that read fails on GUN_FROM_UNTRUSTED_CLIENT, because its root cert violates
##  the trust pinning config we set up earlier.
> rm -fr /tmp/empty_dir; mkdir -p /tmp/empty_dir
> notary -s https://notary-server:4443 -d /tmp/empty_dir list GUN_FROM_UNTRUSTED_CLIENT

* fatal: could not validate the path to a trusted root: unable to match any certificates to trust_pinning config

@docker-jenkins
Copy link

Can one of the admins verify this patch?

@dnwake dnwake force-pushed the import_key_and_cert branch 2 times, most recently from f039a08 to 6587a98 Compare July 8, 2016 07:17
@cyli
Copy link
Contributor

cyli commented Jul 8, 2016

jenkins test this please

@@ -246,6 +256,10 @@ func (t *tufCommander) tufInit(cmd *cobra.Command, args []string) error {
return fmt.Errorf("Must specify a GUN")
}

if t.rootCert != "" && t.rootKey == "" {
return fmt.Errorf("--rootCert specified without --rootKey being specified")
Copy link
Contributor

@riyazdf riyazdf Jul 8, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should completely lowercase --rootcert and --rootkey to match the flags

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks -- will correct.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@riyazdf Fixed in latest push c2baf9e

@GordonTheTurtle
Copy link

Please sign your commits following these rules:
https://github.com/docker/docker/blob/master/CONTRIBUTING.md#sign-your-work
The easiest way to do this is to amend the last commit:

$ git clone -b "import_key_and_cert" [email protected]:dnwake/notary.git somewhere
$ cd somewhere
$ git rebase -i HEAD~3
editor opens
change each 'pick' to 'edit'
save the file and quit
$ git commit --amend -s --no-edit
$ git rebase --continue # and repeat the amend for each commit
$ git push -f

Ammending updates the existing PR. You DO NOT need to open a new one.

1 similar comment
@GordonTheTurtle
Copy link

Please sign your commits following these rules:
https://github.com/docker/docker/blob/master/CONTRIBUTING.md#sign-your-work
The easiest way to do this is to amend the last commit:

$ git clone -b "import_key_and_cert" [email protected]:dnwake/notary.git somewhere
$ cd somewhere
$ git rebase -i HEAD~3
editor opens
change each 'pick' to 'edit'
save the file and quit
$ git commit --amend -s --no-edit
$ git rebase --continue # and repeat the amend for each commit
$ git push -f

Ammending updates the existing PR. You DO NOT need to open a new one.

@@ -1,68 +1,62 @@
-----BEGIN CERTIFICATE-----
MIIFWzCCA0OgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBfMRowGAYDVQQDDBFOb3Rh
Copy link
Contributor

@riyazdf riyazdf Aug 1, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you try rebasing on to master? We bumped all of the fixture certificates a little while back in #842, so you probably won't need this change or the next commit ("Reissued all certs with correct SANs")

@endophage
Copy link
Contributor

@dnwake just checking if you're going to get back to this. There have been a lot of changes so unless you're going to pick it up I'm going to close this and work can start anew in a different PR at some point.

@dnwake
Copy link
Author

dnwake commented Mar 9, 2017

@endophage I intend to get back to it, but haven't had time so far.

Copy link

@cyc115 cyc115 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Questions about the implementation

@endophage
Copy link
Contributor

This has been superseded by #1144 and #1147

@endophage endophage closed this May 9, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants