From b8ccdcb07dfcb8b8db691da28122e5ada880645c Mon Sep 17 00:00:00 2001 From: John Millikin Date: Tue, 26 May 2020 12:08:21 +0900 Subject: [PATCH] Add `ctr` flags for configuring default TLS credentials. Signed-off-by: John Millikin --- cmd/ctr/commands/commands.go | 12 ++++++++++ cmd/ctr/commands/resolver.go | 46 ++++++++++++++++++++++++++++++++---- 2 files changed, 53 insertions(+), 5 deletions(-) diff --git a/cmd/ctr/commands/commands.go b/cmd/ctr/commands/commands.go index 86202414e..9156b0b13 100644 --- a/cmd/ctr/commands/commands.go +++ b/cmd/ctr/commands/commands.go @@ -66,6 +66,18 @@ var ( // compatible with "/etc/docker/certs.d" Usage: "Custom hosts configuration directory", }, + cli.StringFlag{ + Name: "tlscacert", + Usage: "path to TLS root CA", + }, + cli.StringFlag{ + Name: "tlscert", + Usage: "path to TLS client certificate", + }, + cli.StringFlag{ + Name: "tlskey", + Usage: "path to TLS client key", + }, } // ContainerFlags are cli flags specifying container options diff --git a/cmd/ctr/commands/resolver.go b/cmd/ctr/commands/resolver.go index bb394625e..bc6f97be0 100644 --- a/cmd/ctr/commands/resolver.go +++ b/cmd/ctr/commands/resolver.go @@ -20,7 +20,9 @@ import ( "bufio" gocontext "context" "crypto/tls" + "crypto/x509" "fmt" + "io/ioutil" "strings" "github.com/containerd/console" @@ -85,12 +87,11 @@ func GetResolver(ctx gocontext.Context, clicontext *cli.Context) (remotes.Resolv if clicontext.Bool("plain-http") { hostOptions.DefaultScheme = "http" } - - if clicontext.Bool("skip-verify") { - hostOptions.DefaultTLS = &tls.Config{ - InsecureSkipVerify: true, - } + defaultTLS, err := resolverDefaultTLS(clicontext) + if err != nil { + return nil, err } + hostOptions.DefaultTLS = defaultTLS if hostDir := clicontext.String("hosts-dir"); hostDir != "" { hostOptions.HostDir = config.HostDirFromRoot(hostDir) } @@ -99,3 +100,38 @@ func GetResolver(ctx gocontext.Context, clicontext *cli.Context) (remotes.Resolv return docker.NewResolver(options), nil } + +func resolverDefaultTLS(clicontext *cli.Context) (*tls.Config, error) { + config := &tls.Config{} + + if clicontext.Bool("skip-verify") { + config.InsecureSkipVerify = true + } + + if tlsRootPath := clicontext.String("tlscacert"); tlsRootPath != "" { + tlsRootData, err := ioutil.ReadFile(tlsRootPath) + if err != nil { + return nil, errors.Wrapf(err, "failed to read %q", tlsRootPath) + } + + config.RootCAs = x509.NewCertPool() + if !config.RootCAs.AppendCertsFromPEM(tlsRootData) { + return nil, fmt.Errorf("failed to load TLS CAs from %q: invalid data", tlsRootPath) + } + } + + tlsCertPath := clicontext.String("tlscert") + tlsKeyPath := clicontext.String("tlskey") + if tlsCertPath != "" || tlsKeyPath != "" { + if tlsCertPath == "" || tlsKeyPath == "" { + return nil, errors.New("flags --tlscert and --tlskey must be set together") + } + keyPair, err := tls.LoadX509KeyPair(tlsCertPath, tlsKeyPath) + if err != nil { + return nil, errors.Wrapf(err, "failed to load TLS client credentials (cert=%q, key=%q)", tlsCertPath, tlsKeyPath) + } + config.Certificates = []tls.Certificate{keyPair} + } + + return config, nil +}