Merge pull request #49612 from thaJeztah/registry_deprecate_SetCertsDir

registry: deprecate SetCertsDir, HostCertsDir
This commit is contained in:
Sebastiaan van Stijn
2025-03-10 20:56:28 +01:00
committed by GitHub
4 changed files with 56 additions and 36 deletions

View File

@@ -4,13 +4,9 @@ package main
import (
"net"
"path/filepath"
"github.com/docker/docker/daemon/config"
"github.com/docker/docker/opts"
"github.com/docker/docker/pkg/homedir"
"github.com/docker/docker/pkg/rootless"
"github.com/docker/docker/registry"
"github.com/spf13/pflag"
)
@@ -59,14 +55,3 @@ func installConfigFlags(conf *config.Config, flags *pflag.FlagSet) {
flags.BoolVar(&conf.Rootless, "rootless", conf.Rootless, "Enable rootless mode; typically used with RootlessKit")
flags.StringVar(&conf.CgroupNamespaceMode, "default-cgroupns-mode", conf.CgroupNamespaceMode, `Default mode for containers cgroup namespace ("host" | "private")`)
}
// configureCertsDir configures registry.CertsDir() depending on if the daemon
// is running in rootless mode or not.
func configureCertsDir() {
if rootless.RunningWithRootlessKit() {
configHome, err := homedir.GetConfigHome()
if err == nil {
registry.SetCertsDir(filepath.Join(configHome, "docker/certs.d"))
}
}
}

View File

@@ -79,7 +79,6 @@ func newDaemonCommand() (*cobra.Command, error) {
flags := cmd.Flags()
flags.BoolP("version", "v", false, "Print version information and quit")
flags.StringVar(&opts.configFile, "config-file", opts.configFile, "Daemon configuration file")
configureCertsDir()
opts.installFlags(flags)
installConfigFlags(opts.daemonConfig, flags)
installServiceFlags(flags)

View File

@@ -4,13 +4,17 @@ import (
"context"
"net"
"net/url"
"os"
"path/filepath"
"strconv"
"strings"
"sync"
"github.com/containerd/log"
"github.com/distribution/reference"
"github.com/docker/docker/api/types/registry"
"github.com/docker/docker/internal/lazyregexp"
"github.com/docker/docker/pkg/homedir"
)
// ServiceOptions holds command line options.
@@ -58,23 +62,50 @@ var (
validHostPortRegex = lazyregexp.New(`^` + reference.DomainRegexp.String() + `$`)
// certsDir is used to override defaultCertsDir.
certsDir string
// certsDir is used to override defaultCertsDir when running with rootlessKit.
//
// TODO(thaJeztah): change to a sync.OnceValue once we remove [SetCertsDir]
// TODO(thaJeztah): certsDir should not be a package variable, but stored in our config, and passed when needed.
setCertsDirOnce sync.Once
certsDir string
)
func setCertsDir(dir string) string {
setCertsDirOnce.Do(func() {
if dir != "" {
certsDir = dir
return
}
if os.Getenv("ROOTLESSKIT_STATE_DIR") != "" {
// Configure registry.CertsDir() when running in rootless-mode
// This is the equivalent of [rootless.RunningWithRootlessKit],
// but inlining it to prevent adding that as a dependency
// for docker/cli.
//
// [rootless.RunningWithRootlessKit]: https://github.com/moby/moby/blob/b4bdf12daec84caaf809a639f923f7370d4926ad/pkg/rootless/rootless.go#L5-L8
if configHome, _ := homedir.GetConfigHome(); configHome != "" {
certsDir = filepath.Join(configHome, "docker/certs.d")
return
}
}
certsDir = defaultCertsDir
})
return certsDir
}
// SetCertsDir allows the default certs directory to be changed. This function
// is used at daemon startup to set the correct location when running in
// rootless mode.
//
// Deprecated: the cert-directory is now automatically selected when running with rootlessKit, and should no longer be set manually.
func SetCertsDir(path string) {
certsDir = path
setCertsDir(path)
}
// CertsDir is the directory where certificates are stored.
func CertsDir() string {
if certsDir != "" {
return certsDir
}
return defaultCertsDir
// call setCertsDir with an empty path to synchronise with [SetCertsDir]
return setCertsDir("")
}
// newServiceConfig returns a new instance of ServiceConfig

View File

@@ -8,7 +8,6 @@ import (
"net/http"
"os"
"path/filepath"
"strings"
"time"
"github.com/containerd/log"
@@ -18,7 +17,14 @@ import (
)
// HostCertsDir returns the config directory for a specific host.
//
// Deprecated: this function was only used internally, and will be removed in a future release.
func HostCertsDir(hostname string) string {
return hostCertsDir(hostname)
}
// hostCertsDir returns the config directory for a specific host.
func hostCertsDir(hostname string) string {
return filepath.Join(CertsDir(), cleanPath(hostname))
}
@@ -26,11 +32,10 @@ func HostCertsDir(hostname string) string {
func newTLSConfig(hostname string, isSecure bool) (*tls.Config, error) {
// PreferredServerCipherSuites should have no effect
tlsConfig := tlsconfig.ServerDefault()
tlsConfig.InsecureSkipVerify = !isSecure
if isSecure && CertsDir() != "" {
hostDir := HostCertsDir(hostname)
if isSecure {
hostDir := hostCertsDir(hostname)
log.G(context.TODO()).Debugf("hostDir: %s", hostDir)
if err := ReadCertsDirectory(tlsConfig, hostDir); err != nil {
return nil, err
@@ -59,7 +64,8 @@ func ReadCertsDirectory(tlsConfig *tls.Config, directory string) error {
}
for _, f := range fs {
if strings.HasSuffix(f.Name(), ".crt") {
switch filepath.Ext(f.Name()) {
case ".crt":
if tlsConfig.RootCAs == nil {
systemPool, err := tlsconfig.SystemCertPool()
if err != nil {
@@ -67,17 +73,17 @@ func ReadCertsDirectory(tlsConfig *tls.Config, directory string) error {
}
tlsConfig.RootCAs = systemPool
}
log.G(context.TODO()).Debugf("crt: %s", filepath.Join(directory, f.Name()))
data, err := os.ReadFile(filepath.Join(directory, f.Name()))
fileName := filepath.Join(directory, f.Name())
log.G(context.TODO()).Debugf("crt: %s", fileName)
data, err := os.ReadFile(fileName)
if err != nil {
return err
}
tlsConfig.RootCAs.AppendCertsFromPEM(data)
}
if strings.HasSuffix(f.Name(), ".cert") {
case ".cert":
certName := f.Name()
keyName := certName[:len(certName)-5] + ".key"
log.G(context.TODO()).Debugf("cert: %s", filepath.Join(directory, f.Name()))
log.G(context.TODO()).Debugf("cert: %s", filepath.Join(directory, certName))
if !hasFile(fs, keyName) {
return invalidParamf("missing key %s for client certificate %s. CA certificates must use the extension .crt", keyName, certName)
}
@@ -86,11 +92,10 @@ func ReadCertsDirectory(tlsConfig *tls.Config, directory string) error {
return err
}
tlsConfig.Certificates = append(tlsConfig.Certificates, cert)
}
if strings.HasSuffix(f.Name(), ".key") {
case ".key":
keyName := f.Name()
certName := keyName[:len(keyName)-4] + ".cert"
log.G(context.TODO()).Debugf("key: %s", filepath.Join(directory, f.Name()))
log.G(context.TODO()).Debugf("key: %s", filepath.Join(directory, keyName))
if !hasFile(fs, certName) {
return invalidParamf("missing client certificate %s for key %s", certName, keyName)
}