Merge pull request #6108 from baude/v2trust

v2trust set and show
This commit is contained in:
OpenShift Merge Robot
2020-05-07 18:40:48 +02:00
committed by GitHub
9 changed files with 385 additions and 1 deletions

View File

@ -0,0 +1,27 @@
package images
import (
"github.com/containers/libpod/cmd/podman/registry"
"github.com/containers/libpod/cmd/podman/validate"
"github.com/containers/libpod/pkg/domain/entities"
"github.com/spf13/cobra"
)
var (
trustDescription = `Manages which registries you trust as a source of container images based on their location.
The location is determined by the transport and the registry host of the image. Using this container image docker://quay.io/podman/stable as an example, docker is the transport and quay.io is the registry host.`
trustCmd = &cobra.Command{
Use: "trust",
Short: "Manage container image trust policy",
Long: trustDescription,
RunE: validate.SubCommandExists,
}
)
func init() {
registry.Commands = append(registry.Commands, registry.CliCommand{
Mode: []entities.EngineMode{entities.ABIMode},
Command: trustCmd,
Parent: imageCmd,
})
}

View File

@ -0,0 +1,56 @@
package images
import (
"github.com/containers/libpod/cmd/podman/registry"
"github.com/containers/libpod/libpod/image"
"github.com/containers/libpod/pkg/domain/entities"
"github.com/containers/libpod/pkg/util"
"github.com/pkg/errors"
"github.com/spf13/cobra"
)
var (
setTrustDescription = "Set default trust policy or add a new trust policy for a registry"
setTrustCommand = &cobra.Command{
Use: "set [flags] REGISTRY",
Short: "Set default trust policy or a new trust policy for a registry",
Long: setTrustDescription,
Example: "",
RunE: setTrust,
Args: cobra.ExactArgs(1),
}
)
var (
setOptions entities.SetTrustOptions
)
func init() {
registry.Commands = append(registry.Commands, registry.CliCommand{
Mode: []entities.EngineMode{entities.ABIMode},
Command: setTrustCommand,
Parent: trustCmd,
})
setFlags := setTrustCommand.Flags()
setFlags.StringVar(&setOptions.PolicyPath, "policypath", "", "")
_ = setFlags.MarkHidden("policypath")
setFlags.StringSliceVarP(&setOptions.PubKeysFile, "pubkeysfile", "f", []string{}, `Path of installed public key(s) to trust for TARGET.
Absolute path to keys is added to policy.json. May
used multiple times to define multiple public keys.
File(s) must exist before using this command`)
setFlags.StringVarP(&setOptions.Type, "type", "t", "signedBy", "Trust type, accept values: signedBy(default), accept, reject")
}
func setTrust(cmd *cobra.Command, args []string) error {
validTrustTypes := []string{"accept", "insecureAcceptAnything", "reject", "signedBy"}
valid, err := image.IsValidImageURI(args[0])
if err != nil || !valid {
return errors.Wrapf(err, "invalid image uri %s", args[0])
}
if !util.StringInSlice(setOptions.Type, validTrustTypes) {
return errors.Errorf("invalid choice: %s (choose from 'accept', 'reject', 'signedBy')", setOptions.Type)
}
return registry.ImageEngine().SetTrust(registry.Context(), args, setOptions)
}

View File

@ -0,0 +1,77 @@
package images
import (
"fmt"
"os"
"text/tabwriter"
"text/template"
"github.com/containers/libpod/cmd/podman/registry"
"github.com/containers/libpod/pkg/domain/entities"
"github.com/spf13/cobra"
)
var (
showTrustDescription = "Display trust policy for the system"
showTrustCommand = &cobra.Command{
Use: "show [flags] [REGISTRY]",
Short: "Display trust policy for the system",
Long: showTrustDescription,
RunE: showTrust,
Example: "",
}
)
var (
showTrustOptions entities.ShowTrustOptions
)
func init() {
registry.Commands = append(registry.Commands, registry.CliCommand{
Mode: []entities.EngineMode{entities.ABIMode},
Command: showTrustCommand,
Parent: trustCmd,
})
showFlags := showTrustCommand.Flags()
showFlags.BoolVarP(&showTrustOptions.JSON, "json", "j", false, "Output as json")
showFlags.StringVar(&showTrustOptions.PolicyPath, "policypath", "", "")
showFlags.BoolVar(&showTrustOptions.Raw, "raw", false, "Output raw policy file")
_ = showFlags.MarkHidden("policypath")
showFlags.StringVar(&showTrustOptions.RegistryPath, "registrypath", "", "")
_ = showFlags.MarkHidden("registrypath")
}
func showTrust(cmd *cobra.Command, args []string) error {
report, err := registry.ImageEngine().ShowTrust(registry.Context(), args, showTrustOptions)
if err != nil {
return err
}
if showTrustOptions.Raw {
fmt.Println(report.Raw)
return nil
}
if showTrustOptions.JSON {
b, err := json.MarshalIndent(report.Policies, "", " ")
if err != nil {
return err
}
fmt.Println(string(b))
return nil
}
row := "{{.RepoName}}\t{{.Type}}\t{{.GPGId}}\t{{.SignatureStore}}\n"
format := "{{range . }}" + row + "{{end}}"
tmpl, err := template.New("listContainers").Parse(format)
if err != nil {
return err
}
w := tabwriter.NewWriter(os.Stdout, 8, 2, 2, ' ', 0)
if err := tmpl.Execute(w, report.Policies); err != nil {
return err
}
if err := w.Flush(); err != nil {
return err
}
return nil
}

View File

@ -22,6 +22,8 @@ type ImageEngine interface {
Remove(ctx context.Context, images []string, opts ImageRemoveOptions) (*ImageRemoveReport, []error)
Save(ctx context.Context, nameOrId string, tags []string, options ImageSaveOptions) error
Search(ctx context.Context, term string, opts ImageSearchOptions) ([]ImageSearchReport, error)
SetTrust(ctx context.Context, args []string, options SetTrustOptions) error
ShowTrust(ctx context.Context, args []string, options ShowTrustOptions) (*ShowTrustReport, error)
Shutdown(ctx context.Context)
Tag(ctx context.Context, nameOrId string, tags []string, options ImageTagOptions) error
Tree(ctx context.Context, nameOrId string, options ImageTreeOptions) (*ImageTreeReport, error)

View File

@ -7,6 +7,7 @@ import (
"github.com/containers/image/v5/manifest"
"github.com/containers/image/v5/types"
"github.com/containers/libpod/pkg/inspect"
"github.com/containers/libpod/pkg/trust"
docker "github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
"github.com/opencontainers/go-digest"
@ -285,3 +286,26 @@ type ImageTreeOptions struct {
type ImageTreeReport struct {
Tree string // TODO: Refactor move presentation work out of server
}
// ShowTrustOptions are the cli options for showing trust
type ShowTrustOptions struct {
JSON bool
PolicyPath string
Raw bool
RegistryPath string
}
// ShowTrustReport describes the results of show trust
type ShowTrustReport struct {
Raw []byte
SystemRegistriesDirPath string
JSONOutput []byte
Policies []*trust.TrustPolicy
}
// SetTrustOptions describes the CLI options for setting trust
type SetTrustOptions struct {
PolicyPath string
PubKeysFile []string
Type string
}

View File

@ -0,0 +1,171 @@
package abi
import (
"context"
"encoding/json"
"io/ioutil"
"os"
"strings"
"github.com/containers/libpod/pkg/domain/entities"
"github.com/containers/libpod/pkg/trust"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
func (ir *ImageEngine) ShowTrust(ctx context.Context, args []string, options entities.ShowTrustOptions) (*entities.ShowTrustReport, error) {
var (
err error
report entities.ShowTrustReport
)
policyPath := trust.DefaultPolicyPath(ir.Libpod.SystemContext())
if len(options.PolicyPath) > 0 {
policyPath = options.PolicyPath
}
report.Raw, err = ioutil.ReadFile(policyPath)
if err != nil {
return nil, errors.Wrapf(err, "unable to read %s", policyPath)
}
if options.Raw {
return &report, nil
}
report.SystemRegistriesDirPath = trust.RegistriesDirPath(ir.Libpod.SystemContext())
if len(options.RegistryPath) > 0 {
report.SystemRegistriesDirPath = options.RegistryPath
}
policyContentStruct, err := trust.GetPolicy(policyPath)
if err != nil {
return nil, errors.Wrapf(err, "could not read trust policies")
}
report.Policies, err = getPolicyShowOutput(policyContentStruct, report.SystemRegistriesDirPath)
if err != nil {
return nil, errors.Wrapf(err, "could not show trust policies")
}
return &report, nil
}
func (ir *ImageEngine) SetTrust(ctx context.Context, args []string, options entities.SetTrustOptions) error {
var (
policyContentStruct trust.PolicyContent
newReposContent []trust.RepoContent
)
trustType := options.Type
if trustType == "accept" {
trustType = "insecureAcceptAnything"
}
pubkeysfile := options.PubKeysFile
if len(pubkeysfile) == 0 && trustType == "signedBy" {
return errors.Errorf("At least one public key must be defined for type 'signedBy'")
}
policyPath := trust.DefaultPolicyPath(ir.Libpod.SystemContext())
if len(options.PolicyPath) > 0 {
policyPath = options.PolicyPath
}
_, err := os.Stat(policyPath)
if !os.IsNotExist(err) {
policyContent, err := ioutil.ReadFile(policyPath)
if err != nil {
return errors.Wrapf(err, "unable to read %s", policyPath)
}
if err := json.Unmarshal(policyContent, &policyContentStruct); err != nil {
return errors.Errorf("could not read trust policies")
}
}
if len(pubkeysfile) != 0 {
for _, filepath := range pubkeysfile {
newReposContent = append(newReposContent, trust.RepoContent{Type: trustType, KeyType: "GPGKeys", KeyPath: filepath})
}
} else {
newReposContent = append(newReposContent, trust.RepoContent{Type: trustType})
}
if args[0] == "default" {
policyContentStruct.Default = newReposContent
} else {
if len(policyContentStruct.Default) == 0 {
return errors.Errorf("Default trust policy must be set.")
}
registryExists := false
for transport, transportval := range policyContentStruct.Transports {
_, registryExists = transportval[args[0]]
if registryExists {
policyContentStruct.Transports[transport][args[0]] = newReposContent
break
}
}
if !registryExists {
if policyContentStruct.Transports == nil {
policyContentStruct.Transports = make(map[string]trust.RepoMap)
}
if policyContentStruct.Transports["docker"] == nil {
policyContentStruct.Transports["docker"] = make(map[string][]trust.RepoContent)
}
policyContentStruct.Transports["docker"][args[0]] = append(policyContentStruct.Transports["docker"][args[0]], newReposContent...)
}
}
data, err := json.MarshalIndent(policyContentStruct, "", " ")
if err != nil {
return errors.Wrapf(err, "error setting trust policy")
}
return ioutil.WriteFile(policyPath, data, 0644)
}
func getPolicyShowOutput(policyContentStruct trust.PolicyContent, systemRegistriesDirPath string) ([]*trust.TrustPolicy, error) {
var output []*trust.TrustPolicy
registryConfigs, err := trust.LoadAndMergeConfig(systemRegistriesDirPath)
if err != nil {
return nil, err
}
if len(policyContentStruct.Default) > 0 {
defaultPolicyStruct := trust.TrustPolicy{
Name: "* (default)",
RepoName: "default",
Type: trustTypeDescription(policyContentStruct.Default[0].Type),
}
output = append(output, &defaultPolicyStruct)
}
for _, transval := range policyContentStruct.Transports {
for repo, repoval := range transval {
tempTrustShowOutput := trust.TrustPolicy{
Name: repo,
RepoName: repo,
Type: repoval[0].Type,
}
// TODO - keyarr is not used and I don't know its intent; commenting out for now for someone to fix later
//keyarr := []string{}
uids := []string{}
for _, repoele := range repoval {
if len(repoele.KeyPath) > 0 {
//keyarr = append(keyarr, repoele.KeyPath)
uids = append(uids, trust.GetGPGIdFromKeyPath(repoele.KeyPath)...)
}
if len(repoele.KeyData) > 0 {
//keyarr = append(keyarr, string(repoele.KeyData))
uids = append(uids, trust.GetGPGIdFromKeyData(repoele.KeyData)...)
}
}
tempTrustShowOutput.GPGId = strings.Join(uids, ", ")
registryNamespace := trust.HaveMatchRegistry(repo, registryConfigs)
if registryNamespace != nil {
tempTrustShowOutput.SignatureStore = registryNamespace.SigStore
}
output = append(output, &tempTrustShowOutput)
}
}
return output, nil
}
var typeDescription = map[string]string{"insecureAcceptAnything": "accept", "signedBy": "signed", "reject": "reject"}
func trustTypeDescription(trustType string) string {
trustDescription, exist := typeDescription[trustType]
if !exist {
logrus.Warnf("invalid trust type %s", trustType)
}
return trustDescription
}

View File

@ -0,0 +1,16 @@
package tunnel
import (
"context"
"errors"
"github.com/containers/libpod/pkg/domain/entities"
)
func (ir *ImageEngine) ShowTrust(ctx context.Context, args []string, options entities.ShowTrustOptions) (*entities.ShowTrustReport, error) {
return nil, errors.New("not implemented")
}
func (ir *ImageEngine) SetTrust(ctx context.Context, args []string, options entities.SetTrustOptions) error {
return errors.New("not implemented")
}

12
pkg/trust/config.go Normal file
View File

@ -0,0 +1,12 @@
package trust
// Trust Policy describes a basic trust policy configuration
type TrustPolicy struct {
Name string `json:"name"`
RepoName string `json:"repo_name,omitempty"`
Keys []string `json:"keys,omitempty"`
SignatureStore string `json:"sigstore"`
Transport string `json:"transport"`
Type string `json:"type"`
GPGId string `json:"gpg_id,omitempty"`
}

View File

@ -21,7 +21,6 @@ var _ = Describe("Podman trust", func() {
)
BeforeEach(func() {
Skip(v2fail)
tempdir, err = CreateTempDirInTempDir()
if err != nil {
os.Exit(1)