From e24167eef9d55f11b21b487678f79b5a70d3c4dd Mon Sep 17 00:00:00 2001 From: Qi Wang Date: Fri, 11 Jan 2019 11:38:44 -0500 Subject: Fix up `image sign` in PR 2108 Signed-off-by: Qi Wang --- cmd/podman/trust.go | 152 ++++++++++++++++++++++++++++++++++++++++++---------- pkg/trust/trust.go | 122 ++++++++++------------------------------- 2 files changed, 153 insertions(+), 121 deletions(-) diff --git a/cmd/podman/trust.go b/cmd/podman/trust.go index 863f36d09..a99be6ba2 100644 --- a/cmd/podman/trust.go +++ b/cmd/podman/trust.go @@ -6,6 +6,7 @@ import ( "io/ioutil" "os" "sort" + "strings" "github.com/containers/image/types" "github.com/containers/libpod/cmd/podman/formats" @@ -13,6 +14,7 @@ import ( "github.com/containers/libpod/libpod/image" "github.com/containers/libpod/pkg/trust" "github.com/pkg/errors" + "github.com/sirupsen/logrus" "github.com/urfave/cli" ) @@ -103,6 +105,7 @@ func showTrustCmd(c *cli.Context) error { var ( policyPath string systemRegistriesDirPath string + outjson interface{} ) if c.IsSet("policypath") { policyPath = c.String("policypath") @@ -127,30 +130,26 @@ func showTrustCmd(c *cli.Context) error { return nil } - var policyContentStruct trust.PolicyContent - if err := json.Unmarshal(policyContent, &policyContentStruct); err != nil { - return errors.Errorf("could not read trust policies") - } - policyJSON, showOutputMap, err := trust.GetPolicy(policyContentStruct, systemRegistriesDirPath) + policyContentStruct, err := trust.GetPolicy(policyPath) if err != nil { - return errors.Wrapf(err, "error reading registry config file") + return errors.Wrapf(err, "could not read trust policies") } + if c.Bool("json") { - var outjson interface{} + policyJSON, err := getPolicyJSON(policyContentStruct, systemRegistriesDirPath) + if err != nil { + return errors.Wrapf(err, "could not show trust policies in JSON format") + } outjson = policyJSON out := formats.JSONStruct{Output: outjson} return formats.Writer(out).Out() } - sortedRepos := sortPolicyJSONKey(policyJSON) - var output []interface{} - for _, reponame := range sortedRepos { - showOutput, exists := showOutputMap[reponame] - if exists { - output = append(output, interface{}(showOutput)) - } + showOutputMap, err := getPolicyShowOutput(policyContentStruct, systemRegistriesDirPath) + if err != nil { + return errors.Wrapf(err, "could not show trust policies") } - out := formats.StdoutTemplateArray{Output: output, Template: "{{.Repo}}\t{{.Trusttype}}\t{{.GPGid}}\t{{.Sigstore}}"} + out := formats.StdoutTemplateArray{Output: showOutputMap, Template: "{{.Repo}}\t{{.Trusttype}}\t{{.GPGid}}\t{{.Sigstore}}"} return formats.Writer(out).Out() } @@ -159,7 +158,11 @@ func setTrustCmd(c *cli.Context) error { if err != nil { return errors.Wrapf(err, "could not create runtime") } - + var ( + policyPath string + policyContentStruct trust.PolicyContent + newReposContent []trust.RepoContent + ) args := c.Args() if len(args) != 1 { return errors.Errorf("default or a registry name must be specified") @@ -182,17 +185,13 @@ func setTrustCmd(c *cli.Context) error { return errors.Errorf("At least one public key must be defined for type 'signedBy'") } - var policyPath string if c.IsSet("policypath") { policyPath = c.String("policypath") } else { policyPath = trust.DefaultPolicyPath(runtime.SystemContext()) } - var policyContentStruct trust.PolicyContent - policyFileExists := false _, err = os.Stat(policyPath) if !os.IsNotExist(err) { - policyFileExists = true policyContent, err := ioutil.ReadFile(policyPath) if err != nil { return errors.Wrapf(err, "unable to read %s", policyPath) @@ -200,11 +199,7 @@ func setTrustCmd(c *cli.Context) error { if err := json.Unmarshal(policyContent, &policyContentStruct); err != nil { return errors.Errorf("could not read trust policies") } - if args[0] != "default" && len(policyContentStruct.Default) == 0 { - return errors.Errorf("Default trust policy must be set.") - } } - var newReposContent []trust.RepoContent if len(pubkeysfile) != 0 { for _, filepath := range pubkeysfile { newReposContent = append(newReposContent, trust.RepoContent{Type: trusttype, KeyType: "GPGKeys", KeyPath: filepath}) @@ -215,8 +210,8 @@ func setTrustCmd(c *cli.Context) error { if args[0] == "default" { policyContentStruct.Default = newReposContent } else { - if policyFileExists == false && len(policyContentStruct.Default) == 0 { - return errors.Errorf("Default trust policy must be set to create the policy file.") + if len(policyContentStruct.Default) == 0 { + return errors.Errorf("Default trust policy must be set.") } registryExists := false for transport, transportval := range policyContentStruct.Transports { @@ -248,7 +243,7 @@ func setTrustCmd(c *cli.Context) error { return nil } -func sortPolicyJSONKey(m map[string]map[string]interface{}) []string { +func sortShowOutputMapKey(m map[string]trust.ShowOutput) []string { keys := make([]string, len(m)) i := 0 for k := range m { @@ -269,3 +264,106 @@ func isValidTrustType(t string) bool { func getDefaultPolicyPath() string { return trust.DefaultPolicyPath(&types.SystemContext{}) } + +func getPolicyJSON(policyContentStruct trust.PolicyContent, systemRegistriesDirPath string) (map[string]map[string]interface{}, error) { + registryConfigs, err := trust.LoadAndMergeConfig(systemRegistriesDirPath) + if err != nil { + return nil, err + } + + policyJSON := make(map[string]map[string]interface{}) + if len(policyContentStruct.Default) > 0 { + policyJSON["* (default)"] = make(map[string]interface{}) + policyJSON["* (default)"]["type"] = policyContentStruct.Default[0].Type + } + for transname, transval := range policyContentStruct.Transports { + for repo, repoval := range transval { + policyJSON[repo] = make(map[string]interface{}) + policyJSON[repo]["type"] = repoval[0].Type + policyJSON[repo]["transport"] = transname + 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(string(repoele.KeyData))...) + } + } + policyJSON[repo]["keys"] = keyarr + policyJSON[repo]["sigstore"] = "" + registryNamespace := trust.HaveMatchRegistry(repo, registryConfigs) + if registryNamespace != nil { + policyJSON[repo]["sigstore"] = registryNamespace.SigStore + } + } + } + return policyJSON, 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 +} + +func getPolicyShowOutput(policyContentStruct trust.PolicyContent, systemRegistriesDirPath string) ([]interface{}, error) { + var output []interface{} + + registryConfigs, err := trust.LoadAndMergeConfig(systemRegistriesDirPath) + if err != nil { + return nil, err + } + + trustShowOutputMap := make(map[string]trust.ShowOutput) + if len(policyContentStruct.Default) > 0 { + defaultPolicyStruct := trust.ShowOutput{ + Repo: "default", + Trusttype: trustTypeDescription(policyContentStruct.Default[0].Type), + } + trustShowOutputMap["* (default)"] = defaultPolicyStruct + } + for _, transval := range policyContentStruct.Transports { + for repo, repoval := range transval { + tempTrustShowOutput := trust.ShowOutput{ + Repo: repo, + Trusttype: repoval[0].Type, + } + 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(string(repoele.KeyData))...) + } + } + tempTrustShowOutput.GPGid = strings.Join(uids, ", ") + + registryNamespace := trust.HaveMatchRegistry(repo, registryConfigs) + if registryNamespace != nil { + tempTrustShowOutput.Sigstore = registryNamespace.SigStore + } + trustShowOutputMap[repo] = tempTrustShowOutput + } + } + + sortedRepos := sortShowOutputMapKey(trustShowOutputMap) + for _, reponame := range sortedRepos { + showOutput, exists := trustShowOutputMap[reponame] + if exists { + output = append(output, interface{}(showOutput)) + } + } + return output, nil +} diff --git a/pkg/trust/trust.go b/pkg/trust/trust.go index 31e41903e..9a75474ae 100644 --- a/pkg/trust/trust.go +++ b/pkg/trust/trust.go @@ -175,43 +175,30 @@ func CreateTmpFile(dir, pattern string, content []byte) (string, error) { return tmpfile.Name(), nil } -func getGPGIdFromKeyPath(path []string) []string { - var uids []string - for _, k := range path { - cmd := exec.Command("gpg2", "--with-colons", k) - results, err := cmd.Output() - if err != nil { - logrus.Warnf("error get key identity: %s", err) - continue - } - uids = append(uids, parseUids(results)...) +// GetGPGIdFromKeyPath return user keyring from key path +func GetGPGIdFromKeyPath(path string) []string { + cmd := exec.Command("gpg2", "--with-colons", path) + results, err := cmd.Output() + if err != nil { + logrus.Errorf("error getting key identity: %s", err) + return nil } - return uids + return parseUids(results) } -func getGPGIdFromKeyData(keys []string) []string { - var uids []string - for _, k := range keys { - decodeKey, err := base64.StdEncoding.DecodeString(k) - if err != nil { - logrus.Warnf("error decoding key data") - continue - } - tmpfileName, err := CreateTmpFile("", "", decodeKey) - if err != nil { - logrus.Warnf("error creating key date temp file %s", err) - } - defer os.Remove(tmpfileName) - k = tmpfileName - cmd := exec.Command("gpg2", "--with-colons", k) - results, err := cmd.Output() - if err != nil { - logrus.Warnf("error get key identity: %s", err) - continue - } - uids = append(uids, parseUids(results)...) +// GetGPGIdFromKeyData return user keyring from keydata +func GetGPGIdFromKeyData(key string) []string { + decodeKey, err := base64.StdEncoding.DecodeString(key) + if err != nil { + logrus.Errorf("%s, error decoding key data", err) + return nil } - return uids + tmpfileName, err := CreateTmpFile("", "", decodeKey) + if err != nil { + logrus.Errorf("error creating key date temp file %s", err) + } + defer os.Remove(tmpfileName) + return GetGPGIdFromKeyPath(tmpfileName) } func parseUids(colonDelimitKeys []byte) []string { @@ -234,68 +221,15 @@ func parseUids(colonDelimitKeys []byte) []string { return parseduids } -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 -} - -// GetPolicy return the struct to show policy.json in json format and a map (reponame, ShowOutput) pair for image trust show command -func GetPolicy(policyContentStruct PolicyContent, systemRegistriesDirPath string) (map[string]map[string]interface{}, map[string]ShowOutput, error) { - registryConfigs, err := LoadAndMergeConfig(systemRegistriesDirPath) +// GetPolicy parse policy.json into PolicyContent struct +func GetPolicy(policyPath string) (PolicyContent, error) { + var policyContentStruct PolicyContent + policyContent, err := ioutil.ReadFile(policyPath) if err != nil { - return nil, nil, err + return policyContentStruct, errors.Wrapf(err, "unable to read policy file %s", policyPath) } - - trustShowOutputMap := make(map[string]ShowOutput) - policyJSON := make(map[string]map[string]interface{}) - if len(policyContentStruct.Default) > 0 { - policyJSON["* (default)"] = make(map[string]interface{}) - policyJSON["* (default)"]["type"] = policyContentStruct.Default[0].Type - - var defaultPolicyStruct ShowOutput - defaultPolicyStruct.Repo = "default" - defaultPolicyStruct.Trusttype = trustTypeDescription(policyContentStruct.Default[0].Type) - trustShowOutputMap["* (default)"] = defaultPolicyStruct - } - for transname, transval := range policyContentStruct.Transports { - for repo, repoval := range transval { - tempTrustShowOutput := ShowOutput{ - Repo: repo, - Trusttype: repoval[0].Type, - } - policyJSON[repo] = make(map[string]interface{}) - policyJSON[repo]["type"] = repoval[0].Type - policyJSON[repo]["transport"] = transname - keyDataArr := []string{} - keyPathArr := []string{} - keyarr := []string{} - for _, repoele := range repoval { - if len(repoele.KeyPath) > 0 { - keyarr = append(keyarr, repoele.KeyPath) - keyPathArr = append(keyPathArr, repoele.KeyPath) - } - if len(repoele.KeyData) > 0 { - keyarr = append(keyarr, string(repoele.KeyData)) - keyDataArr = append(keyDataArr, string(repoele.KeyData)) - } - } - policyJSON[repo]["keys"] = keyarr - uids := append(getGPGIdFromKeyPath(keyPathArr), getGPGIdFromKeyData(keyDataArr)...) - tempTrustShowOutput.GPGid = strings.Join(uids, ",") - - policyJSON[repo]["sigstore"] = "" - registryNamespace := HaveMatchRegistry(repo, registryConfigs) - if registryNamespace != nil { - policyJSON[repo]["sigstore"] = registryNamespace.SigStore - tempTrustShowOutput.Sigstore = registryNamespace.SigStore - } - trustShowOutputMap[repo] = tempTrustShowOutput - } + if err := json.Unmarshal(policyContent, &policyContentStruct); err != nil { + return policyContentStruct, errors.Wrapf(err, "could not parse trust policies") } - return policyJSON, trustShowOutputMap, nil + return policyContentStruct, nil } -- cgit v1.2.3-54-g00ecf