mirror of
https://github.com/containers/podman.git
synced 2025-09-25 15:55:32 +08:00
Merge pull request #13247 from rhatdan/trust
Cleanup display of trust with transports
This commit is contained in:
@ -12,6 +12,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
noHeading bool
|
||||||
showTrustDescription = "Display trust policy for the system"
|
showTrustDescription = "Display trust policy for the system"
|
||||||
showTrustCommand = &cobra.Command{
|
showTrustCommand = &cobra.Command{
|
||||||
Annotations: map[string]string{registry.EngineMode: registry.ABIMode},
|
Annotations: map[string]string{registry.EngineMode: registry.ABIMode},
|
||||||
@ -40,6 +41,7 @@ func init() {
|
|||||||
showFlags.BoolVar(&showTrustOptions.Raw, "raw", false, "Output raw policy file")
|
showFlags.BoolVar(&showTrustOptions.Raw, "raw", false, "Output raw policy file")
|
||||||
_ = showFlags.MarkHidden("policypath")
|
_ = showFlags.MarkHidden("policypath")
|
||||||
showFlags.StringVar(&showTrustOptions.RegistryPath, "registrypath", "", "")
|
showFlags.StringVar(&showTrustOptions.RegistryPath, "registrypath", "", "")
|
||||||
|
showFlags.BoolVarP(&noHeading, "noheading", "n", false, "Do not print column headings")
|
||||||
_ = showFlags.MarkHidden("registrypath")
|
_ = showFlags.MarkHidden("registrypath")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,10 +66,22 @@ func showTrust(cmd *cobra.Command, args []string) error {
|
|||||||
rpt := report.New(os.Stdout, cmd.Name())
|
rpt := report.New(os.Stdout, cmd.Name())
|
||||||
defer rpt.Flush()
|
defer rpt.Flush()
|
||||||
|
|
||||||
|
hdrs := report.Headers(imageReporter{}, map[string]string{
|
||||||
|
"Transport": "Transport",
|
||||||
|
"RepoName": "Name",
|
||||||
|
"Type": "Type",
|
||||||
|
"GPGId": "Id",
|
||||||
|
"SignatureStore": "Store",
|
||||||
|
})
|
||||||
rpt, err = rpt.Parse(report.OriginPodman,
|
rpt, err = rpt.Parse(report.OriginPodman,
|
||||||
"{{range . }}{{.RepoName}}\t{{.Type}}\t{{.GPGId}}\t{{.SignatureStore}}\n{{end -}}")
|
"{{range . }}{{.Transport}}\t{{.RepoName}}\t{{.Type}}\t{{.GPGId}}\t{{.SignatureStore}}\n{{end -}}")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if !noHeading {
|
||||||
|
if err := rpt.Execute(hdrs); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
return rpt.Execute(trust.Policies)
|
return rpt.Execute(trust.Policies)
|
||||||
}
|
}
|
||||||
|
@ -40,6 +40,8 @@ Trust may be updated using the command **podman image trust set** for an existin
|
|||||||
#### **--help**, **-h**
|
#### **--help**, **-h**
|
||||||
Print usage statement.
|
Print usage statement.
|
||||||
|
|
||||||
|
### set OPTIONS
|
||||||
|
|
||||||
#### **--pubkeysfile**=*KEY1*, **-f**
|
#### **--pubkeysfile**=*KEY1*, **-f**
|
||||||
A path to an exported public key on the local system. Key paths
|
A path to an exported public key on the local system. Key paths
|
||||||
will be referenced in policy.json. Any path to a file may be used but locating the file in **/etc/pki/containers** is recommended. Options may be used multiple times to
|
will be referenced in policy.json. Any path to a file may be used but locating the file in **/etc/pki/containers** is recommended. Options may be used multiple times to
|
||||||
@ -54,14 +56,17 @@ Trust may be updated using the command **podman image trust set** for an existin
|
|||||||
registry scope
|
registry scope
|
||||||
**reject**: do not accept images for this registry scope
|
**reject**: do not accept images for this registry scope
|
||||||
|
|
||||||
## show OPTIONS
|
### show OPTIONS
|
||||||
|
|
||||||
#### **--raw**
|
|
||||||
Output trust policy file as raw JSON
|
|
||||||
|
|
||||||
#### **--json**, **-j**
|
#### **--json**, **-j**
|
||||||
Output trust as JSON for machine parsing
|
Output trust as JSON for machine parsing
|
||||||
|
|
||||||
|
#### **--noheading**, **-n**
|
||||||
|
Omit the table headings from the trust listings
|
||||||
|
|
||||||
|
#### **--raw**
|
||||||
|
Output trust policy file as raw JSON
|
||||||
|
|
||||||
## EXAMPLES
|
## EXAMPLES
|
||||||
|
|
||||||
Accept all unsigned images from a registry
|
Accept all unsigned images from a registry
|
||||||
@ -74,15 +79,110 @@ Modify default trust policy
|
|||||||
|
|
||||||
Display system trust policy
|
Display system trust policy
|
||||||
|
|
||||||
sudo podman image trust show
|
podman image trust show
|
||||||
|
```
|
||||||
|
TRANSPORT NAME TYPE ID STORE
|
||||||
|
all default reject
|
||||||
|
repository docker.io/library accept
|
||||||
|
repository registry.access.redhat.com signed security@redhat.com https://access.redhat.com/webassets/docker/content/sigstore
|
||||||
|
repository registry.redhat.io signed security@redhat.com https://registry.redhat.io/containers/sigstore
|
||||||
|
repository docker.io reject
|
||||||
|
docker-daemon accept
|
||||||
|
```
|
||||||
|
|
||||||
Display trust policy file
|
Display trust policy file
|
||||||
|
|
||||||
sudo podman image trust show --raw
|
podman image trust show --raw
|
||||||
|
```
|
||||||
|
{
|
||||||
|
"default": [
|
||||||
|
{
|
||||||
|
"type": "reject"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"transports": {
|
||||||
|
"docker": {
|
||||||
|
"docker.io": [
|
||||||
|
{
|
||||||
|
"type": "reject"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"docker.io/library": [
|
||||||
|
{
|
||||||
|
"type": "insecureAcceptAnything"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"registry.access.redhat.com": [
|
||||||
|
{
|
||||||
|
"type": "signedBy",
|
||||||
|
"keyType": "GPGKeys",
|
||||||
|
"keyPath": "/etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"registry.redhat.io": [
|
||||||
|
{
|
||||||
|
"type": "signedBy",
|
||||||
|
"keyType": "GPGKeys",
|
||||||
|
"keyPath": "/etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"docker-daemon": {
|
||||||
|
"": [
|
||||||
|
{
|
||||||
|
"type": "insecureAcceptAnything"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
Display trust as JSON
|
Display trust as JSON
|
||||||
|
|
||||||
sudo podman image trust show --json
|
podman image trust show --json
|
||||||
|
```
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"transport": "all",
|
||||||
|
"name": "* (default)",
|
||||||
|
"repo_name": "default",
|
||||||
|
"type": "reject"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"transport": "repository",
|
||||||
|
"name": "docker.io",
|
||||||
|
"repo_name": "docker.io",
|
||||||
|
"type": "reject"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"transport": "repository",
|
||||||
|
"name": "docker.io/library",
|
||||||
|
"repo_name": "docker.io/library",
|
||||||
|
"type": "accept"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"transport": "repository",
|
||||||
|
"name": "registry.access.redhat.com",
|
||||||
|
"repo_name": "registry.access.redhat.com",
|
||||||
|
"sigstore": "https://access.redhat.com/webassets/docker/content/sigstore",
|
||||||
|
"type": "signed",
|
||||||
|
"gpg_id": "security@redhat.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"transport": "repository",
|
||||||
|
"name": "registry.redhat.io",
|
||||||
|
"repo_name": "registry.redhat.io",
|
||||||
|
"sigstore": "https://registry.redhat.io/containers/sigstore",
|
||||||
|
"type": "signed",
|
||||||
|
"gpg_id": "security@redhat.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"transport": "docker-daemon",
|
||||||
|
"type": "accept"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
## SEE ALSO
|
## SEE ALSO
|
||||||
**[containers-policy.json(5)](https://github.com/containers/image/blob/main/docs/containers-policy.json.5.md)**
|
**[containers-policy.json(5)](https://github.com/containers/image/blob/main/docs/containers-policy.json.5.md)**
|
||||||
|
@ -122,18 +122,24 @@ func getPolicyShowOutput(policyContentStruct trust.PolicyContent, systemRegistri
|
|||||||
|
|
||||||
if len(policyContentStruct.Default) > 0 {
|
if len(policyContentStruct.Default) > 0 {
|
||||||
defaultPolicyStruct := trust.Policy{
|
defaultPolicyStruct := trust.Policy{
|
||||||
Name: "* (default)",
|
Transport: "all",
|
||||||
RepoName: "default",
|
Name: "* (default)",
|
||||||
Type: trustTypeDescription(policyContentStruct.Default[0].Type),
|
RepoName: "default",
|
||||||
|
Type: trustTypeDescription(policyContentStruct.Default[0].Type),
|
||||||
}
|
}
|
||||||
output = append(output, &defaultPolicyStruct)
|
output = append(output, &defaultPolicyStruct)
|
||||||
}
|
}
|
||||||
for _, transval := range policyContentStruct.Transports {
|
for transport, transval := range policyContentStruct.Transports {
|
||||||
|
if transport == "docker" {
|
||||||
|
transport = "repository"
|
||||||
|
}
|
||||||
|
|
||||||
for repo, repoval := range transval {
|
for repo, repoval := range transval {
|
||||||
tempTrustShowOutput := trust.Policy{
|
tempTrustShowOutput := trust.Policy{
|
||||||
Name: repo,
|
Name: repo,
|
||||||
RepoName: repo,
|
RepoName: repo,
|
||||||
Type: repoval[0].Type,
|
Transport: transport,
|
||||||
|
Type: trustTypeDescription(repoval[0].Type),
|
||||||
}
|
}
|
||||||
// TODO - keyarr is not used and I don't know its intent; commenting out for now for someone to fix later
|
// TODO - keyarr is not used and I don't know its intent; commenting out for now for someone to fix later
|
||||||
//keyarr := []string{}
|
//keyarr := []string{}
|
||||||
|
@ -2,11 +2,11 @@ package trust
|
|||||||
|
|
||||||
// Policy describes a basic trust policy configuration
|
// Policy describes a basic trust policy configuration
|
||||||
type Policy struct {
|
type Policy struct {
|
||||||
Name string `json:"name"`
|
Transport string `json:"transport"`
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
RepoName string `json:"repo_name,omitempty"`
|
RepoName string `json:"repo_name,omitempty"`
|
||||||
Keys []string `json:"keys,omitempty"`
|
Keys []string `json:"keys,omitempty"`
|
||||||
SignatureStore string `json:"sigstore"`
|
SignatureStore string `json:"sigstore,omitempty"`
|
||||||
Transport string `json:"transport"`
|
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
GPGId string `json:"gpg_id,omitempty"`
|
GPGId string `json:"gpg_id,omitempty"`
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,7 @@ import (
|
|||||||
// PolicyContent struct for policy.json file
|
// PolicyContent struct for policy.json file
|
||||||
type PolicyContent struct {
|
type PolicyContent struct {
|
||||||
Default []RepoContent `json:"default"`
|
Default []RepoContent `json:"default"`
|
||||||
Transports TransportsContent `json:"transports"`
|
Transports TransportsContent `json:"transports,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// RepoContent struct used under each repo
|
// RepoContent struct used under each repo
|
||||||
|
@ -39,7 +39,7 @@ var _ = Describe("Podman trust", func() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
It("podman image trust show", func() {
|
It("podman image trust show", func() {
|
||||||
session := podmanTest.Podman([]string{"image", "trust", "show", "--registrypath", filepath.Join(INTEGRATION_ROOT, "test"), "--policypath", filepath.Join(INTEGRATION_ROOT, "test/policy.json")})
|
session := podmanTest.Podman([]string{"image", "trust", "show", "-n", "--registrypath", filepath.Join(INTEGRATION_ROOT, "test"), "--policypath", filepath.Join(INTEGRATION_ROOT, "test/policy.json")})
|
||||||
session.WaitWithDefaultTimeout()
|
session.WaitWithDefaultTimeout()
|
||||||
Expect(session).Should(Exit(0))
|
Expect(session).Should(Exit(0))
|
||||||
outArray := session.OutputToStringArray()
|
outArray := session.OutputToStringArray()
|
||||||
@ -47,21 +47,18 @@ var _ = Describe("Podman trust", func() {
|
|||||||
|
|
||||||
// Repository order is not guaranteed. So, check that
|
// Repository order is not guaranteed. So, check that
|
||||||
// all expected lines appear in output; we also check total number of lines, so that handles all of them.
|
// all expected lines appear in output; we also check total number of lines, so that handles all of them.
|
||||||
Expect(string(session.Out.Contents())).To(MatchRegexp(`(?m)^default\s+accept\s*$`))
|
Expect(string(session.Out.Contents())).To(MatchRegexp(`(?m)^all\s+default\s+accept\s*$`))
|
||||||
Expect(string(session.Out.Contents())).To(MatchRegexp(`(?m)^docker.io/library/hello-world\s+reject\s*$`))
|
Expect(string(session.Out.Contents())).To(MatchRegexp(`(?m)^repository\s+docker.io/library/hello-world\s+reject\s*$`))
|
||||||
Expect(string(session.Out.Contents())).To(MatchRegexp(`(?m)^registry.access.redhat.com\s+signedBy\s+security@redhat.com, security@redhat.com\s+https://access.redhat.com/webassets/docker/content/sigstore\s*$`))
|
Expect(string(session.Out.Contents())).To(MatchRegexp(`(?m)^repository\s+registry.access.redhat.com\s+signed\s+security@redhat.com, security@redhat.com\s+https://access.redhat.com/webassets/docker/content/sigstore\s*$`))
|
||||||
})
|
})
|
||||||
|
|
||||||
It("podman image trust set", func() {
|
It("podman image trust set", func() {
|
||||||
path, err := os.Getwd()
|
policyJSON := filepath.Join(podmanTest.TempDir, "trust_set_test.json")
|
||||||
if err != nil {
|
session := podmanTest.Podman([]string{"image", "trust", "set", "--policypath", policyJSON, "-t", "accept", "default"})
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
session := podmanTest.Podman([]string{"image", "trust", "set", "--policypath", filepath.Join(filepath.Dir(path), "trust_set_test.json"), "-t", "accept", "default"})
|
|
||||||
session.WaitWithDefaultTimeout()
|
session.WaitWithDefaultTimeout()
|
||||||
Expect(session).Should(Exit(0))
|
Expect(session).Should(Exit(0))
|
||||||
var teststruct map[string][]map[string]string
|
var teststruct map[string][]map[string]string
|
||||||
policyContent, err := ioutil.ReadFile(filepath.Join(filepath.Dir(path), "trust_set_test.json"))
|
policyContent, err := ioutil.ReadFile(policyJSON)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
@ -88,25 +85,23 @@ var _ = Describe("Podman trust", func() {
|
|||||||
}
|
}
|
||||||
Expect(repoMap).To(Equal(map[string][]map[string]string{
|
Expect(repoMap).To(Equal(map[string][]map[string]string{
|
||||||
"* (default)": {{
|
"* (default)": {{
|
||||||
|
"type": "accept",
|
||||||
|
"transport": "all",
|
||||||
"name": "* (default)",
|
"name": "* (default)",
|
||||||
"repo_name": "default",
|
"repo_name": "default",
|
||||||
"sigstore": "",
|
|
||||||
"transport": "",
|
|
||||||
"type": "accept",
|
|
||||||
}},
|
}},
|
||||||
"docker.io/library/hello-world": {{
|
"docker.io/library/hello-world": {{
|
||||||
|
"transport": "repository",
|
||||||
"name": "docker.io/library/hello-world",
|
"name": "docker.io/library/hello-world",
|
||||||
"repo_name": "docker.io/library/hello-world",
|
"repo_name": "docker.io/library/hello-world",
|
||||||
"sigstore": "",
|
|
||||||
"transport": "",
|
|
||||||
"type": "reject",
|
"type": "reject",
|
||||||
}},
|
}},
|
||||||
"registry.access.redhat.com": {{
|
"registry.access.redhat.com": {{
|
||||||
|
"transport": "repository",
|
||||||
"name": "registry.access.redhat.com",
|
"name": "registry.access.redhat.com",
|
||||||
"repo_name": "registry.access.redhat.com",
|
"repo_name": "registry.access.redhat.com",
|
||||||
"sigstore": "https://access.redhat.com/webassets/docker/content/sigstore",
|
"sigstore": "https://access.redhat.com/webassets/docker/content/sigstore",
|
||||||
"transport": "",
|
"type": "signed",
|
||||||
"type": "signedBy",
|
|
||||||
"gpg_id": "security@redhat.com, security@redhat.com",
|
"gpg_id": "security@redhat.com, security@redhat.com",
|
||||||
}},
|
}},
|
||||||
}))
|
}))
|
||||||
|
46
test/system/750-trust.bats
Normal file
46
test/system/750-trust.bats
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
#!/usr/bin/env bats -*- bats -*-
|
||||||
|
#
|
||||||
|
# tests for podman image trust
|
||||||
|
#
|
||||||
|
|
||||||
|
load helpers
|
||||||
|
|
||||||
|
@test "podman image trust set" {
|
||||||
|
skip_if_remote "trust only works locally"
|
||||||
|
policypath=$PODMAN_TMPDIR/policy.json
|
||||||
|
run_podman 125 image trust set --policypath=$policypath --type=bogus default
|
||||||
|
is "$output" "Error: invalid choice: bogus.*" "error from --type=bogus"
|
||||||
|
|
||||||
|
run_podman image trust set --policypath=$policypath --type=accept default
|
||||||
|
run_podman image trust show --policypath=$policypath
|
||||||
|
is "$output" ".*all *default *accept" "default policy should be accept"
|
||||||
|
|
||||||
|
run_podman image trust set --policypath=$policypath --type=reject default
|
||||||
|
run_podman image trust show --policypath=$policypath
|
||||||
|
is "$output" ".*all *default *reject" "default policy should be reject"
|
||||||
|
|
||||||
|
run_podman image trust set --policypath=$policypath --type=reject docker.io
|
||||||
|
run_podman image trust show --policypath=$policypath
|
||||||
|
is "$output" ".*all *default *reject" "default policy should still be reject"
|
||||||
|
is "$output" ".*repository *docker.io *reject" "docker.io should also be reject"
|
||||||
|
|
||||||
|
run_podman image trust show --policypath=$policypath --json
|
||||||
|
subset=$(jq -r '.[0] | .repo_name, .type' <<<"$output" | fmt)
|
||||||
|
is "$subset" "default reject" "--json also shows default"
|
||||||
|
subset=$(jq -r '.[1] | .repo_name, .type' <<<"$output" | fmt)
|
||||||
|
is "$subset" "docker.io reject" "--json also shows docker.io"
|
||||||
|
|
||||||
|
run_podman image trust set --policypath=$policypath --type=accept docker.io
|
||||||
|
run_podman image trust show --policypath=$policypath --json
|
||||||
|
subset=$(jq -r '.[0] | .repo_name, .type' <<<"$output" | fmt)
|
||||||
|
is "$subset" "default reject" "--json, default is still reject"
|
||||||
|
subset=$(jq -r '.[1] | .repo_name, .type' <<<"$output" | fmt)
|
||||||
|
is "$subset" "docker.io accept" "--json, docker.io should now be accept"
|
||||||
|
|
||||||
|
run cat $policypath
|
||||||
|
policy=$output
|
||||||
|
run_podman image trust show --policypath=$policypath --raw
|
||||||
|
is "$output" "$policy" "output should show match content of policy.json"
|
||||||
|
}
|
||||||
|
|
||||||
|
# vim: filetype=sh
|
@ -1,8 +0,0 @@
|
|||||||
{
|
|
||||||
"default": [
|
|
||||||
{
|
|
||||||
"type": "insecureAcceptAnything"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"transports": null
|
|
||||||
}
|
|
Reference in New Issue
Block a user