mirror of https://github.com/docker/cli.git
support multiple arguments to trust inspect
Signed-off-by: Riyaz Faizullabhoy <riyaz.faizullabhoy@docker.com>
This commit is contained in:
parent
cd38d39d0d
commit
1eb87cc096
|
@ -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) {
|
||||||
|
|
|
@ -14,20 +14,40 @@ 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 {
|
||||||
|
trustRepoInfoList := []trustRepo{}
|
||||||
|
for _, remote := range remotes {
|
||||||
|
trustInfo, err := getRepoTrustInfo(cli, remote)
|
||||||
|
if err != nil {
|
||||||
|
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)
|
signatureRows, adminRolesWithSigs, delegationRoles, err := lookupTrustInfo(cli, remote)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
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 {
|
||||||
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
{}
|
[{"AdminstrativeKeys":[{"Name":"Root","Keys":["rootID"]},{"Name":"Repository","Keys":["targetsID"]}]}]
|
|
@ -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"]}]}]
|
|
@ -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"]}]}]
|
|
@ -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"]}]}]
|
|
@ -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"]}]}]
|
|
@ -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"]}]}]
|
|
@ -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,31 +40,33 @@ new tags.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ docker trust inspect alpine:latest | jq
|
$ docker trust inspect alpine:latest | jq
|
||||||
{
|
[
|
||||||
"SignedTags": [
|
{
|
||||||
{
|
"SignedTags": [
|
||||||
"SignedTag": "latest",
|
{
|
||||||
"Digest": "d6bfc3baf615dc9618209a8d607ba2a8103d9c8a405b3bd8741d88b4bef36478",
|
"SignedTag": "latest",
|
||||||
"Signers": [
|
"Digest": "d6bfc3baf615dc9618209a8d607ba2a8103d9c8a405b3bd8741d88b4bef36478",
|
||||||
"Repo Admin"
|
"Signers": [
|
||||||
]
|
"Repo Admin"
|
||||||
}
|
]
|
||||||
],
|
}
|
||||||
"AdminstrativeKeys": [
|
],
|
||||||
{
|
"AdminstrativeKeys": [
|
||||||
"Name": "Repository",
|
{
|
||||||
"Keys": [
|
"Name": "Repository",
|
||||||
"5a46c9aaa82ff150bb7305a2d17d0c521c2d784246807b2dc611f436a69041fd"
|
"Keys": [
|
||||||
]
|
"5a46c9aaa82ff150bb7305a2d17d0c521c2d784246807b2dc611f436a69041fd"
|
||||||
},
|
]
|
||||||
{
|
},
|
||||||
"Name": "Root",
|
{
|
||||||
"Keys": [
|
"Name": "Root",
|
||||||
"a2489bcac7a79aa67b19b96c4a3bf0c675ffdf00c6d2fabe1a5df1115e80adce"
|
"Keys": [
|
||||||
]
|
"a2489bcac7a79aa67b19b96c4a3bf0c675ffdf00c6d2fabe1a5df1115e80adce"
|
||||||
}
|
]
|
||||||
]
|
}
|
||||||
}
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
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,55 +80,57 @@ 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",
|
{
|
||||||
"Digest": "941d3dba358621ce3c41ef67b47cf80f701ff80cdf46b5cc86587eaebfe45557",
|
"SignedTag": "purple",
|
||||||
"Signers": [
|
"Digest": "941d3dba358621ce3c41ef67b47cf80f701ff80cdf46b5cc86587eaebfe45557",
|
||||||
"alice",
|
"Signers": [
|
||||||
"bob",
|
"alice",
|
||||||
"carol"
|
"bob",
|
||||||
]
|
"carol"
|
||||||
}
|
]
|
||||||
],
|
}
|
||||||
"Signers": [
|
],
|
||||||
{
|
"Signers": [
|
||||||
"Name": "alice",
|
{
|
||||||
"Keys": [
|
"Name": "alice",
|
||||||
"04dd031411ed671ae1e12f47ddc8646d98f135090b01e54c3561e843084484a3",
|
"Keys": [
|
||||||
"6a11e4898a4014d400332ab0e096308c844584ff70943cdd1d6628d577f45fd8"
|
"04dd031411ed671ae1e12f47ddc8646d98f135090b01e54c3561e843084484a3",
|
||||||
]
|
"6a11e4898a4014d400332ab0e096308c844584ff70943cdd1d6628d577f45fd8"
|
||||||
},
|
]
|
||||||
{
|
},
|
||||||
"Name": "bob",
|
{
|
||||||
"Keys": [
|
"Name": "bob",
|
||||||
"433e245c656ae9733cdcc504bfa560f90950104442c4528c9616daa45824ccba"
|
"Keys": [
|
||||||
]
|
"433e245c656ae9733cdcc504bfa560f90950104442c4528c9616daa45824ccba"
|
||||||
},
|
]
|
||||||
{
|
},
|
||||||
"Name": "carol",
|
{
|
||||||
"Keys": [
|
"Name": "carol",
|
||||||
"d32fa8b5ca08273a2880f455fcb318da3dc80aeae1a30610815140deef8f30d9",
|
"Keys": [
|
||||||
"9a8bbec6ba2af88a5fad6047d428d17e6d05dbdd03d15b4fc8a9a0e8049cd606"
|
"d32fa8b5ca08273a2880f455fcb318da3dc80aeae1a30610815140deef8f30d9",
|
||||||
]
|
"9a8bbec6ba2af88a5fad6047d428d17e6d05dbdd03d15b4fc8a9a0e8049cd606"
|
||||||
}
|
]
|
||||||
],
|
}
|
||||||
"AdminstrativeKeys": [
|
],
|
||||||
{
|
"AdminstrativeKeys": [
|
||||||
"Name": "Repository",
|
{
|
||||||
"Keys": [
|
"Name": "Repository",
|
||||||
"27df2c8187e7543345c2e0bf3a1262e0bc63a72754e9a7395eac3f747ec23a44"
|
"Keys": [
|
||||||
]
|
"27df2c8187e7543345c2e0bf3a1262e0bc63a72754e9a7395eac3f747ec23a44"
|
||||||
},
|
]
|
||||||
{
|
},
|
||||||
"Name": "Root",
|
{
|
||||||
"Keys": [
|
"Name": "Root",
|
||||||
"40b66ccc8b176be8c7d365a17f3e046d1c3494e053dd57cfeacfe2e19c4f8e8f"
|
"Keys": [
|
||||||
]
|
"40b66ccc8b176be8c7d365a17f3e046d1c3494e053dd57cfeacfe2e19c4f8e8f"
|
||||||
}
|
]
|
||||||
]
|
}
|
||||||
}
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
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,114 +144,36 @@ 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",
|
{
|
||||||
"Keys": [
|
"Name": "Repository",
|
||||||
"5a46c9aaa82ff150bb7305a2d17d0c521c2d784246807b2dc611f436a69041fd"
|
"Keys": [
|
||||||
]
|
"5a46c9aaa82ff150bb7305a2d17d0c521c2d784246807b2dc611f436a69041fd"
|
||||||
},
|
]
|
||||||
{
|
},
|
||||||
"Name": "Root",
|
{
|
||||||
"Keys": [
|
"Name": "Root",
|
||||||
"a2489bcac7a79aa67b19b96c4a3bf0c675ffdf00c6d2fabe1a5df1115e80adce"
|
"Keys": [
|
||||||
]
|
"a2489bcac7a79aa67b19b96c4a3bf0c675ffdf00c6d2fabe1a5df1115e80adce"
|
||||||
}
|
]
|
||||||
]
|
}
|
||||||
}
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
### 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"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
Loading…
Reference in New Issue