summaryrefslogtreecommitdiff
path: root/pkg/trust
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/trust')
-rw-r--r--pkg/trust/config.go12
-rw-r--r--pkg/trust/policy.go125
-rw-r--r--pkg/trust/registries.go121
-rw-r--r--pkg/trust/trust.go241
4 files changed, 255 insertions, 244 deletions
diff --git a/pkg/trust/config.go b/pkg/trust/config.go
deleted file mode 100644
index 6186d4cbd..000000000
--- a/pkg/trust/config.go
+++ /dev/null
@@ -1,12 +0,0 @@
-package trust
-
-// Policy describes a basic trust policy configuration
-type Policy struct {
- Transport string `json:"transport"`
- Name string `json:"name,omitempty"`
- RepoName string `json:"repo_name,omitempty"`
- Keys []string `json:"keys,omitempty"`
- SignatureStore string `json:"sigstore,omitempty"`
- Type string `json:"type"`
- GPGId string `json:"gpg_id,omitempty"`
-}
diff --git a/pkg/trust/policy.go b/pkg/trust/policy.go
new file mode 100644
index 000000000..9c44f7da2
--- /dev/null
+++ b/pkg/trust/policy.go
@@ -0,0 +1,125 @@
+package trust
+
+import (
+ "bufio"
+ "bytes"
+ "encoding/base64"
+ "encoding/json"
+ "fmt"
+ "io/ioutil"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "strings"
+
+ "github.com/containers/image/v5/types"
+ "github.com/sirupsen/logrus"
+)
+
+// PolicyContent struct for policy.json file
+type PolicyContent struct {
+ Default []RepoContent `json:"default"`
+ Transports TransportsContent `json:"transports,omitempty"`
+}
+
+// RepoContent struct used under each repo
+type RepoContent struct {
+ Type string `json:"type"`
+ KeyType string `json:"keyType,omitempty"`
+ KeyPath string `json:"keyPath,omitempty"`
+ KeyData string `json:"keyData,omitempty"`
+ SignedIdentity json.RawMessage `json:"signedIdentity,omitempty"`
+}
+
+// RepoMap map repo name to policycontent for each repo
+type RepoMap map[string][]RepoContent
+
+// TransportsContent struct for content under "transports"
+type TransportsContent map[string]RepoMap
+
+// DefaultPolicyPath returns a path to the default policy of the system.
+func DefaultPolicyPath(sys *types.SystemContext) string {
+ systemDefaultPolicyPath := "/etc/containers/policy.json"
+ if sys != nil {
+ if sys.SignaturePolicyPath != "" {
+ return sys.SignaturePolicyPath
+ }
+ if sys.RootForImplicitAbsolutePaths != "" {
+ return filepath.Join(sys.RootForImplicitAbsolutePaths, systemDefaultPolicyPath)
+ }
+ }
+ return systemDefaultPolicyPath
+}
+
+// CreateTmpFile creates a temp file under dir and writes the content into it
+func CreateTmpFile(dir, pattern string, content []byte) (string, error) {
+ tmpfile, err := ioutil.TempFile(dir, pattern)
+ if err != nil {
+ return "", err
+ }
+ defer tmpfile.Close()
+
+ if _, err := tmpfile.Write(content); err != nil {
+ return "", err
+ }
+ return tmpfile.Name(), nil
+}
+
+// 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("Getting key identity: %s", err)
+ return nil
+ }
+ return 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
+ }
+ tmpfileName, err := CreateTmpFile("", "", decodeKey)
+ if err != nil {
+ logrus.Errorf("Creating key date temp file %s", err)
+ }
+ defer os.Remove(tmpfileName)
+ return GetGPGIdFromKeyPath(tmpfileName)
+}
+
+func parseUids(colonDelimitKeys []byte) []string {
+ var parseduids []string
+ scanner := bufio.NewScanner(bytes.NewReader(colonDelimitKeys))
+ for scanner.Scan() {
+ line := scanner.Text()
+ if strings.HasPrefix(line, "uid:") || strings.HasPrefix(line, "pub:") {
+ uid := strings.Split(line, ":")[9]
+ if uid == "" {
+ continue
+ }
+ parseduid := uid
+ if strings.Contains(uid, "<") && strings.Contains(uid, ">") {
+ parseduid = strings.SplitN(strings.SplitAfterN(uid, "<", 2)[1], ">", 2)[0]
+ }
+ parseduids = append(parseduids, parseduid)
+ }
+ }
+ return parseduids
+}
+
+// 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 policyContentStruct, fmt.Errorf("unable to read policy file: %w", err)
+ }
+ if err := json.Unmarshal(policyContent, &policyContentStruct); err != nil {
+ return policyContentStruct, fmt.Errorf("could not parse trust policies from %s: %w", policyPath, err)
+ }
+ return policyContentStruct, nil
+}
diff --git a/pkg/trust/registries.go b/pkg/trust/registries.go
new file mode 100644
index 000000000..ba6ffe281
--- /dev/null
+++ b/pkg/trust/registries.go
@@ -0,0 +1,121 @@
+package trust
+
+import (
+ "fmt"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "strings"
+
+ "github.com/containers/image/v5/types"
+ "github.com/docker/docker/pkg/homedir"
+ "github.com/ghodss/yaml"
+)
+
+// RegistryConfiguration is one of the files in registriesDirPath configuring lookaside locations, or the result of merging them all.
+// NOTE: Keep this in sync with docs/registries.d.md!
+type RegistryConfiguration struct {
+ DefaultDocker *RegistryNamespace `json:"default-docker"`
+ // The key is a namespace, using fully-expanded Docker reference format or parent namespaces (per dockerReference.PolicyConfiguration*),
+ Docker map[string]RegistryNamespace `json:"docker"`
+}
+
+// RegistryNamespace defines lookaside locations for a single namespace.
+type RegistryNamespace struct {
+ SigStore string `json:"sigstore"` // For reading, and if SigStoreStaging is not present, for writing.
+ SigStoreStaging string `json:"sigstore-staging"` // For writing only.
+}
+
+// systemRegistriesDirPath is the path to registries.d.
+const systemRegistriesDirPath = "/etc/containers/registries.d"
+
+// userRegistriesDir is the path to the per user registries.d.
+var userRegistriesDir = filepath.FromSlash(".config/containers/registries.d")
+
+// RegistriesDirPath returns a path to registries.d
+func RegistriesDirPath(sys *types.SystemContext) string {
+ if sys != nil && sys.RegistriesDirPath != "" {
+ return sys.RegistriesDirPath
+ }
+ userRegistriesDirPath := filepath.Join(homedir.Get(), userRegistriesDir)
+ if _, err := os.Stat(userRegistriesDirPath); err == nil {
+ return userRegistriesDirPath
+ }
+ if sys != nil && sys.RootForImplicitAbsolutePaths != "" {
+ return filepath.Join(sys.RootForImplicitAbsolutePaths, systemRegistriesDirPath)
+ }
+
+ return systemRegistriesDirPath
+}
+
+// LoadAndMergeConfig loads configuration files in dirPath
+func LoadAndMergeConfig(dirPath string) (*RegistryConfiguration, error) {
+ mergedConfig := RegistryConfiguration{Docker: map[string]RegistryNamespace{}}
+ dockerDefaultMergedFrom := ""
+ nsMergedFrom := map[string]string{}
+
+ dir, err := os.Open(dirPath)
+ if err != nil {
+ if os.IsNotExist(err) {
+ return &mergedConfig, nil
+ }
+ return nil, err
+ }
+ configNames, err := dir.Readdirnames(0)
+ if err != nil {
+ return nil, err
+ }
+ for _, configName := range configNames {
+ if !strings.HasSuffix(configName, ".yaml") {
+ continue
+ }
+ configPath := filepath.Join(dirPath, configName)
+ configBytes, err := ioutil.ReadFile(configPath)
+ if err != nil {
+ return nil, err
+ }
+ var config RegistryConfiguration
+ err = yaml.Unmarshal(configBytes, &config)
+ if err != nil {
+ return nil, fmt.Errorf("error parsing %s: %w", configPath, err)
+ }
+ if config.DefaultDocker != nil {
+ if mergedConfig.DefaultDocker != nil {
+ return nil, fmt.Errorf(`error parsing signature storage configuration: "default-docker" defined both in "%s" and "%s"`,
+ dockerDefaultMergedFrom, configPath)
+ }
+ mergedConfig.DefaultDocker = config.DefaultDocker
+ dockerDefaultMergedFrom = configPath
+ }
+ for nsName, nsConfig := range config.Docker { // includes config.Docker == nil
+ if _, ok := mergedConfig.Docker[nsName]; ok {
+ return nil, fmt.Errorf(`error parsing signature storage configuration: "docker" namespace "%s" defined both in "%s" and "%s"`,
+ nsName, nsMergedFrom[nsName], configPath)
+ }
+ mergedConfig.Docker[nsName] = nsConfig
+ nsMergedFrom[nsName] = configPath
+ }
+ }
+ return &mergedConfig, nil
+}
+
+// HaveMatchRegistry checks if trust settings for the registry have been configured in yaml file
+func HaveMatchRegistry(key string, registryConfigs *RegistryConfiguration) *RegistryNamespace {
+ searchKey := key
+ if !strings.Contains(searchKey, "/") {
+ val, exists := registryConfigs.Docker[searchKey]
+ if exists {
+ return &val
+ }
+ }
+ for range strings.Split(key, "/") {
+ val, exists := registryConfigs.Docker[searchKey]
+ if exists {
+ return &val
+ }
+ if strings.Contains(searchKey, "/") {
+ searchKey = searchKey[:strings.LastIndex(searchKey, "/")]
+ }
+ }
+ return registryConfigs.DefaultDocker
+}
diff --git a/pkg/trust/trust.go b/pkg/trust/trust.go
index 28dac1ab6..6186d4cbd 100644
--- a/pkg/trust/trust.go
+++ b/pkg/trust/trust.go
@@ -1,235 +1,12 @@
package trust
-import (
- "bufio"
- "bytes"
- "encoding/base64"
- "encoding/json"
- "fmt"
- "io/ioutil"
- "os"
- "os/exec"
- "path/filepath"
- "strings"
-
- "github.com/containers/image/v5/types"
- "github.com/docker/docker/pkg/homedir"
- "github.com/ghodss/yaml"
- "github.com/sirupsen/logrus"
-)
-
-// PolicyContent struct for policy.json file
-type PolicyContent struct {
- Default []RepoContent `json:"default"`
- Transports TransportsContent `json:"transports,omitempty"`
-}
-
-// RepoContent struct used under each repo
-type RepoContent struct {
- Type string `json:"type"`
- KeyType string `json:"keyType,omitempty"`
- KeyPath string `json:"keyPath,omitempty"`
- KeyData string `json:"keyData,omitempty"`
- SignedIdentity json.RawMessage `json:"signedIdentity,omitempty"`
-}
-
-// RepoMap map repo name to policycontent for each repo
-type RepoMap map[string][]RepoContent
-
-// TransportsContent struct for content under "transports"
-type TransportsContent map[string]RepoMap
-
-// RegistryConfiguration is one of the files in registriesDirPath configuring lookaside locations, or the result of merging them all.
-// NOTE: Keep this in sync with docs/registries.d.md!
-type RegistryConfiguration struct {
- DefaultDocker *RegistryNamespace `json:"default-docker"`
- // The key is a namespace, using fully-expanded Docker reference format or parent namespaces (per dockerReference.PolicyConfiguration*),
- Docker map[string]RegistryNamespace `json:"docker"`
-}
-
-// RegistryNamespace defines lookaside locations for a single namespace.
-type RegistryNamespace struct {
- SigStore string `json:"sigstore"` // For reading, and if SigStoreStaging is not present, for writing.
- SigStoreStaging string `json:"sigstore-staging"` // For writing only.
-}
-
-// systemRegistriesDirPath is the path to registries.d.
-const systemRegistriesDirPath = "/etc/containers/registries.d"
-
-// userRegistriesDir is the path to the per user registries.d.
-var userRegistriesDir = filepath.FromSlash(".config/containers/registries.d")
-
-// DefaultPolicyPath returns a path to the default policy of the system.
-func DefaultPolicyPath(sys *types.SystemContext) string {
- systemDefaultPolicyPath := "/etc/containers/policy.json"
- if sys != nil {
- if sys.SignaturePolicyPath != "" {
- return sys.SignaturePolicyPath
- }
- if sys.RootForImplicitAbsolutePaths != "" {
- return filepath.Join(sys.RootForImplicitAbsolutePaths, systemDefaultPolicyPath)
- }
- }
- return systemDefaultPolicyPath
-}
-
-// RegistriesDirPath returns a path to registries.d
-func RegistriesDirPath(sys *types.SystemContext) string {
- if sys != nil && sys.RegistriesDirPath != "" {
- return sys.RegistriesDirPath
- }
- userRegistriesDirPath := filepath.Join(homedir.Get(), userRegistriesDir)
- if _, err := os.Stat(userRegistriesDirPath); err == nil {
- return userRegistriesDirPath
- }
- if sys != nil && sys.RootForImplicitAbsolutePaths != "" {
- return filepath.Join(sys.RootForImplicitAbsolutePaths, systemRegistriesDirPath)
- }
-
- return systemRegistriesDirPath
-}
-
-// LoadAndMergeConfig loads configuration files in dirPath
-func LoadAndMergeConfig(dirPath string) (*RegistryConfiguration, error) {
- mergedConfig := RegistryConfiguration{Docker: map[string]RegistryNamespace{}}
- dockerDefaultMergedFrom := ""
- nsMergedFrom := map[string]string{}
-
- dir, err := os.Open(dirPath)
- if err != nil {
- if os.IsNotExist(err) {
- return &mergedConfig, nil
- }
- return nil, err
- }
- configNames, err := dir.Readdirnames(0)
- if err != nil {
- return nil, err
- }
- for _, configName := range configNames {
- if !strings.HasSuffix(configName, ".yaml") {
- continue
- }
- configPath := filepath.Join(dirPath, configName)
- configBytes, err := ioutil.ReadFile(configPath)
- if err != nil {
- return nil, err
- }
- var config RegistryConfiguration
- err = yaml.Unmarshal(configBytes, &config)
- if err != nil {
- return nil, fmt.Errorf("error parsing %s: %w", configPath, err)
- }
- if config.DefaultDocker != nil {
- if mergedConfig.DefaultDocker != nil {
- return nil, fmt.Errorf(`error parsing signature storage configuration: "default-docker" defined both in "%s" and "%s"`,
- dockerDefaultMergedFrom, configPath)
- }
- mergedConfig.DefaultDocker = config.DefaultDocker
- dockerDefaultMergedFrom = configPath
- }
- for nsName, nsConfig := range config.Docker { // includes config.Docker == nil
- if _, ok := mergedConfig.Docker[nsName]; ok {
- return nil, fmt.Errorf(`error parsing signature storage configuration: "docker" namespace "%s" defined both in "%s" and "%s"`,
- nsName, nsMergedFrom[nsName], configPath)
- }
- mergedConfig.Docker[nsName] = nsConfig
- nsMergedFrom[nsName] = configPath
- }
- }
- return &mergedConfig, nil
-}
-
-// HaveMatchRegistry checks if trust settings for the registry have been configured in yaml file
-func HaveMatchRegistry(key string, registryConfigs *RegistryConfiguration) *RegistryNamespace {
- searchKey := key
- if !strings.Contains(searchKey, "/") {
- val, exists := registryConfigs.Docker[searchKey]
- if exists {
- return &val
- }
- }
- for range strings.Split(key, "/") {
- val, exists := registryConfigs.Docker[searchKey]
- if exists {
- return &val
- }
- if strings.Contains(searchKey, "/") {
- searchKey = searchKey[:strings.LastIndex(searchKey, "/")]
- }
- }
- return registryConfigs.DefaultDocker
-}
-
-// CreateTmpFile creates a temp file under dir and writes the content into it
-func CreateTmpFile(dir, pattern string, content []byte) (string, error) {
- tmpfile, err := ioutil.TempFile(dir, pattern)
- if err != nil {
- return "", err
- }
- defer tmpfile.Close()
-
- if _, err := tmpfile.Write(content); err != nil {
- return "", err
- }
- return tmpfile.Name(), nil
-}
-
-// 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("Getting key identity: %s", err)
- return nil
- }
- return 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
- }
- tmpfileName, err := CreateTmpFile("", "", decodeKey)
- if err != nil {
- logrus.Errorf("Creating key date temp file %s", err)
- }
- defer os.Remove(tmpfileName)
- return GetGPGIdFromKeyPath(tmpfileName)
-}
-
-func parseUids(colonDelimitKeys []byte) []string {
- var parseduids []string
- scanner := bufio.NewScanner(bytes.NewReader(colonDelimitKeys))
- for scanner.Scan() {
- line := scanner.Text()
- if strings.HasPrefix(line, "uid:") || strings.HasPrefix(line, "pub:") {
- uid := strings.Split(line, ":")[9]
- if uid == "" {
- continue
- }
- parseduid := uid
- if strings.Contains(uid, "<") && strings.Contains(uid, ">") {
- parseduid = strings.SplitN(strings.SplitAfterN(uid, "<", 2)[1], ">", 2)[0]
- }
- parseduids = append(parseduids, parseduid)
- }
- }
- return parseduids
-}
-
-// 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 policyContentStruct, fmt.Errorf("unable to read policy file: %w", err)
- }
- if err := json.Unmarshal(policyContent, &policyContentStruct); err != nil {
- return policyContentStruct, fmt.Errorf("could not parse trust policies from %s: %w", policyPath, err)
- }
- return policyContentStruct, nil
+// Policy describes a basic trust policy configuration
+type Policy struct {
+ Transport string `json:"transport"`
+ Name string `json:"name,omitempty"`
+ RepoName string `json:"repo_name,omitempty"`
+ Keys []string `json:"keys,omitempty"`
+ SignatureStore string `json:"sigstore,omitempty"`
+ Type string `json:"type"`
+ GPGId string `json:"gpg_id,omitempty"`
}