github.com/containers/libpod@v1.9.4-0.20220419124438-4284fd425507/cmd/podman/trust_set_show.go (about) 1 package main 2 3 import ( 4 "io/ioutil" 5 "os" 6 "sort" 7 "strings" 8 9 "github.com/containers/buildah/pkg/formats" 10 "github.com/containers/libpod/cmd/podman/cliconfig" 11 "github.com/containers/libpod/cmd/podman/libpodruntime" 12 "github.com/containers/libpod/libpod/image" 13 "github.com/containers/libpod/pkg/trust" 14 "github.com/pkg/errors" 15 "github.com/sirupsen/logrus" 16 "github.com/spf13/cobra" 17 ) 18 19 var ( 20 setTrustCommand cliconfig.SetTrustValues 21 showTrustCommand cliconfig.ShowTrustValues 22 setTrustDescription = "Set default trust policy or add a new trust policy for a registry" 23 _setTrustCommand = &cobra.Command{ 24 Use: "set [flags] REGISTRY", 25 Short: "Set default trust policy or a new trust policy for a registry", 26 Long: setTrustDescription, 27 Example: "", 28 RunE: func(cmd *cobra.Command, args []string) error { 29 setTrustCommand.InputArgs = args 30 setTrustCommand.GlobalFlags = MainGlobalOpts 31 setTrustCommand.Remote = remoteclient 32 return setTrustCmd(&setTrustCommand) 33 }, 34 } 35 36 showTrustDescription = "Display trust policy for the system" 37 _showTrustCommand = &cobra.Command{ 38 Use: "show [flags] [REGISTRY]", 39 Short: "Display trust policy for the system", 40 Long: showTrustDescription, 41 RunE: func(cmd *cobra.Command, args []string) error { 42 showTrustCommand.InputArgs = args 43 showTrustCommand.GlobalFlags = MainGlobalOpts 44 return showTrustCmd(&showTrustCommand) 45 }, 46 Example: "", 47 } 48 ) 49 50 func init() { 51 setTrustCommand.Command = _setTrustCommand 52 setTrustCommand.SetHelpTemplate(HelpTemplate()) 53 setTrustCommand.SetUsageTemplate(UsageTemplate()) 54 showTrustCommand.Command = _showTrustCommand 55 showTrustCommand.SetHelpTemplate(HelpTemplate()) 56 showTrustCommand.SetUsageTemplate(UsageTemplate()) 57 setFlags := setTrustCommand.Flags() 58 setFlags.StringVar(&setTrustCommand.PolicyPath, "policypath", "", "") 59 markFlagHidden(setFlags, "policypath") 60 setFlags.StringSliceVarP(&setTrustCommand.PubKeysFile, "pubkeysfile", "f", []string{}, `Path of installed public key(s) to trust for TARGET. 61 Absolute path to keys is added to policy.json. May 62 used multiple times to define multiple public keys. 63 File(s) must exist before using this command`) 64 setFlags.StringVarP(&setTrustCommand.TrustType, "type", "t", "signedBy", "Trust type, accept values: signedBy(default), accept, reject") 65 66 showFlags := showTrustCommand.Flags() 67 showFlags.BoolVarP(&showTrustCommand.Json, "json", "j", false, "Output as json") 68 showFlags.StringVar(&showTrustCommand.PolicyPath, "policypath", "", "") 69 showFlags.BoolVar(&showTrustCommand.Raw, "raw", false, "Output raw policy file") 70 markFlagHidden(showFlags, "policypath") 71 showFlags.StringVar(&showTrustCommand.RegistryPath, "registrypath", "", "") 72 markFlagHidden(showFlags, "registrypath") 73 } 74 75 func showTrustCmd(c *cliconfig.ShowTrustValues) error { 76 runtime, err := libpodruntime.GetRuntime(getContext(), &c.PodmanCommand) 77 if err != nil { 78 return errors.Wrapf(err, "could not create runtime") 79 } 80 81 var ( 82 policyPath string 83 systemRegistriesDirPath string 84 outjson interface{} 85 ) 86 if c.Flag("policypath").Changed { 87 policyPath = c.PolicyPath 88 } else { 89 policyPath = trust.DefaultPolicyPath(runtime.SystemContext()) 90 } 91 policyContent, err := ioutil.ReadFile(policyPath) 92 if err != nil { 93 return errors.Wrapf(err, "unable to read %s", policyPath) 94 } 95 if c.Flag("registrypath").Changed { 96 systemRegistriesDirPath = c.RegistryPath 97 } else { 98 systemRegistriesDirPath = trust.RegistriesDirPath(runtime.SystemContext()) 99 } 100 101 if c.Raw { 102 _, err := os.Stdout.Write(policyContent) 103 if err != nil { 104 return errors.Wrap(err, "could not read raw trust policies") 105 } 106 return nil 107 } 108 109 policyContentStruct, err := trust.GetPolicy(policyPath) 110 if err != nil { 111 return errors.Wrapf(err, "could not read trust policies") 112 } 113 114 if c.Json { 115 policyJSON, err := getPolicyJSON(policyContentStruct, systemRegistriesDirPath) 116 if err != nil { 117 return errors.Wrapf(err, "could not show trust policies in JSON format") 118 } 119 outjson = policyJSON 120 out := formats.JSONStruct{Output: outjson} 121 return out.Out() 122 } 123 124 showOutputMap, err := getPolicyShowOutput(policyContentStruct, systemRegistriesDirPath) 125 if err != nil { 126 return errors.Wrapf(err, "could not show trust policies") 127 } 128 out := formats.StdoutTemplateArray{Output: showOutputMap, Template: "{{.Repo}}\t{{.Trusttype}}\t{{.GPGid}}\t{{.Sigstore}}"} 129 return out.Out() 130 } 131 132 func setTrustCmd(c *cliconfig.SetTrustValues) error { 133 runtime, err := libpodruntime.GetRuntime(getContext(), &c.PodmanCommand) 134 if err != nil { 135 return errors.Wrapf(err, "could not create runtime") 136 } 137 var ( 138 policyPath string 139 policyContentStruct trust.PolicyContent 140 newReposContent []trust.RepoContent 141 ) 142 args := c.InputArgs 143 if len(args) != 1 { 144 return errors.Errorf("default or a registry name must be specified") 145 } 146 valid, err := image.IsValidImageURI(args[0]) 147 if err != nil || !valid { 148 return errors.Wrapf(err, "invalid image uri %s", args[0]) 149 } 150 151 trusttype := c.TrustType 152 if !isValidTrustType(trusttype) { 153 return errors.Errorf("invalid choice: %s (choose from 'accept', 'reject', 'signedBy')", trusttype) 154 } 155 if trusttype == "accept" { 156 trusttype = "insecureAcceptAnything" 157 } 158 159 pubkeysfile := c.PubKeysFile 160 if len(pubkeysfile) == 0 && trusttype == "signedBy" { 161 return errors.Errorf("At least one public key must be defined for type 'signedBy'") 162 } 163 164 if c.Flag("policypath").Changed { 165 policyPath = c.PolicyPath 166 } else { 167 policyPath = trust.DefaultPolicyPath(runtime.SystemContext()) 168 } 169 _, err = os.Stat(policyPath) 170 if !os.IsNotExist(err) { 171 policyContent, err := ioutil.ReadFile(policyPath) 172 if err != nil { 173 return errors.Wrapf(err, "unable to read %s", policyPath) 174 } 175 if err := json.Unmarshal(policyContent, &policyContentStruct); err != nil { 176 return errors.Errorf("could not read trust policies") 177 } 178 } 179 if len(pubkeysfile) != 0 { 180 for _, filepath := range pubkeysfile { 181 newReposContent = append(newReposContent, trust.RepoContent{Type: trusttype, KeyType: "GPGKeys", KeyPath: filepath}) 182 } 183 } else { 184 newReposContent = append(newReposContent, trust.RepoContent{Type: trusttype}) 185 } 186 if args[0] == "default" { 187 policyContentStruct.Default = newReposContent 188 } else { 189 if len(policyContentStruct.Default) == 0 { 190 return errors.Errorf("Default trust policy must be set.") 191 } 192 registryExists := false 193 for transport, transportval := range policyContentStruct.Transports { 194 _, registryExists = transportval[args[0]] 195 if registryExists { 196 policyContentStruct.Transports[transport][args[0]] = newReposContent 197 break 198 } 199 } 200 if !registryExists { 201 if policyContentStruct.Transports == nil { 202 policyContentStruct.Transports = make(map[string]trust.RepoMap) 203 } 204 if policyContentStruct.Transports["docker"] == nil { 205 policyContentStruct.Transports["docker"] = make(map[string][]trust.RepoContent) 206 } 207 policyContentStruct.Transports["docker"][args[0]] = append(policyContentStruct.Transports["docker"][args[0]], newReposContent...) 208 } 209 } 210 211 data, err := json.MarshalIndent(policyContentStruct, "", " ") 212 if err != nil { 213 return errors.Wrapf(err, "error setting trust policy") 214 } 215 err = ioutil.WriteFile(policyPath, data, 0644) 216 if err != nil { 217 return errors.Wrapf(err, "error setting trust policy") 218 } 219 return nil 220 } 221 222 func sortShowOutputMapKey(m map[string]trust.ShowOutput) []string { 223 keys := make([]string, len(m)) 224 i := 0 225 for k := range m { 226 keys[i] = k 227 i++ 228 } 229 sort.Strings(keys) 230 return keys 231 } 232 233 func isValidTrustType(t string) bool { 234 if t == "accept" || t == "insecureAcceptAnything" || t == "reject" || t == "signedBy" { 235 return true 236 } 237 return false 238 } 239 240 func getPolicyJSON(policyContentStruct trust.PolicyContent, systemRegistriesDirPath string) (map[string]map[string]interface{}, error) { 241 registryConfigs, err := trust.LoadAndMergeConfig(systemRegistriesDirPath) 242 if err != nil { 243 return nil, err 244 } 245 246 policyJSON := make(map[string]map[string]interface{}) 247 if len(policyContentStruct.Default) > 0 { 248 policyJSON["* (default)"] = make(map[string]interface{}) 249 policyJSON["* (default)"]["type"] = policyContentStruct.Default[0].Type 250 } 251 for transname, transval := range policyContentStruct.Transports { 252 for repo, repoval := range transval { 253 policyJSON[repo] = make(map[string]interface{}) 254 policyJSON[repo]["type"] = repoval[0].Type 255 policyJSON[repo]["transport"] = transname 256 keyarr := []string{} 257 for _, repoele := range repoval { 258 if len(repoele.KeyPath) > 0 { 259 keyarr = append(keyarr, repoele.KeyPath) 260 } 261 if len(repoele.KeyData) > 0 { 262 keyarr = append(keyarr, repoele.KeyData) 263 } 264 } 265 policyJSON[repo]["keys"] = keyarr 266 policyJSON[repo]["sigstore"] = "" 267 registryNamespace := trust.HaveMatchRegistry(repo, registryConfigs) 268 if registryNamespace != nil { 269 policyJSON[repo]["sigstore"] = registryNamespace.SigStore 270 } 271 } 272 } 273 return policyJSON, nil 274 } 275 276 var typeDescription = map[string]string{"insecureAcceptAnything": "accept", "signedBy": "signed", "reject": "reject"} 277 278 func trustTypeDescription(trustType string) string { 279 trustDescription, exist := typeDescription[trustType] 280 if !exist { 281 logrus.Warnf("invalid trust type %s", trustType) 282 } 283 return trustDescription 284 } 285 286 func getPolicyShowOutput(policyContentStruct trust.PolicyContent, systemRegistriesDirPath string) ([]interface{}, error) { 287 var output []interface{} 288 289 registryConfigs, err := trust.LoadAndMergeConfig(systemRegistriesDirPath) 290 if err != nil { 291 return nil, err 292 } 293 294 trustShowOutputMap := make(map[string]trust.ShowOutput) 295 if len(policyContentStruct.Default) > 0 { 296 defaultPolicyStruct := trust.ShowOutput{ 297 Repo: "default", 298 Trusttype: trustTypeDescription(policyContentStruct.Default[0].Type), 299 } 300 trustShowOutputMap["* (default)"] = defaultPolicyStruct 301 } 302 for _, transval := range policyContentStruct.Transports { 303 for repo, repoval := range transval { 304 tempTrustShowOutput := trust.ShowOutput{ 305 Repo: repo, 306 Trusttype: repoval[0].Type, 307 } 308 // TODO - keyarr is not used and I don't know its intent; commenting out for now for someone to fix later 309 //keyarr := []string{} 310 uids := []string{} 311 for _, repoele := range repoval { 312 if len(repoele.KeyPath) > 0 { 313 //keyarr = append(keyarr, repoele.KeyPath) 314 uids = append(uids, trust.GetGPGIdFromKeyPath(repoele.KeyPath)...) 315 } 316 if len(repoele.KeyData) > 0 { 317 //keyarr = append(keyarr, string(repoele.KeyData)) 318 uids = append(uids, trust.GetGPGIdFromKeyData(repoele.KeyData)...) 319 } 320 } 321 tempTrustShowOutput.GPGid = strings.Join(uids, ", ") 322 323 registryNamespace := trust.HaveMatchRegistry(repo, registryConfigs) 324 if registryNamespace != nil { 325 tempTrustShowOutput.Sigstore = registryNamespace.SigStore 326 } 327 trustShowOutputMap[repo] = tempTrustShowOutput 328 } 329 } 330 331 sortedRepos := sortShowOutputMapKey(trustShowOutputMap) 332 for _, reponame := range sortedRepos { 333 showOutput, exists := trustShowOutputMap[reponame] 334 if exists { 335 output = append(output, interface{}(showOutput)) 336 } 337 } 338 return output, nil 339 }