Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions common/pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -488,11 +488,6 @@ type EngineConfig struct {
// backwards compat with older version of libpod and Podman.
SetOptions

// SignaturePolicyPath is the path to a signature policy to use for
// validating images. If left empty, the containers/image default signature
// policy will be used.
SignaturePolicyPath string `toml:"-"`

// SDNotify tells container engine to allow containers to notify the host systemd of
// readiness using the SD_NOTIFY mechanism.
SDNotify bool `toml:"-"`
Expand Down
6 changes: 0 additions & 6 deletions common/pkg/config/config_bsd.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,6 @@

package config

const (
// DefaultSignaturePolicyPath is the default value for the
// policy.json file.
DefaultSignaturePolicyPath = "/usr/local/etc/containers/policy.json"
)

var defaultHelperBinariesDir = []string{
"/usr/local/bin",
"/usr/local/libexec/podman",
Expand Down
6 changes: 0 additions & 6 deletions common/pkg/config/config_darwin.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,5 @@
package config

const (
// DefaultSignaturePolicyPath is the default value for the
// policy.json file.
DefaultSignaturePolicyPath = "/etc/containers/policy.json"
)

var defaultHelperBinariesDir = []string{
// Relative to the binary directory
"$BINDIR/../libexec/podman",
Expand Down
6 changes: 0 additions & 6 deletions common/pkg/config/config_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,6 @@ import (
"go.podman.io/common/pkg/capabilities"
)

const (
// DefaultSignaturePolicyPath is the default value for the
// policy.json file.
DefaultSignaturePolicyPath = "/etc/containers/policy.json"
)

func selinuxEnabled() bool {
return selinux.GetEnabled()
}
Expand Down
4 changes: 0 additions & 4 deletions common/pkg/config/config_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,6 @@ import (
)

const (
// DefaultSignaturePolicyPath is the default value for the
// policy.json file.
DefaultSignaturePolicyPath = "/etc/containers/policy.json"

// Mount type for mounting host dir
_typeBind = "bind"
)
Expand Down
21 changes: 0 additions & 21 deletions common/pkg/config/default.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import (
nettypes "go.podman.io/common/libnetwork/types"
"go.podman.io/common/pkg/apparmor"
"go.podman.io/storage/pkg/configfile"
"go.podman.io/storage/pkg/fileutils"
"go.podman.io/storage/pkg/homedir"
"go.podman.io/storage/pkg/unshare"
"go.podman.io/storage/types"
Expand Down Expand Up @@ -177,9 +176,6 @@ const (
// DefaultSubnet is the subnet that will be used for the default
// network.
DefaultSubnet = "10.88.0.0/16"
// DefaultRootlessSignaturePolicyPath is the location within
// XDG_CONFIG_HOME of the rootless policy.json file.
DefaultRootlessSignaturePolicyPath = "containers/policy.json"
// DefaultShmSize is the default upper limit on the size of tmpfs mounts.
DefaultShmSize = "65536k"
// DefaultUserNSSize indicates the default number of UIDs allocated for user namespace within a container.
Expand All @@ -205,23 +201,6 @@ func defaultConfig() (*Config, error) {
return nil, err
}

defaultEngineConfig.SignaturePolicyPath = DefaultSignaturePolicyPath
// NOTE: For now we want Windows to use system locations.
// GetRootlessUID == -1 on Windows, so exclude negative range
if unshare.GetRootlessUID() > 0 {
configHome, err := homedir.GetConfigHome()
if err != nil {
return nil, err
}
sigPath := filepath.Join(configHome, DefaultRootlessSignaturePolicyPath)
defaultEngineConfig.SignaturePolicyPath = sigPath
if err := fileutils.Exists(sigPath); err != nil {
if err := fileutils.Exists(DefaultSignaturePolicyPath); err == nil {
defaultEngineConfig.SignaturePolicyPath = DefaultSignaturePolicyPath
}
}
}

return &Config{
Containers: ContainersConfig{
Annotations: configfile.Slice{},
Expand Down
121 changes: 63 additions & 58 deletions image/docker/registries_d.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package docker
import (
"errors"
"fmt"
"io"
"io/fs"
"net/url"
"os"
Expand All @@ -15,30 +16,19 @@ import (
"go.podman.io/image/v5/docker/reference"
"go.podman.io/image/v5/internal/rootless"
"go.podman.io/image/v5/types"
"go.podman.io/storage/pkg/fileutils"
"go.podman.io/storage/pkg/configfile"
"go.podman.io/storage/pkg/homedir"
"go.podman.io/storage/pkg/unshare"
"gopkg.in/yaml.v3"
)

// systemRegistriesDirPath is the path to registries.d, used for locating lookaside Docker signature storage.
// You can override this at build time with
// -ldflags '-X go.podman.io/image/v5/docker.systemRegistriesDirPath=$your_path'
var systemRegistriesDirPath = builtinRegistriesDirPath

// builtinRegistriesDirPath is the path to registries.d.
// DO NOT change this, instead see systemRegistriesDirPath above.
const builtinRegistriesDirPath = etcDir + "/containers/registries.d"

// userRegistriesDirPath is the path to the per user registries.d.
var userRegistriesDir = filepath.FromSlash(".config/containers/registries.d")

// defaultUserDockerDir is the default lookaside directory for unprivileged user
var defaultUserDockerDir = filepath.FromSlash(".local/share/containers/sigstore")

// defaultDockerDir is the default lookaside directory for root
var defaultDockerDir = "/var/lib/containers/sigstore"

// registryConfiguration is one of the files in registriesDirPath configuring lookaside locations, or the result of merging them all.
// registryConfiguration is one of the registries signature storage YAML fragments, or the result of merging them all.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The files are not documented to be purely for signature-related items.

// NOTE: Keep this in sync with docs/registries.d.md!
type registryConfiguration struct {
DefaultDocker *registryNamespace `yaml:"default-docker"`
Expand Down Expand Up @@ -78,31 +68,40 @@ func SignatureStorageBaseURL(sys *types.SystemContext, ref types.ImageReference,

// loadRegistryConfiguration returns a registryConfiguration appropriate for sys.
func loadRegistryConfiguration(sys *types.SystemContext) (*registryConfiguration, error) {
dirPath := registriesDirPath(sys)
logrus.Debugf(`Using registries.d directory %s`, dirPath)
return loadAndMergeConfig(dirPath)
}

// registriesDirPath returns a path to registries.d
func registriesDirPath(sys *types.SystemContext) string {
return registriesDirPathWithHomeDir(sys, homedir.Get())
}

// registriesDirPathWithHomeDir is an internal implementation detail of registriesDirPath,
// it exists only to allow testing it with an artificial home directory.
func registriesDirPathWithHomeDir(sys *types.SystemContext, homeDir string) string {
if sys != nil && sys.RegistriesDirPath != "" {
return sys.RegistriesDirPath
logrus.Debugf(`Using registries.d directory %s`, sys.RegistriesDirPath)
return loadAndMergeConfig(sys.RegistriesDirPath)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At a glance, this separate implementation is fairly unsatisfactory.

One approach might be to extend configfile yet again, to support “read exactly this directory and nothing else”. Another would be to have a directory enumerator that returns the same iterator as configfile.Read (whether that enumerator exists in this package or as a configfile.ReadInSingleDirectory). Then the iteration+merging loop would exist just once.

}
userRegistriesDirPath := filepath.Join(homeDir, userRegistriesDir)
if err := fileutils.Exists(userRegistriesDirPath); err == nil {
return userRegistriesDirPath
var rootForImplicitAbsPaths string
if sys != nil {
rootForImplicitAbsPaths = sys.RootForImplicitAbsolutePaths
}
if sys != nil && sys.RootForImplicitAbsolutePaths != "" {
return filepath.Join(sys.RootForImplicitAbsolutePaths, systemRegistriesDirPath)
registriesFiles := configfile.File{
Name: "registries",
Extension: "yaml",
DoNotLoadMainFiles: true,
DoNotUseExtensionForConfigName: true,
RootForImplicitAbsolutePaths: rootForImplicitAbsPaths,
UserId: unshare.GetRootlessUID(),
ErrorIfNotFound: false,
}

return systemRegistriesDirPath
mergedConfig := registryConfiguration{Docker: map[string]registryNamespace{}}
dockerDefaultMergedFrom := ""
nsMergedFrom := map[string]string{}
for item, err := range configfile.Read(&registriesFiles) {
if err != nil {
return nil, err
}
contents, err := io.ReadAll(item.Reader)
if err != nil {
return nil, err
}
logrus.Debugf(`Reading registries signature storage configuration from %q`, item.Name)
if err := mergeRegistriesYAMLFragment(&mergedConfig, item.Name, contents, &dockerDefaultMergedFrom, nsMergedFrom); err != nil {
return nil, err
}
}
return &mergedConfig, nil
}

// loadAndMergeConfig loads configuration files in dirPath
Expand All @@ -119,6 +118,7 @@ func loadAndMergeConfig(dirPath string) (*registryConfiguration, error) {
}
return nil, err
}
defer dir.Close()
configNames, err := dir.Readdirnames(0)
if err != nil {
return nil, err
Expand All @@ -131,39 +131,44 @@ func loadAndMergeConfig(dirPath string) (*registryConfiguration, error) {
configBytes, err := os.ReadFile(configPath)
if err != nil {
if errors.Is(err, fs.ErrNotExist) {
// file must have been removed between the directory listing
// and the open call, ignore that as it is a expected race
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is non-obvious enough to be worth preserving the comment.

continue
}
return nil, err
}

var config registryConfiguration
err = yaml.Unmarshal(configBytes, &config)
if err != nil {
return nil, fmt.Errorf("parsing %s: %w", configPath, err)
if err := mergeRegistriesYAMLFragment(&mergedConfig, configPath, configBytes, &dockerDefaultMergedFrom, nsMergedFrom); err != nil {
return nil, err
}
}

if config.DefaultDocker != nil {
if mergedConfig.DefaultDocker != nil {
return nil, fmt.Errorf(`Error parsing signature storage configuration: "default-docker" defined both in %q and %q`,
dockerDefaultMergedFrom, configPath)
}
mergedConfig.DefaultDocker = config.DefaultDocker
dockerDefaultMergedFrom = configPath
}
return &mergedConfig, nil
}

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 %q defined both in %q and %q`,
nsName, nsMergedFrom[nsName], configPath)
}
mergedConfig.Docker[nsName] = nsConfig
nsMergedFrom[nsName] = configPath
// mergeRegistriesYAMLFragment parses configBytes as a single registries.d YAML fragment and merges it into merged.
func mergeRegistriesYAMLFragment(merged *registryConfiguration, configPath string, configBytes []byte, dockerDefaultMergedFrom *string, nsMergedFrom map[string]string) error {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Non-blocking: This works, but I think defining an object to hold the merging state, with new / mergeFragment / mergedConfig methods would be cleaner. But see elsewhere, do we need this split at all?)

var config registryConfiguration
err := yaml.Unmarshal(configBytes, &config)
if err != nil {
return fmt.Errorf("parsing %s: %w", configPath, err)
}

if config.DefaultDocker != nil {
if merged.DefaultDocker != nil {
return fmt.Errorf(`Error parsing signature storage configuration: "default-docker" defined both in %q and %q`,
*dockerDefaultMergedFrom, configPath)
}
merged.DefaultDocker = config.DefaultDocker
*dockerDefaultMergedFrom = configPath
}

return &mergedConfig, nil
for nsName, nsConfig := range config.Docker {
if _, ok := merged.Docker[nsName]; ok {
return fmt.Errorf(`Error parsing signature storage configuration: "docker" namespace %q defined both in %q and %q`,
nsName, nsMergedFrom[nsName], configPath)
}
merged.Docker[nsName] = nsConfig
nsMergedFrom[nsName] = configPath
}
return nil
}

// lookasideStorageBaseURL returns an appropriate signature storage URL for ref, for write access if “write”.
Expand Down
Loading
Loading