mirror of
https://github.com/containers/podman.git
synced 2025-05-21 09:05:56 +08:00
127 lines
4.3 KiB
Go
127 lines
4.3 KiB
Go
package trust
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"github.com/containers/image/v5/types"
|
|
"github.com/containers/storage/pkg/fileutils"
|
|
"github.com/docker/docker/pkg/homedir"
|
|
"sigs.k8s.io/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 := fileutils.Exists(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
|
|
}
|