Skip to content

Commit

Permalink
Merge pull request #15466 from mtrmac/image-trust-sigstore
Browse files Browse the repository at this point in the history
podman image trust overhaul, incl. sigstore
  • Loading branch information
rhatdan authored Aug 25, 2022
2 parents f98215c + 61fe95b commit bb7ae54
Show file tree
Hide file tree
Showing 12 changed files with 1,086 additions and 355 deletions.
4 changes: 2 additions & 2 deletions cmd/podman/images/trust_set.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,15 +53,15 @@ File(s) must exist before using this command`)
}

func setTrust(cmd *cobra.Command, args []string) error {
validTrustTypes := []string{"accept", "insecureAcceptAnything", "reject", "signedBy"}
validTrustTypes := []string{"accept", "insecureAcceptAnything", "reject", "signedBy", "sigstoreSigned"}

valid, err := isValidImageURI(args[0])
if err != nil || !valid {
return err
}

if !util.StringInSlice(setOptions.Type, validTrustTypes) {
return fmt.Errorf("invalid choice: %s (choose from 'accept', 'reject', 'signedBy')", setOptions.Type)
return fmt.Errorf("invalid choice: %s (choose from 'accept', 'reject', 'signedBy', 'sigstoreSigned')", setOptions.Type)
}
return registry.ImageEngine().SetTrust(registry.Context(), args, setOptions)
}
Expand Down
9 changes: 6 additions & 3 deletions docs/source/markdown/podman-image-trust.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ Trust **type** provides a way to:

Allowlist ("accept") or
Denylist ("reject") registries or
Require signature (“signedBy”).
Require a simple signing signature (“signedBy”),
Require a sigstore signature ("sigstoreSigned").

Trust may be updated using the command **podman image trust set** for an existing trust scope.

Expand All @@ -45,12 +46,14 @@ Trust may be updated using the command **podman image trust set** for an existin
#### **--pubkeysfile**, **-f**=*KEY1*
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
require an image be signed by multiple keys. The **--pubkeysfile** option is required for the **signedBy** type.
require an image be signed by multiple keys. The **--pubkeysfile** option is required for the **signedBy** and **sigstoreSigned** types.

#### **--type**, **-t**=*value*
The trust type for this policy entry.
Accepted values:
**signedBy** (default): Require signatures with corresponding list of
**signedBy** (default): Require simple signing signatures with corresponding list of
public keys
**sigstoreSigned**: Require sigstore signatures with corresponding list of
public keys
**accept**: do not require any signatures for this
registry scope
Expand Down
141 changes: 9 additions & 132 deletions pkg/domain/infra/abi/trust.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,11 @@ package abi

import (
"context"
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"os"
"strings"

"github.com/containers/podman/v4/pkg/domain/entities"
"github.com/containers/podman/v4/pkg/trust"
"github.com/sirupsen/logrus"
)

func (ir *ImageEngine) ShowTrust(ctx context.Context, args []string, options entities.ShowTrustOptions) (*entities.ShowTrustReport, error) {
Expand All @@ -34,145 +29,27 @@ func (ir *ImageEngine) ShowTrust(ctx context.Context, args []string, options ent
if len(options.RegistryPath) > 0 {
report.SystemRegistriesDirPath = options.RegistryPath
}
policyContentStruct, err := trust.GetPolicy(policyPath)
if err != nil {
return nil, fmt.Errorf("could not read trust policies: %w", err)
}
report.Policies, err = getPolicyShowOutput(policyContentStruct, report.SystemRegistriesDirPath)
report.Policies, err = trust.PolicyDescription(policyPath, report.SystemRegistriesDirPath)
if err != nil {
return nil, fmt.Errorf("could not show trust policies: %w", err)
}
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.New("at least one public key must be defined for type 'signedBy'")
if len(args) != 1 {
return fmt.Errorf("SetTrust called with unexpected %d args", len(args))
}
scope := args[0]

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 err
}
if err := json.Unmarshal(policyContent, &policyContentStruct); err != nil {
return errors.New("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.New("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 fmt.Errorf("error setting trust policy: %w", err)
}
return ioutil.WriteFile(policyPath, data, 0644)
}

func getPolicyShowOutput(policyContentStruct trust.PolicyContent, systemRegistriesDirPath string) ([]*trust.Policy, error) {
var output []*trust.Policy

registryConfigs, err := trust.LoadAndMergeConfig(systemRegistriesDirPath)
if err != nil {
return nil, err
}

if len(policyContentStruct.Default) > 0 {
defaultPolicyStruct := trust.Policy{
Transport: "all",
Name: "* (default)",
RepoName: "default",
Type: trustTypeDescription(policyContentStruct.Default[0].Type),
}
output = append(output, &defaultPolicyStruct)
}
for transport, transval := range policyContentStruct.Transports {
if transport == "docker" {
transport = "repository"
}

for repo, repoval := range transval {
tempTrustShowOutput := trust.Policy{
Name: repo,
RepoName: repo,
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
// 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
return trust.AddPolicyEntries(policyPath, trust.AddPolicyEntriesInput{
Scope: scope,
Type: options.Type,
PubKeyFiles: options.PubKeysFile,
})
}
12 changes: 0 additions & 12 deletions pkg/trust/config.go

This file was deleted.

Loading

0 comments on commit bb7ae54

Please sign in to comment.