support multiple arguments to trust inspect

Signed-off-by: Riyaz Faizullabhoy <riyaz.faizullabhoy@docker.com>
This commit is contained in:
Riyaz Faizullabhoy 2017-11-16 10:09:57 -08:00
parent cd38d39d0d
commit 1eb87cc096
10 changed files with 165 additions and 198 deletions

View File

@ -192,7 +192,24 @@ func (e EmptyTargetsNotaryRepository) GetAllTargetMetadataByName(name string) ([
} }
func (e EmptyTargetsNotaryRepository) ListRoles() ([]client.RoleWithSignatures, error) { func (e EmptyTargetsNotaryRepository) ListRoles() ([]client.RoleWithSignatures, error) {
return []client.RoleWithSignatures{}, nil rootRole := data.Role{
RootRole: data.RootRole{
KeyIDs: []string{"rootID"},
Threshold: 1,
},
Name: data.CanonicalRootRole,
}
targetsRole := data.Role{
RootRole: data.RootRole{
KeyIDs: []string{"targetsID"},
Threshold: 1,
},
Name: data.CanonicalTargetsRole,
}
return []client.RoleWithSignatures{
{Role: rootRole},
{Role: targetsRole}}, nil
} }
func (e EmptyTargetsNotaryRepository) GetDelegationRoles() ([]data.Role, error) { func (e EmptyTargetsNotaryRepository) GetDelegationRoles() ([]data.Role, error) {

View File

@ -14,21 +14,41 @@ import (
func newInspectCommand(dockerCli command.Cli) *cobra.Command { func newInspectCommand(dockerCli command.Cli) *cobra.Command {
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "inspect IMAGE[:TAG]", Use: "inspect IMAGE[:TAG] [IMAGE[:TAG]...]",
Short: "Return low-level information about keys and signatures", Short: "Return low-level information about keys and signatures",
Args: cli.ExactArgs(1), Args: cli.RequiresMinArgs(1),
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
return inspectTrustInfo(dockerCli, args[0]) return inspectTrustInfo(dockerCli, args)
}, },
} }
return cmd return cmd
} }
func inspectTrustInfo(cli command.Cli, remote string) error { func inspectTrustInfo(cli command.Cli, remotes []string) error {
signatureRows, adminRolesWithSigs, delegationRoles, err := lookupTrustInfo(cli, remote) trustRepoInfoList := []trustRepo{}
for _, remote := range remotes {
trustInfo, err := getRepoTrustInfo(cli, remote)
if err != nil { if err != nil {
return err return err
} }
if trustInfo == nil {
continue
}
trustRepoInfoList = append(trustRepoInfoList, *trustInfo)
}
trustInspectJSON, err := json.Marshal(trustRepoInfoList)
if err != nil {
return errors.Wrap(err, "error while serializing trusted repository info")
}
fmt.Fprintf(cli.Out(), string(trustInspectJSON))
return nil
}
func getRepoTrustInfo(cli command.Cli, remote string) (*trustRepo, error) {
signatureRows, adminRolesWithSigs, delegationRoles, err := lookupTrustInfo(cli, remote)
if err != nil {
return nil, err
}
// process the signatures to include repo admin if signed by the base targets role // process the signatures to include repo admin if signed by the base targets role
for idx, sig := range signatureRows { for idx, sig := range signatureRows {
if len(sig.Signers) == 0 { if len(sig.Signers) == 0 {
@ -55,17 +75,11 @@ func inspectTrustInfo(cli command.Cli, remote string) error {
} }
sort.Slice(adminList, func(i, j int) bool { return adminList[i].Name > adminList[j].Name }) sort.Slice(adminList, func(i, j int) bool { return adminList[i].Name > adminList[j].Name })
trustRepoInfo := &trustRepo{ return &trustRepo{
SignedTags: signatureRows, SignedTags: signatureRows,
Signers: signerList, Signers: signerList,
AdminstrativeKeys: adminList, AdminstrativeKeys: adminList,
} }, nil
trustInspectJSON, err := json.Marshal(trustRepoInfo)
if err != nil {
return errors.Wrap(err, "error while serializing trusted repository info")
}
fmt.Fprintf(cli.Out(), string(trustInspectJSON))
return nil
} }
// trustRepo represents consumable information about a trusted repository // trustRepo represents consumable information about a trusted repository

View File

@ -114,6 +114,15 @@ func TestTrustInspectCommandFullRepoWithSigners(t *testing.T) {
golden.Assert(t, cli.OutBuffer().String(), "trust-inspect-full-repo-with-signers.golden") golden.Assert(t, cli.OutBuffer().String(), "trust-inspect-full-repo-with-signers.golden")
} }
func TestTrustInspectCommandMultipleFullReposWithSigners(t *testing.T) {
cli := test.NewFakeCli(&fakeClient{})
cli.SetNotaryClient(getLoadedNotaryRepository)
cmd := newInspectCommand(cli)
cmd.SetArgs([]string{"signed-repo", "signed-repo"})
assert.NoError(t, cmd.Execute())
golden.Assert(t, cli.OutBuffer().String(), "trust-inspect-multiple-repos-with-signers.golden")
}
func TestTrustInspectCommandUnsignedTagInSignedRepo(t *testing.T) { func TestTrustInspectCommandUnsignedTagInSignedRepo(t *testing.T) {
cli := test.NewFakeCli(&fakeClient{}) cli := test.NewFakeCli(&fakeClient{})
cli.SetNotaryClient(getLoadedNotaryRepository) cli.SetNotaryClient(getLoadedNotaryRepository)

View File

@ -1 +1 @@
{} [{"AdminstrativeKeys":[{"Name":"Root","Keys":["rootID"]},{"Name":"Repository","Keys":["targetsID"]}]}]

View File

@ -1 +1 @@
{"SignedTags":[{"SignedTag":"green","Digest":"677265656e2d646967657374","Signers":["Repo Admin"]}],"AdminstrativeKeys":[{"Name":"Root","Keys":["rootID"]},{"Name":"Repository","Keys":["targetsID"]}]} [{"SignedTags":[{"SignedTag":"green","Digest":"677265656e2d646967657374","Signers":["Repo Admin"]}],"AdminstrativeKeys":[{"Name":"Root","Keys":["rootID"]},{"Name":"Repository","Keys":["targetsID"]}]}]

View File

@ -1 +1 @@
{"SignedTags":[{"SignedTag":"blue","Digest":"626c75652d646967657374","Signers":["alice"]},{"SignedTag":"green","Digest":"677265656e2d646967657374","Signers":["Repo Admin"]},{"SignedTag":"red","Digest":"7265642d646967657374","Signers":["alice","bob"]}],"Signers":[{"Name":"bob","Keys":["B"]},{"Name":"alice","Keys":["A"]}],"AdminstrativeKeys":[{"Name":"Root","Keys":["rootID"]},{"Name":"Repository","Keys":["targetsID"]}]} [{"SignedTags":[{"SignedTag":"blue","Digest":"626c75652d646967657374","Signers":["alice"]},{"SignedTag":"green","Digest":"677265656e2d646967657374","Signers":["Repo Admin"]},{"SignedTag":"red","Digest":"7265642d646967657374","Signers":["alice","bob"]}],"Signers":[{"Name":"bob","Keys":["B"]},{"Name":"alice","Keys":["A"]}],"AdminstrativeKeys":[{"Name":"Root","Keys":["rootID"]},{"Name":"Repository","Keys":["targetsID"]}]}]

View File

@ -0,0 +1 @@
[{"SignedTags":[{"SignedTag":"blue","Digest":"626c75652d646967657374","Signers":["alice"]},{"SignedTag":"green","Digest":"677265656e2d646967657374","Signers":["Repo Admin"]},{"SignedTag":"red","Digest":"7265642d646967657374","Signers":["alice","bob"]}],"Signers":[{"Name":"bob","Keys":["B"]},{"Name":"alice","Keys":["A"]}],"AdminstrativeKeys":[{"Name":"Root","Keys":["rootID"]},{"Name":"Repository","Keys":["targetsID"]}]},{"SignedTags":[{"SignedTag":"blue","Digest":"626c75652d646967657374","Signers":["alice"]},{"SignedTag":"green","Digest":"677265656e2d646967657374","Signers":["Repo Admin"]},{"SignedTag":"red","Digest":"7265642d646967657374","Signers":["alice","bob"]}],"Signers":[{"Name":"bob","Keys":["B"]},{"Name":"alice","Keys":["A"]}],"AdminstrativeKeys":[{"Name":"Root","Keys":["rootID"]},{"Name":"Repository","Keys":["targetsID"]}]}]

View File

@ -1 +1 @@
{"SignedTags":[{"SignedTag":"green","Digest":"677265656e2d646967657374","Signers":["Repo Admin"]}],"AdminstrativeKeys":[{"Name":"Root","Keys":["rootID"]},{"Name":"Repository","Keys":["targetsID"]}]} [{"SignedTags":[{"SignedTag":"green","Digest":"677265656e2d646967657374","Signers":["Repo Admin"]}],"AdminstrativeKeys":[{"Name":"Root","Keys":["rootID"]},{"Name":"Repository","Keys":["targetsID"]}]}]

View File

@ -1 +1 @@
{"Signers":[{"Name":"bob","Keys":["B"]},{"Name":"alice","Keys":["A"]}],"AdminstrativeKeys":[{"Name":"Root","Keys":["rootID"]},{"Name":"Repository","Keys":["targetsID"]}]} [{"Signers":[{"Name":"bob","Keys":["B"]},{"Name":"alice","Keys":["A"]}],"AdminstrativeKeys":[{"Name":"Root","Keys":["rootID"]},{"Name":"Repository","Keys":["targetsID"]}]}]

View File

@ -16,7 +16,7 @@ keywords: "view, notary, trust"
# trust inspect # trust inspect
```markdown ```markdown
Usage: docker trust inspect IMAGE[:TAG] Usage: docker trust inspect IMAGE[:TAG] [IMAGE[:TAG]...]
Return low-level information about keys and signatures Return low-level information about keys and signatures
@ -40,7 +40,8 @@ new tags.
```bash ```bash
$ docker trust inspect alpine:latest | jq $ docker trust inspect alpine:latest | jq
{ [
{
"SignedTags": [ "SignedTags": [
{ {
"SignedTag": "latest", "SignedTag": "latest",
@ -64,7 +65,8 @@ $ docker trust inspect alpine:latest | jq
] ]
} }
] ]
} }
]
``` ```
The `SignedTags` key will list the `SignedTag` name, its `Digest`, and the `Signers` responsible for the signature. The `SignedTags` key will list the `SignedTag` name, its `Digest`, and the `Signers` responsible for the signature.
@ -78,7 +80,8 @@ If signers are set up for the repository via other `docker trust` commands, `doc
```bash ```bash
$ docker trust inspect my-image:purple | jq $ docker trust inspect my-image:purple | jq
{ [
{
"SignedTags": [ "SignedTags": [
{ {
"SignedTag": "purple", "SignedTag": "purple",
@ -126,7 +129,8 @@ $ docker trust inspect my-image:purple | jq
] ]
} }
] ]
} }
]
``` ```
If the image tag is unsigned or unavailable, `docker trust inspect` does not display any signed tags. If the image tag is unsigned or unavailable, `docker trust inspect` does not display any signed tags.
@ -140,7 +144,8 @@ However, if other tags are signed in the same image repository, `docker trust in
```bash ```bash
$ docker trust inspect alpine:unsigned | jq $ docker trust inspect alpine:unsigned | jq
{ [
{
"AdminstrativeKeys": [ "AdminstrativeKeys": [
{ {
"Name": "Repository", "Name": "Repository",
@ -155,99 +160,20 @@ $ docker trust inspect alpine:unsigned | jq
] ]
} }
] ]
} }
]
``` ```
### Get details about signatures for all image tags in a repository ### Get details about signatures for all image tags in a repository
```bash ```bash
$ docker trust inspect alpine | jq $ docker trust inspect alpine | jq
{
"SignedTags": [ ```
{
"SignedTag": "2.6",
"Digest": "9ace551613070689a12857d62c30ef0daa9a376107ec0fff0e34786cedb3399b", ### Get details about signatures for multiple images
"Signers": [
"Repo Admin" ```bash
] $ docker trust inspect alpine ubuntu | jq
},
{
"SignedTag": "2.7",
"Digest": "9f08005dff552038f0ad2f46b8e65ff3d25641747d3912e3ea8da6785046561a",
"Signers": [
"Repo Admin"
]
},
{
"SignedTag": "3.1",
"Digest": "2d74cbc2fbe3d261fdcca45d493ce1e3f3efd270114a62e383a8e45caeb48788",
"Signers": [
"Repo Admin"
]
},
{
"SignedTag": "3.2",
"Digest": "8565a58be8238ef688dbd90e43ec8e080114f1e1db846399116543eb8ef7d7b7",
"Signers": [
"Repo Admin"
]
},
{
"SignedTag": "3.3",
"Digest": "06fa785d55c35050241c60274e24ad57025683d5e939b3a31cc94193ca24740b",
"Signers": [
"Repo Admin"
]
},
{
"SignedTag": "3.4",
"Digest": "915b0ffca1d76ac57d83f28d568bcb516b6c274843ea8df7fac4b247440f796b",
"Signers": [
"Repo Admin"
]
},
{
"SignedTag": "3.5",
"Digest": "b007a354427e1880de9cdba533e8e57382b7f2853a68a478a17d447b302c219c",
"Signers": [
"Repo Admin"
]
},
{
"SignedTag": "3.6",
"Digest": "d6bfc3baf615dc9618209a8d607ba2a8103d9c8a405b3bd8741d88b4bef36478",
"Signers": [
"Repo Admin"
]
},
{
"SignedTag": "edge",
"Digest": "23e7d843e63a3eee29b6b8cfcd10e23dd1ef28f47251a985606a31040bf8e096",
"Signers": [
"Repo Admin"
]
},
{
"SignedTag": "latest",
"Digest": "d6bfc3baf615dc9618209a8d607ba2a8103d9c8a405b3bd8741d88b4bef36478",
"Signers": [
"Repo Admin"
]
}
],
"AdminstrativeKeys": [
{
"Name": "Repository",
"Keys": [
"5a46c9aaa82ff150bb7305a2d17d0c521c2d784246807b2dc611f436a69041fd"
]
},
{
"Name": "Root",
"Keys": [
"a2489bcac7a79aa67b19b96c4a3bf0c675ffdf00c6d2fabe1a5df1115e80adce"
]
}
]
}
``` ```