mirror of https://github.com/containers/podman.git
				
				
				
			
		
			
				
	
	
		
			126 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			126 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			Go
		
	
	
	
| package trust
 | |
| 
 | |
| import (
 | |
| 	"fmt"
 | |
| 	"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 {
 | |
| 	Lookaside        string `json:"lookaside"`         // For reading, and if LookasideStaging is not present, for writing.
 | |
| 	LookasideStaging string `json:"lookaside-staging"` // For writing only.
 | |
| 	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 registries.d 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 := os.ReadFile(configPath)
 | |
| 		if err != nil {
 | |
| 			return nil, err
 | |
| 		}
 | |
| 		var config registryConfiguration
 | |
| 		err = yaml.Unmarshal(configBytes, &config)
 | |
| 		if err != nil {
 | |
| 			return nil, fmt.Errorf("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
 | |
| }
 | |
| 
 | |
| // registriesDConfigurationForScope returns registries.d configuration for the provided scope.
 | |
| // scope can be "" to return only the global default configuration entry.
 | |
| func registriesDConfigurationForScope(registryConfigs *registryConfiguration, scope string) *registryNamespace {
 | |
| 	searchScope := scope
 | |
| 	if searchScope != "" {
 | |
| 		if !strings.Contains(searchScope, "/") {
 | |
| 			val, exists := registryConfigs.Docker[searchScope]
 | |
| 			if exists {
 | |
| 				return &val
 | |
| 			}
 | |
| 		}
 | |
| 		for range strings.Split(scope, "/") {
 | |
| 			val, exists := registryConfigs.Docker[searchScope]
 | |
| 			if exists {
 | |
| 				return &val
 | |
| 			}
 | |
| 			if strings.Contains(searchScope, "/") {
 | |
| 				searchScope = searchScope[:strings.LastIndex(searchScope, "/")]
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 	return registryConfigs.DefaultDocker
 | |
| }
 |