Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

resolver: support self signed certificates #1410

Merged
merged 1 commit into from
Mar 18, 2020
Merged
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
31 changes: 31 additions & 0 deletions cmd/buildkitd/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package main

import (
"io"
"os"

"github.com/BurntSushi/toml"
"github.com/moby/buildkit/cmd/buildkitd/config"
"github.com/pkg/errors"
)

func Load(r io.Reader) (config.Config, *toml.MetaData, error) {
var c config.Config
md, err := toml.DecodeReader(r, &c)
if err != nil {
return c, nil, errors.Wrap(err, "failed to parse config")
}
return c, &md, nil
}

func LoadFile(fp string) (config.Config, *toml.MetaData, error) {
f, err := os.Open(fp)
if err != nil {
if os.IsNotExist(err) {
return config.Config{}, nil, nil
}
return config.Config{}, nil, errors.Wrapf(err, "failed to load config from %s", fp)
}
defer f.Close()
return Load(f)
}
43 changes: 11 additions & 32 deletions cmd/buildkitd/config/config.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,5 @@
package config

import (
"io"
"os"

"github.com/BurntSushi/toml"
"github.com/pkg/errors"
)

// Config provides containerd configuration data for the server
type Config struct {
Debug bool `toml:"debug"`
Expand Down Expand Up @@ -42,9 +34,17 @@ type GRPCConfig struct {
}

type RegistryConfig struct {
Mirrors []string `toml:"mirrors"`
PlainHTTP *bool `toml:"http"`
Insecure *bool `toml:"insecure"`
Mirrors []string `toml:"mirrors"`
PlainHTTP *bool `toml:"http"`
Insecure *bool `toml:"insecure"`
RootCAs []string `toml:"ca"`
KeyPairs []TLSKeyPair `toml:"keypair"`
Copy link
Member

Choose a reason for hiding this comment

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

toml:"keypairs" ?

Copy link
Member Author

Choose a reason for hiding this comment

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

All of them are arrays really 🤷‍♂

Copy link
Member Author

Choose a reason for hiding this comment

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

Looking at the toml it actually makes more sense to keep it singular for complex types because they need to be defined one-by-one and plural for simple types. Already quite a mess though.

TLSConfigDir []string `toml:"tlsconfigdir"`
}

type TLSKeyPair struct {
Key string `toml:"key"`
Certificate string `toml:"cert"`
}

type TLSConfig struct {
Expand Down Expand Up @@ -103,24 +103,3 @@ type DNSConfig struct {
Options []string `toml:"options"`
SearchDomains []string `toml:"searchDomains"`
}

func Load(r io.Reader) (Config, *toml.MetaData, error) {
var c Config
md, err := toml.DecodeReader(r, &c)
if err != nil {
return c, nil, errors.Wrap(err, "failed to parse config")
}
return c, &md, nil
}

func LoadFile(fp string) (Config, *toml.MetaData, error) {
f, err := os.Open(fp)
if err != nil {
if os.IsNotExist(err) {
return Config{}, nil, nil
}
return Config{}, nil, errors.Wrapf(err, "failed to load config from %s", fp)
}
defer f.Close()
return Load(f)
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package config
package main

import (
"bytes"
Expand Down Expand Up @@ -51,6 +51,12 @@ keepDuration=7200
[registry."docker.io"]
mirrors=["hub.docker.io"]
http=true
insecure=true
ca=["myca.pem"]
tlsconfigdir=["/etc/buildkitd/myregistry"]
[[registry."docker.io".keypair]]
key="key.pem"
cert="cert.pem"

[dns]
nameservers=["1.1.1.1","8.8.8.8"]
Expand Down Expand Up @@ -102,7 +108,12 @@ searchDomains=["example.com"]
require.Equal(t, 0, len(cfg.Workers.Containerd.GCPolicy[1].Filters))

require.Equal(t, *cfg.Registries["docker.io"].PlainHTTP, true)
require.Equal(t, *cfg.Registries["docker.io"].Insecure, true)
require.Equal(t, cfg.Registries["docker.io"].Mirrors[0], "hub.docker.io")
require.Equal(t, cfg.Registries["docker.io"].RootCAs, []string{"myca.pem"})
require.Equal(t, cfg.Registries["docker.io"].TLSConfigDir, []string{"/etc/buildkitd/myregistry"})
require.Equal(t, cfg.Registries["docker.io"].KeyPairs[0].Key, "key.pem")
require.Equal(t, cfg.Registries["docker.io"].KeyPairs[0].Certificate, "cert.pem")

require.NotNil(t, cfg.DNS)
require.Equal(t, cfg.DNS.Nameservers, []string{"1.1.1.1", "8.8.8.8"})
Expand Down
14 changes: 3 additions & 11 deletions cmd/buildkitd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ func main() {
ctx, cancel := context.WithCancel(appcontext.Context())
defer cancel()

cfg, md, err := config.LoadFile(c.GlobalString("config"))
cfg, md, err := LoadFile(c.GlobalString("config"))
if err != nil {
return err
}
Expand Down Expand Up @@ -337,7 +337,7 @@ func defaultConfigPath() string {
}

func defaultConf() (config.Config, *toml.MetaData, error) {
cfg, md, err := config.LoadFile(defaultConfigPath())
cfg, md, err := LoadFile(defaultConfigPath())
if err != nil {
if _, ok := errors.Cause(err).(*os.PathError); !ok {
return config.Config{}, nil, err
Expand Down Expand Up @@ -621,15 +621,7 @@ func newController(c *cli.Context, cfg *config.Config) (*control.Controller, err
}

func resolverFunc(cfg *config.Config) docker.RegistryHosts {
m := map[string]resolver.RegistryConf{}
for k, v := range cfg.Registries {
m[k] = resolver.RegistryConf{
Mirrors: v.Mirrors,
PlainHTTP: v.PlainHTTP,
Insecure: v.Insecure,
}
}
return resolver.NewRegistryConfig(m)
return resolver.NewRegistryConfig(cfg.Registries)
}

func newWorkerController(c *cli.Context, wiOpt workerInitializerOpt) (*worker.Controller, error) {
Expand Down
5 changes: 5 additions & 0 deletions docs/buildkitd.toml.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,4 +83,9 @@ insecure-entitlements = [ "network.host", "security.insecure" ]
[registry."docker.io"]
mirrors = ["hub.docker.io"]
http = true
insecure = true
ca=["/etc/config/myca.pem"]
[[registry."docker.io".keypair]]
key="/etc/config/key.pem"
cert="/etc/config/cert.pem"
```
100 changes: 89 additions & 11 deletions util/resolver/resolver.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,37 +3,109 @@ package resolver
import (
"context"
"crypto/tls"
"crypto/x509"
"io/ioutil"
"net/http"
"os"
"path/filepath"
"runtime"
"strings"
"time"

"github.com/containerd/containerd/remotes"
"github.com/containerd/containerd/remotes/docker"
"github.com/moby/buildkit/cmd/buildkitd/config"
"github.com/moby/buildkit/session"
"github.com/moby/buildkit/session/auth"
"github.com/moby/buildkit/util/tracing"
"github.com/pkg/errors"
)

type RegistryConf struct {
Mirrors []string
PlainHTTP *bool
Insecure *bool
}
func fillInsecureOpts(host string, c config.RegistryConfig, h *docker.RegistryHost) error {
tc, err := loadTLSConfig(c)
if err != nil {
return err
}

func fillInsecureOpts(host string, c RegistryConf, h *docker.RegistryHost) {
if c.PlainHTTP != nil && *c.PlainHTTP {
h.Scheme = "http"
} else if c.Insecure != nil && *c.Insecure {
h.Client = &http.Client{
Transport: tracing.NewTransport(&http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: true}}),
if tc == nil {
tc = &tls.Config{}
}
tc.InsecureSkipVerify = true
} else if c.PlainHTTP == nil {
if ok, _ := docker.MatchLocalhost(host); ok {
h.Scheme = "http"
}
}

if tc != nil && h.Scheme != "http" {
h.Client = &http.Client{
Transport: tracing.NewTransport(&http.Transport{TLSClientConfig: tc}),
}
}

return nil
}

func NewRegistryConfig(m map[string]RegistryConf) docker.RegistryHosts {
func loadTLSConfig(c config.RegistryConfig) (*tls.Config, error) {
for _, d := range c.TLSConfigDir {
fs, err := ioutil.ReadDir(d)
if err != nil && !os.IsNotExist(err) && !os.IsPermission(err) {
return nil, errors.WithStack(err)
}
for _, f := range fs {
if strings.HasSuffix(f.Name(), ".crt") {
c.RootCAs = append(c.RootCAs, filepath.Join(d, f.Name()))
}
if strings.HasSuffix(f.Name(), ".cert") {
c.KeyPairs = append(c.KeyPairs, config.TLSKeyPair{
Certificate: filepath.Join(d, f.Name()),
Key: filepath.Join(d, strings.TrimSuffix(f.Name(), ".cert")+".key"),
})
tonistiigi marked this conversation as resolved.
Show resolved Hide resolved
}
}
}

var tc *tls.Config

if len(c.RootCAs) > 0 {
tc = &tls.Config{}
systemPool, err := x509.SystemCertPool()
if err != nil {
tonistiigi marked this conversation as resolved.
Show resolved Hide resolved
if runtime.GOOS == "windows" {
systemPool = x509.NewCertPool()
} else {
return nil, errors.Wrapf(err, "unable to get system cert pool")
}
}
tc.RootCAs = systemPool
}

for _, p := range c.RootCAs {
dt, err := ioutil.ReadFile(p)
if err != nil {
return nil, errors.Wrapf(err, "failed to read %s", p)
}
tc.RootCAs.AppendCertsFromPEM(dt)
}

for _, kp := range c.KeyPairs {
cert, err := tls.LoadX509KeyPair(kp.Certificate, kp.Key)
if err != nil {
return nil, errors.Wrapf(err, "failed to load keypair for %s", kp.Certificate)
}
if tc == nil {
tc = &tls.Config{}
}
tc.Certificates = append(tc.Certificates, cert)
}

return tc, nil
}

func NewRegistryConfig(m map[string]config.RegistryConfig) docker.RegistryHosts {
return docker.Registries(
func(host string) ([]docker.RegistryHost, error) {
c, ok := m[host]
Expand All @@ -51,7 +123,10 @@ func NewRegistryConfig(m map[string]RegistryConf) docker.RegistryHosts {
Path: "/v2",
Capabilities: docker.HostCapabilityPull | docker.HostCapabilityResolve,
}
fillInsecureOpts(mirror, m[mirror], &h)

if err := fillInsecureOpts(mirror, m[mirror], &h); err != nil {
return nil, err
}

out = append(out, h)
}
Expand All @@ -67,7 +142,10 @@ func NewRegistryConfig(m map[string]RegistryConf) docker.RegistryHosts {
Path: "/v2",
Capabilities: docker.HostCapabilityPush | docker.HostCapabilityPull | docker.HostCapabilityResolve,
}
fillInsecureOpts(host, c, &h)

if err := fillInsecureOpts(host, c, &h); err != nil {
return nil, err
}

out = append(out, h)
return out, nil
Expand Down