registry: ReadCertsDirectory: internalize, and pass context

- Split the implementation from the exported function (exported
  function is still used by the CLI for Docker Content Trust).
- Pass through context to allow handling context-cancellation
  once wired up in callers.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
Sebastiaan van Stijn
2025-03-28 17:17:37 +01:00
parent 11bf52e9e3
commit f158d2e809
3 changed files with 21 additions and 9 deletions

View File

@@ -29,15 +29,15 @@ func hostCertsDir(hostname string) string {
}
// newTLSConfig constructs a client TLS configuration based on server defaults
func newTLSConfig(hostname string, isSecure bool) (*tls.Config, error) {
func newTLSConfig(ctx context.Context, hostname string, isSecure bool) (*tls.Config, error) {
// PreferredServerCipherSuites should have no effect
tlsConfig := tlsconfig.ServerDefault()
tlsConfig.InsecureSkipVerify = !isSecure
if isSecure {
hostDir := hostCertsDir(hostname)
log.G(context.TODO()).Debugf("hostDir: %s", hostDir)
if err := ReadCertsDirectory(tlsConfig, hostDir); err != nil {
log.G(ctx).Debugf("hostDir: %s", hostDir)
if err := loadTLSConfig(ctx, hostDir, tlsConfig); err != nil {
return nil, err
}
}
@@ -58,6 +58,12 @@ func hasFile(files []os.DirEntry, name string) bool {
// including roots and certificate pairs and updates the
// provided TLS configuration.
func ReadCertsDirectory(tlsConfig *tls.Config, directory string) error {
return loadTLSConfig(context.TODO(), directory, tlsConfig)
}
// loadTLSConfig reads the directory for TLS certificates including roots and
// certificate pairs, and updates the provided TLS configuration.
func loadTLSConfig(ctx context.Context, directory string, tlsConfig *tls.Config) error {
fs, err := os.ReadDir(directory)
if err != nil {
if os.IsNotExist(err) {
@@ -67,6 +73,9 @@ func ReadCertsDirectory(tlsConfig *tls.Config, directory string) error {
}
for _, f := range fs {
if ctx.Err() != nil {
return ctx.Err()
}
switch filepath.Ext(f.Name()) {
case ".crt":
if tlsConfig.RootCAs == nil {
@@ -77,7 +86,7 @@ func ReadCertsDirectory(tlsConfig *tls.Config, directory string) error {
tlsConfig.RootCAs = systemPool
}
fileName := filepath.Join(directory, f.Name())
log.G(context.TODO()).Debugf("crt: %s", fileName)
log.G(ctx).Debugf("crt: %s", fileName)
data, err := os.ReadFile(fileName)
if err != nil {
return err
@@ -86,7 +95,7 @@ func ReadCertsDirectory(tlsConfig *tls.Config, directory string) error {
case ".cert":
certName := f.Name()
keyName := certName[:len(certName)-5] + ".key"
log.G(context.TODO()).Debugf("cert: %s", filepath.Join(directory, certName))
log.G(ctx).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)
}
@@ -98,7 +107,7 @@ func ReadCertsDirectory(tlsConfig *tls.Config, directory string) error {
case ".key":
keyName := f.Name()
certName := keyName[:len(keyName)-4] + ".cert"
log.G(context.TODO()).Debugf("key: %s", filepath.Join(directory, keyName))
log.G(ctx).Debugf("key: %s", filepath.Join(directory, keyName))
if !hasFile(fs, certName) {
return invalidParamf("missing client certificate %s for key %s", certName, keyName)
}

View File

@@ -32,7 +32,7 @@ type v1Endpoint struct {
// newV1Endpoint parses the given address to return a registry endpoint.
// TODO: remove. This is only used by search.
func newV1Endpoint(index *registry.IndexInfo, headers http.Header) (*v1Endpoint, error) {
tlsConfig, err := newTLSConfig(index.Name, index.Secure)
tlsConfig, err := newTLSConfig(context.TODO(), index.Name, index.Secure)
if err != nil {
return nil, err
}

View File

@@ -1,6 +1,7 @@
package registry // import "github.com/docker/docker/registry"
import (
"context"
"net/url"
"strings"
@@ -8,6 +9,7 @@ import (
)
func (s *Service) lookupV2Endpoints(hostname string, includeMirrors bool) ([]APIEndpoint, error) {
ctx := context.TODO()
var endpoints []APIEndpoint
if hostname == DefaultNamespace || hostname == IndexHostname {
if includeMirrors {
@@ -19,7 +21,8 @@ func (s *Service) lookupV2Endpoints(hostname string, includeMirrors bool) ([]API
if err != nil {
return nil, invalidParam(err)
}
mirrorTLSConfig, err := newTLSConfig(mirrorURL.Host, s.config.isSecureIndex(mirrorURL.Host))
// TODO(thaJeztah); this should all be memoized when loading the config. We're resolving mirrors and loading TLS config every time.
mirrorTLSConfig, err := newTLSConfig(ctx, mirrorURL.Host, s.config.isSecureIndex(mirrorURL.Host))
if err != nil {
return nil, err
}
@@ -39,7 +42,7 @@ func (s *Service) lookupV2Endpoints(hostname string, includeMirrors bool) ([]API
return endpoints, nil
}
tlsConfig, err := newTLSConfig(hostname, s.config.isSecureIndex(hostname))
tlsConfig, err := newTLSConfig(ctx, hostname, s.config.isSecureIndex(hostname))
if err != nil {
return nil, err
}