-
Notifications
You must be signed in to change notification settings - Fork 2.1k
docker trust: interact with signers and keys #566
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
Conversation
|
Just from the description; should we think of making |
|
@thaJeztah: we kept For most users the flows will look something like: |
|
I like it either as it is now, or as another level under Moving them to the top level would be confusing. |
works for me; would that be more difficult to implement (as we currently don't have sub-sub commands)? |
|
Shouldn't be. All we need is a couple additional |
|
@dnephin @thaJeztah : sounds good! Are we okay with these being one of the only (if not the only) commands in If there's consensus I'm happy to make the change. |
|
I'm OK with it; it may be slightly awkward to have the commands nested this deep, but with the context given above, I think it's the best option (and most consistent with other commands as in ping @docker/core-cli-maintainers PTAL |
|
The completions are not equipped for another nesting level, so I'd prefer the less deeply nested forms. |
|
I'm ok with We almost went for |
|
Ok! From discussions with @dnephin, @thaJeztah, @vdemeester, @stevvooe, and @vieux : it sounds like I'm not sure what the implications are for bash completions, is it possible to make it work with this level deep of commands? |
|
For bash completion it will be 0.5 to 3 days of work. I'm also not sure about the implications on zsh and fish completion. |
a3eeeaf to
0dc16d3
Compare
|
@albers: got it. I've moved the commands around to be a level lower, now we have: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks!
The UX generally seems good to me, although I'm not all that familiar with the workflow.
The design also generally seems good, the only major issue is the addition of 12 new unnecessary dependencies. I think this needs to be fixed in notary before we can merge.
Comments are mostly code review, small changes to match conventions and refactors to reduce arg counts.
cli/command/trust/key_generate.go
Outdated
| func setupPassphraseAndGenerateKeys(streams command.Streams, keyName string) error { | ||
| // always use a fresh passphrase for each key generation | ||
| freshPassRetGetter := func() notary.PassRetriever { return trust.GetPassphraseRetriever(streams.In(), streams.Out()) } | ||
| cwd, err := os.Getwd() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe this could have a flag to set the target directory, and default to the working directory if the flag isn't set? I'm not sure where these keys would normally be placed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
agreed! Added.
cli/command/trust/key_generate.go
Outdated
| return validateAndGenerateKey(streams, keyName, cwd, freshPassRetGetter) | ||
| } | ||
|
|
||
| func validateAndGenerateKey(streams command.Streams, keyName string, workingDir string, passphraseGetter func() notary.PassRetriever) error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
passphraseGetter seems like an unnecessary argument because it could be created in this function from streams.
keyName and directory could be part of an options struct (if it makes sense to allow setting of a target directory).
cli/command/trust/key_generate.go
Outdated
| return nil | ||
| } | ||
|
|
||
| func generateKey(keyName, pubDir, privTrustDir string, passRet notary.PassRetriever) error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
privTrustDir and passRet are only used once as args to the same function, so they can be replaced with a single arg keyStore.
pubDir is only used once, at the very end of the function, and I believe the line where it's used is actually duplicated by the caller, so it seems like it could be removed as well, and this function could return the pubPEM. The file write could be done by the caller, which would remove the duplicate line, and the extra arg.
maybe something like:
func generatePublicPEM(keyName string, keyStore trust.KeyStore) *pem.Block { ... }
cli/command/trust/key_load.go
Outdated
| return nil | ||
| } | ||
|
|
||
| func loadPrivKeyFromPath(privKeyImporters []utils.Importer, keyPath, keyName string, passRet notary.PassRetriever) error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
privKeyImporters, keyName, and passRet are all only used once, as args to the same function, on the very last line of this function. Instead of passing in these 3 args, the function could return a io.Reader, and ImportKeys can be called from the caller of this function.
func getPrivKeyFromPath(keyPath string) (error, io.Reader) {
...
return bytes.NewReader(keyBytes), nil
}
cli/command/trust/key_load_test.go
Outdated
|
|
||
| func TestLoadKeyFromPath(t *testing.T) { | ||
| for keyID, keyBytes := range testKeys { | ||
| testLoadKeyFromPath(t, keyID, keyBytes) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To make it easier to debug failures in this test I would suggest wrapping this call in a https://golang.org/pkg/testing/#T.Run and using the keyID as the name (or possibly a more descriptive string).
That will also let you replace the assert.NoError() calls with require.NoError() and still test both cases if there is a failure in the first (because t.Fatal() only exits the t.Run())
same below in TestLoadKeyTooPermissive
cli/command/trust/signer_remove.go
Outdated
| Short: "Remove a signer", | ||
| Args: cli.RequiresMinArgs(2), | ||
| RunE: func(cmd *cobra.Command, args []string) error { | ||
| return removeSigner(dockerCli, args[0], args[1:], &options) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Most commands (including newSignerAddCommand above) pass args using the options struct instead of separate args. I think it would be good to do that here as well.
Also it shouldn't be necessary to use a pointer for options. The values should never be modified, so I believe we pass a struct (not a pointer) in all other commands.
cli/command/trust/signer_remove.go
Outdated
| }, | ||
| } | ||
| flags := cmd.Flags() | ||
| flags.BoolVarP(&options.forceYes, "yes", "y", false, "Answer yes to removing most recent signer (no confirmation)") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should probably say something like "do not prompt for confirmation before ..." or something along those lines
cli/command/trust/signer_remove.go
Outdated
| return counter < releasesRoleWithSigs.Threshold, nil | ||
| } | ||
|
|
||
| func removeSingleSigner(cli command.Cli, image, signerName string, forceYes bool) error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When signerName is part of options I think signerName and forceYes can be replaced with options signerRemoveOptions
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I left this function signature as is because otherwise there's a weird discrepancy between the unpacked image named and otherwise packed options.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't really see how this is a problem. It's quite common for a function to only use some fields or methods on a struct.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@dnephin: I don't think that is a safe practice: this is an inner helper function that only needs to know about one repo. Including the extra images in the slice is extraneous info, and I worry that a future contribution may misuse it.
That said, if you feel strongly about changing to the signerRemoveOptions, you are the maintainer and I will make the change - just let me know.
cli/command/trust/signer_add.go
Outdated
|
|
||
| var validSignerName = regexp.MustCompile(`^[a-z0-9]+[a-z0-9\_\-]*$`).MatchString | ||
|
|
||
| func addSigner(cli command.Cli, options *signerAddOptions) error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should accept the struct, not pointer to struct
vendor.conf
Outdated
| github.com/bugsnag/bugsnag-go 13fd6b8acda029830ef9904df6b63be0a83369d0 | ||
| github.com/bugsnag/osext 0dd3f918b21bec95ace9dc86c7e70266cfc5c702 | ||
| github.com/bugsnag/panicwrap e2c28503fcd0675329da73bf48b33404db873782 | ||
| github.com/BurntSushi/toml a368813c5e648fee92e5f6c30e3944ff9d5e8895 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is bringing in a whole lot of unnecessary dependencies.
I believe the problem is github.com/docker/notary/util. I think this illustrates one of the major problems with a utils package.
from https://blog.golang.org/package-names
Avoid meaningless package names. Packages named util ... provide clients with no sense of what the package contains. This makes it harder for clients to use the package and makes it harder for maintainers to keep the package focused. Over time, they accumulate dependencies that can make compilation significantly and unnecessarily slower, especially in large programs.
A generic package like utils tends to collect a bunch of unrelated functions/types that have completely different dependencies which means that using any of the functions results in the consumer having to depend on a bunch of unrelated things (sql libraryes, logging libraries, etc).
I think this needs to be fixed in notary and anything used in docker/cli needs to be moved out of utils so we can use it without bringing in a dozen unnecessary packages.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm looking into it - it's possible that this may not be so clean because the notary server-side services also use a key storage interface with connects with the DB (hence many of the imports). I'll get back to you with an update.
|
thanks @dnephin for the review! I'm looking into package refactors on |
|
@dnephin: great news! I have a fix in flight for upstream notary that will remove all vendoring except for an updated notary commit hash. We would love to move this forward before the next release - please let me know if there are other review comments I can address :) |
Signed-off-by: Riyaz Faizullabhoy <riyaz.faizullabhoy@docker.com>
Signed-off-by: Riyaz Faizullabhoy <riyaz.faizullabhoy@docker.com>
559ffc0 to
9e25404
Compare
|
updated: the only vendoring is now limited to an updated |
dnephin
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! vendor looks good now. Left some comments about error handling and output streams.
cli/command/trust/key_generate.go
Outdated
| pubPEM, err := generateKeyAndOutputPubPEM(keyName, privKeyFileStore) | ||
| if err != nil { | ||
| fmt.Fprintf(streams.Out(), err.Error()) | ||
| return fmt.Errorf("Error generating key for: %s", keyName) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think it's correct to print an error on stdout. This should return an error without the fmt.Fprintf()
return errors.Wrapf(err, "failed to generate key for %s", keyName)
cli/command/trust/key_generate.go
Outdated
| pubFileName := strings.Join([]string{keyName, "pub"}, ".") | ||
| pubFilePath := filepath.Join(workingDir, pubFileName) | ||
| if err := ioutil.WriteFile(pubFilePath, pem.EncodeToMemory(&pubPEM), notary.PrivNoExecPerms); err != nil { | ||
| return "", fmt.Errorf("Error writing public key to location: %s", pubFilePath) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe wrap the original error so it's easier to debug? Also errors are supposed to always start with lowercase so that they can be wrapped by other code.
return "', errors.Wrapf(err, "failed to write public key to %s", pubFilePath)
cli/command/trust/key_load.go
Outdated
| passRet := trust.GetPassphraseRetriever(streams.In(), streams.Out()) | ||
| keyBytes, err := getPrivKeyBytesFromPath(keyPath) | ||
| if err != nil { | ||
| return fmt.Errorf("error reading key from %s: %s", keyPath, err) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return errors.Wrapf(err, "error reading key from %s", keyPath)
cli/command/trust/key_load.go
Outdated
| return fmt.Errorf("error reading key from %s: %s", keyPath, err) | ||
| } | ||
| if err := loadPrivKeyBytesToStore(keyBytes, privKeyImporters, keyPath, options.keyName, passRet); err != nil { | ||
| return fmt.Errorf("error importing key from %s: %s", keyPath, err) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
errors.Wrapf()
cli/command/trust/key_load.go
Outdated
| return nil, err | ||
| } | ||
| if fileInfo.Mode() != ownerReadOnlyPerms && fileInfo.Mode() != ownerReadAndWritePerms { | ||
| return nil, fmt.Errorf("private key permission from %s should be set to 400 or 600", keyPath) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about 700, or 200? Maybe this could say "private key must not be readable by others" or something like that?
I think the ssh client says something like this: "It is required that your private key files are NOT accessible by others."
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think 200 or 700 make sense here, for 200 you'd have writable but not readable (I've never seen this done?), and with 700 the key would be executable (also don't see a use for this?).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree those would be silly permissions. My point is that the error message is misleading. The requirement is that it can't be readable by others, not that it must be one of those two permissions. The error message should match the requirement. The ssh client is a good example of this.
If I'm not mistaken this error message will also be used on windows. "set to 400 or 600" is meaningless to windows users.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, I just noticed the code does actually check for specifically those permissions. I think this needs to be changed to just check that the specific bits are not set.
Something like this?
mode & 077 == 0
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sounds good, updated!
cli/command/trust/signer_add.go
Outdated
| var errImages []string | ||
| for _, imageName := range options.images { | ||
| if err := addSignerToImage(cli, signerName, imageName, options.keys.GetAll()); err != nil { | ||
| fmt.Fprintln(cli.Out(), err.Error()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should go to cli.Err() instead of stdout
cli/command/trust/signer_add.go
Outdated
| if os.IsNotExist(err) { | ||
| return nil, fmt.Errorf("file for public key does not exist: %s", pubKeyPath) | ||
| } | ||
| return nil, fmt.Errorf("unable to read public key from file: %s", pubKeyPath) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe errors.Wrapf() to make it easier to debug with the original error.
cli/command/trust/signer_remove.go
Outdated
| var errImages []string | ||
| for _, image := range options.images { | ||
| if err := removeSingleSigner(cli, image, options.signer, options.forceYes); err != nil { | ||
| fmt.Fprintln(cli.Out(), err.Error()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/cli.Out()/cli.Err()/
cli/command/trust/signer_remove.go
Outdated
| } | ||
| delegationRoles, err := notaryRepo.GetDelegationRoles() | ||
| if err != nil { | ||
| return fmt.Errorf("Error retrieving signers for %s", imageName) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe errors.Wrapf()?
cli/command/trust/signer_remove.go
Outdated
| return nil | ||
| } | ||
| } else if err != nil { | ||
| fmt.Fprintln(cli.Out(), err.Error()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't this return the error here to exit early?
If not I guess just s/cli.Out/cli.Err/
|
I also see there's still quite a few places that print "informational" information on |
|
@thaJeztah: thank you for the thorough review! I think I've addressed all comments. As for the bug you found: I am not able to repro so maybe it is an odd tty issue in the container? |
07a62d8 to
3b45ad3
Compare
dnephin
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
| for _, imageName := range options.images { | ||
| fmt.Fprintf(cli.Out(), "Adding signer \"%s\" to %s...\n", signerName, imageName) | ||
| if err := addSignerToImage(cli, signerName, imageName, signerPubKeys); err != nil { | ||
| fmt.Fprintln(cli.Err(), err.Error()+"\n") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fprintln() already adds a newline, but there's also a \n at the end of the message. Are you sure we want an extra blank line between these?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added an extra blank line to separate the signer output if there are multiple ex:
$ docker trust signer add alice example/trust-demo example/trust-demo2 --key alice.crt
Adding signer "alice" to example/trust-demo...
Enter passphrase for repository key with ID 95b9e55:
Successfully added signer: alice to example/trust-demo
Adding signer "alice" to example/trust-demo2...
Enter passphrase for repository key with ID ece554f:
Successfully added signer: alice to example/trust-demo2
Let me know if you'd prefer for the blank line to be removed, but I think it helps improve readability
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok
| for _, image := range options.images { | ||
| fmt.Fprintf(cli.Out(), "Removing signer \"%s\" from %s...\n", options.signer, image) | ||
| if err := removeSingleSigner(cli, image, options.signer, options.forceYes); err != nil { | ||
| fmt.Fprintln(cli.Err(), err.Error()+"\n") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same here
cli/command/trust/signer_remove.go
Outdated
| fmt.Fprintln(cli.Err(), err.Error()+"\n") | ||
| errImages = append(errImages, image) | ||
| } else { | ||
| fmt.Fprintf(cli.Out(), "Successfully removed %s from %s\n\n", options.signer, image) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same here, seems to be an extra blank line
thaJeztah
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
left some comments
cli/command/trust/helpers.go
Outdated
| if err != nil { | ||
| return err | ||
| } | ||
| // Initialize the notary repository with a remotely managed snapshot |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks; then it can be removed here 😉
| # trust key generate | ||
|
|
||
| ```markdown | ||
| Usage: docker trust key generate NAME |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should match the actual output;
Usage: docker trust key generate NAME
Generate and load a signing key-pair
Options:
--dir string Directory to generate key in, defaults to current directory
--help Print usage
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
updated!
cli/command/trust/key_load.go
Outdated
| ) | ||
|
|
||
| const ( | ||
| nonOwnerReadWritePerms = 0077 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be named nonOwnerReadWriteMask ? (e.g.)?
cli/command/trust/key_load.go
Outdated
| }, | ||
| } | ||
| flags := cmd.Flags() | ||
| flags.StringVarP(&options.keyName, "name", "n", "signer", "Name for the loaded key") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, didn't look at this one in my previous review; let's remove the shorthand -n for now (we can add it back later if we want to) (we don't have a -n shorthand for --name so far in our UX)
| # trust key load | ||
|
|
||
| ```markdown | ||
| Usage: docker trust key load [OPTIONS] KEY |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here:
Usage: docker trust key load [OPTIONS] KEY
Load a private key file for signing
Options:
--help Print usage
-n, --name string Name for the loaded key (default "signer")
Or (when removing the -n shorthand);
Usage: docker trust key load [OPTIONS] KEY
Load a private key file for signing
Options:
--help Print usage
--name string Name for the loaded key (default "signer")
| # trust signer remove | ||
|
|
||
| ```markdown | ||
| Usage: docker trust signer remove [OPTIONS] NAME IMAGE [IMAGE...] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Usage: docker trust signer remove [OPTIONS] NAME IMAGE [IMAGE...]
Remove a signer
Options:
--help Print usage
-y, --yes Do not prompt for confirmation before removing the most recent signer
| To remove an existing signer, `alice`, from this repository: | ||
|
|
||
| ```bash | ||
| $ docker trust inspect example/trust-demo |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/inspect/view/
| To remove an existing signer, `alice`, from multiple repositories: | ||
|
|
||
| ```bash | ||
| $ docker trust inspect example/trust-demo |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/inspect/view/
cli/command/trust/signer_remove.go
Outdated
|
|
||
| func removeSigner(cli command.Cli, options signerRemoveOptions) error { | ||
| var errImages []string | ||
| for _, image := range options.images { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like we don't require a :tag for these images as well
| To add a new signer, `alice`, to this repository: | ||
|
|
||
| ```bash | ||
| $ docker trust inspect example/trust-demo |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/inspect/view/
(some other places as well)
cli/command/trust/signer_remove.go
Outdated
| }, | ||
| } | ||
| flags := cmd.Flags() | ||
| flags.BoolVarP(&options.forceYes, "yes", "y", false, "Do not prompt for confirmation before removing the most recent signer") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Noticed that for docker xx prune, we're using --force for this;
Usage: docker image prune [OPTIONS]
Remove unused images
Options:
-a, --all Remove all unused images, not just dangling ones
--filter filter Provide filter values (e.g. 'until=<timestamp>')
-f, --force Do not prompt for confirmation
--help Print usage
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll update to force 👍
thaJeztah
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
changes LGTM, but can you squash the commits where applicable?
| return trustmanager.ImportKeys(bytes.NewReader(privKeyBytes), privKeyImporters, keyName, "", passRet) | ||
| } | ||
|
|
||
| func decodePrivKeyIfNecessary(privPemBytes []byte, passRet notary.PassRetriever) ([]byte, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would be good to have a unit-test for this one, but I'm okay adding that in a follow-up
Signed-off-by: Riyaz Faizullabhoy <riyaz.faizullabhoy@docker.com>
Signed-off-by: Riyaz Faizullabhoy <riyaz.faizullabhoy@docker.com>
Signed-off-by: Riyaz Faizullabhoy <riyaz.faizullabhoy@docker.com>
Signed-off-by: Riyaz Faizullabhoy <riyaz.faizullabhoy@docker.com>
4f805ef to
4ec0cc9
Compare
Signed-off-by: Riyaz Faizullabhoy <riyaz.faizullabhoy@docker.com>
Signed-off-by: Riyaz Faizullabhoy <riyaz.faizullabhoy@docker.com>
Signed-off-by: Riyaz Faizullabhoy <riyaz.faizullabhoy@docker.com>
Signed-off-by: Riyaz Faizullabhoy <riyaz.faizullabhoy@docker.com>
4ec0cc9 to
e189a21
Compare
|
thanks @thaJeztah: I've cut down to ~half the commits! |
|
Thanks! Discussed with @riyazdf and further squashing proved to be difficult, so I'm good with the current number of commits 👍 |
This PR introduces four more
docker trustsubcommands to interact with signers and keys:docker trust signer add: add a signer to one or more reposdocker trust signer remove: remove a signer from one or more reposdocker trust key load: load a private key into the local storage to use for signingdocker trust key generate: generate a signing key-pair. The private key is automatically loaded into the local storage, and the public key can be used forsigner addcc @ashfall and @eiais who also implemented these features
This PR includes code and documentation and extends the functionality in #472. As such, it can be included in a followup release.
Original design doc here