support loading certs from a directory
Add `remotes/certutil` functions for loading `ca.crt`, `client.cert`, and `client.key` into `tls.Config` from a directory like `/etc/docker/certs.d/<hostname>. See https://docs.docker.com/engine/security/certificates/ . Client applications including CRI plugin are expected to configure the resolver using these functions. As an example, the `ctr` tool is extended to support `ctr images pull --certs-dir=/etc/docker/certs.d example.com/foo/bar:baz`. Tested with Harbor 1.8. Signed-off-by: Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp>
This commit is contained in:

committed by
Derek McGowan

parent
e852da5855
commit
dc131aa862
@@ -61,6 +61,11 @@ var (
|
||||
Name: "refresh",
|
||||
Usage: "refresh token for authorization server",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "certs-dir",
|
||||
// compatible with "/etc/docker/certs.d"
|
||||
Usage: "custom certificates directory that contains \"<hostname>/{ca.crt, client.cert, client.key}\"",
|
||||
},
|
||||
}
|
||||
|
||||
// ContainerFlags are cli flags specifying container options
|
||||
|
@@ -21,15 +21,20 @@ import (
|
||||
gocontext "context"
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/containerd/console"
|
||||
"github.com/containerd/containerd/remotes"
|
||||
"github.com/containerd/containerd/remotes/certutil"
|
||||
"github.com/containerd/containerd/remotes/docker"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
@@ -94,6 +99,7 @@ func GetResolver(ctx gocontext.Context, clicontext *cli.Context) (remotes.Resolv
|
||||
},
|
||||
ExpectContinueTimeout: 5 * time.Second,
|
||||
}
|
||||
loadCertsDir(tr.TLSClientConfig, clicontext.String("certs-dir"))
|
||||
|
||||
options.Client = &http.Client{
|
||||
Transport: tr,
|
||||
@@ -108,3 +114,30 @@ func GetResolver(ctx gocontext.Context, clicontext *cli.Context) (remotes.Resolv
|
||||
|
||||
return docker.NewResolver(options), nil
|
||||
}
|
||||
|
||||
// loadCertsDir loads certs from certsDir like "/etc/docker/certs.d" .
|
||||
func loadCertsDir(config *tls.Config, certsDir string) {
|
||||
if certsDir == "" {
|
||||
return
|
||||
}
|
||||
fs, err := ioutil.ReadDir(certsDir)
|
||||
if err != nil && !os.IsNotExist(err) {
|
||||
logrus.WithError(err).Errorf("cannot read certs directory %q", certsDir)
|
||||
return
|
||||
}
|
||||
for _, f := range fs {
|
||||
if !f.IsDir() {
|
||||
continue
|
||||
}
|
||||
// TODO: skip loading if f.Name() is not valid FQDN/IP
|
||||
hostDir := filepath.Join(certsDir, f.Name())
|
||||
caCertGlob := filepath.Join(hostDir, "*.crt")
|
||||
if _, err = certutil.LoadCACerts(config, caCertGlob); err != nil {
|
||||
logrus.WithError(err).Errorf("cannot load certs from %q", caCertGlob)
|
||||
}
|
||||
keyGlob := filepath.Join(hostDir, "*.key")
|
||||
if _, _, err = certutil.LoadKeyPairs(config, keyGlob, certutil.DockerKeyPairCertLocator); err != nil {
|
||||
logrus.WithError(err).Errorf("cannot load key pairs from %q", keyGlob)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user