func (provider *Docker) createClient() (client.APIClient, error) { var httpClient *http.Client httpHeaders := map[string]string{ // FIXME(vdemeester) use version here O:) "User-Agent": "Traefik", } if provider.TLS != nil { tlsOptions := tlsconfig.Options{ CAFile: provider.TLS.CA, CertFile: provider.TLS.Cert, KeyFile: provider.TLS.Key, InsecureSkipVerify: provider.TLS.InsecureSkipVerify, } config, err := tlsconfig.Client(tlsOptions) if err != nil { return nil, err } tr := &http.Transport{ TLSClientConfig: config, } proto, addr, _, err := client.ParseHost(provider.Endpoint) if err != nil { return nil, err } sockets.ConfigureTransport(tr, proto, addr) httpClient = &http.Client{ Transport: tr, } } return client.NewClient(provider.Endpoint, DockerAPIVersion, httpClient, httpHeaders) }
// NewEngineAPIClient creates a new Docker engine API client func NewEngineAPIClient(config *api.DockerConfig) (*dockerapi.Client, error) { var httpClient *http.Client if config.UseTLS || config.TLSVerify { tlscOptions := tlsconfig.Options{ InsecureSkipVerify: !config.TLSVerify, } if _, err := os.Stat(config.CAFile); !os.IsNotExist(err) { tlscOptions.CAFile = config.CAFile } if _, err := os.Stat(config.CertFile); !os.IsNotExist(err) { tlscOptions.CertFile = config.CertFile } if _, err := os.Stat(config.KeyFile); !os.IsNotExist(err) { tlscOptions.KeyFile = config.KeyFile } tlsc, err := tlsconfig.Client(tlscOptions) if err != nil { return nil, err } httpClient = &http.Client{ Transport: &http.Transport{ TLSClientConfig: tlsc, }, } } return dockerapi.NewClient(config.Endpoint, os.Getenv("DOCKER_API_VERSION"), httpClient, nil) }
// NewEnvClient initializes a new API client based on environment variables. // Use DOCKER_HOST to set the url to the docker server. // Use DOCKER_API_VERSION to set the version of the API to reach, leave empty for latest. // Use DOCKER_CERT_PATH to load the tls certificates from. // Use DOCKER_TLS_VERIFY to enable or disable TLS verification, off by default. func NewEnvClient() (*Client, error) { var client *http.Client if dockerCertPath := os.Getenv("DOCKER_CERT_PATH"); dockerCertPath != "" { options := tlsconfig.Options{ CAFile: filepath.Join(dockerCertPath, "ca.pem"), CertFile: filepath.Join(dockerCertPath, "cert.pem"), KeyFile: filepath.Join(dockerCertPath, "key.pem"), InsecureSkipVerify: os.Getenv("DOCKER_TLS_VERIFY") == "", } tlsc, err := tlsconfig.Client(options) if err != nil { return nil, err } client = &http.Client{ Transport: &http.Transport{ TLSClientConfig: tlsc, }, } } host := os.Getenv("DOCKER_HOST") if host == "" { host = DefaultDockerHost } return NewClient(host, os.Getenv("DOCKER_API_VERSION"), client, nil) }
// OptionKVOpts function returns an option setter for kvstore options func OptionKVOpts(opts map[string]string) Option { return func(c *Config) { if opts["kv.cacertfile"] != "" && opts["kv.certfile"] != "" && opts["kv.keyfile"] != "" { log.Info("Option Initializing KV with TLS") tlsConfig, err := tlsconfig.Client(tlsconfig.Options{ CAFile: opts["kv.cacertfile"], CertFile: opts["kv.certfile"], KeyFile: opts["kv.keyfile"], }) if err != nil { log.Errorf("Unable to set up TLS: %s", err) return } if _, ok := c.Scopes[datastore.GlobalScope]; !ok { c.Scopes[datastore.GlobalScope] = &datastore.ScopeCfg{} } if c.Scopes[datastore.GlobalScope].Client.Config == nil { c.Scopes[datastore.GlobalScope].Client.Config = &store.Config{TLS: tlsConfig} } else { c.Scopes[datastore.GlobalScope].Client.Config.TLS = tlsConfig } // Workaround libkv/etcd bug for https c.Scopes[datastore.GlobalScope].Client.Config.ClientTLS = &store.ClientTLSConfig{ CACertFile: opts["kv.cacertfile"], CertFile: opts["kv.certfile"], KeyFile: opts["kv.keyfile"], } } else { log.Info("Option Initializing KV without TLS") } } }
// NewClient creates a new plugin client (http). func NewClient(addr string, tlsConfig tlsconfig.Options) (*Client, error) { tr := &http.Transport{} c, err := tlsconfig.Client(tlsConfig) if err != nil { return nil, err } tr.TLSClientConfig = c u, err := url.Parse(addr) if err != nil { return nil, err } socket := u.Host if socket == "" { // valid local socket addresses have the host empty. socket = u.Path } if err := sockets.ConfigureTransport(tr, u.Scheme, socket); err != nil { return nil, err } scheme := httpScheme(u) clientTransport := transport.NewHTTPTransport(tr, scheme, socket) return NewClientWithTransport(clientTransport), nil }
func newPlugin(dockerHost string) (*authzPlugin, error) { c, _ := tlsconfig.Client(tlsconfig.Options{InsecureSkipVerify: true}) client, err := dockerclient.NewDockerClient(dockerHost, c) if err != nil { return nil, err } aclsAPI = new(impl.ACLsBackDefaultImpl) return &authzPlugin{client: client}, nil }
func parseTLSConfig(cfg map[string]string) (*tls.Config, error) { _, skipVerify := cfg["syslog-tls-skip-verify"] opts := tlsconfig.Options{ CAFile: cfg["syslog-tls-ca-cert"], CertFile: cfg["syslog-tls-cert"], KeyFile: cfg["syslog-tls-key"], InsecureSkipVerify: skipVerify, } return tlsconfig.Client(opts) }
// Initialize is exported func (s *Discovery) Initialize(uris string, heartbeat time.Duration, ttl time.Duration, clusterOpts map[string]string) error { var ( parts = strings.SplitN(uris, "/", 2) addrs = strings.Split(parts[0], ",") err error ) // A custom prefix to the path can be optionally used. if len(parts) == 2 { s.prefix = parts[1] } s.heartbeat = heartbeat s.ttl = ttl // Use a custom path if specified in discovery options dpath := defaultDiscoveryPath if clusterOpts["kv.path"] != "" { dpath = clusterOpts["kv.path"] } s.path = path.Join(s.prefix, dpath) var config *store.Config if clusterOpts["kv.cacertfile"] != "" && clusterOpts["kv.certfile"] != "" && clusterOpts["kv.keyfile"] != "" { logrus.Info("Initializing discovery with TLS") tlsConfig, err := tlsconfig.Client(tlsconfig.Options{ CAFile: clusterOpts["kv.cacertfile"], CertFile: clusterOpts["kv.certfile"], KeyFile: clusterOpts["kv.keyfile"], }) if err != nil { return err } config = &store.Config{ // Set ClientTLS to trigger https (bug in libkv/etcd) ClientTLS: &store.ClientTLSConfig{ CACertFile: clusterOpts["kv.cacertfile"], CertFile: clusterOpts["kv.certfile"], KeyFile: clusterOpts["kv.keyfile"], }, // The actual TLS config that will be used TLS: tlsConfig, } } else { logrus.Info("Initializing discovery without TLS") } // Creates a new store, will ignore options given // if not supported by the chosen store s.store, err = libkv.NewStore(s.backend, addrs, config) return err }
// AdminConnection sets up an admin RethinkDB connection to the host (`host:port` format) // using the CA .pem file provided at path `caFile` func AdminConnection(tlsOpts tlsconfig.Options, host string) (*gorethink.Session, error) { logrus.Debugf("attempting to connect admin to host %s", host) t, err := tlsconfig.Client(tlsOpts) if err != nil { return nil, err } return gorethink.Connect( gorethink.ConnectOpts{ Address: host, TLSConfig: t, }, ) }
// NewClient creates a new plugin client (http). func NewClient(addr string, tlsConfig tlsconfig.Options) (*Client, error) { tr := &http.Transport{} c, err := tlsconfig.Client(tlsConfig) if err != nil { return nil, err } tr.TLSClientConfig = c protoAndAddr := strings.Split(addr, "://") ConfigureTCPTransport(tr, protoAndAddr[0], protoAndAddr[1]) return &Client{&http.Client{Transport: tr}, protoAndAddr[1]}, nil }
func newClientTransport(tlsOptions *tlsconfig.Options) (*http.Transport, error) { if tlsOptions == nil { return &http.Transport{}, nil } config, err := tlsconfig.Client(*tlsOptions) if err != nil { return nil, err } return &http.Transport{ TLSClientConfig: config, }, nil }
// UserConnection sets up a user RethinkDB connection to the host (`host:port` format) // using the CA .pem file provided at path `caFile`, using the provided username. func UserConnection(tlsOpts tlsconfig.Options, host, username, password string) (*gorethink.Session, error) { logrus.Debugf("attempting to connect user %s to host %s", username, host) t, err := tlsconfig.Client(tlsOpts) if err != nil { return nil, err } return gorethink.Connect( gorethink.ConnectOpts{ Address: host, TLSConfig: t, Username: username, Password: password, }, ) }
func (d *Daemon) getClientConfig() (*clientConfig, error) { var ( transport *http.Transport scheme string addr string proto string ) if d.UseDefaultTLSHost { option := &tlsconfig.Options{ CAFile: "fixtures/https/ca.pem", CertFile: "fixtures/https/client-cert.pem", KeyFile: "fixtures/https/client-key.pem", } tlsConfig, err := tlsconfig.Client(*option) if err != nil { return nil, err } transport = &http.Transport{ TLSClientConfig: tlsConfig, } addr = fmt.Sprintf("%s:%d", opts.DefaultHTTPHost, opts.DefaultTLSHTTPPort) scheme = "https" proto = "tcp" } else if d.UseDefaultHost { addr = opts.DefaultUnixSocket proto = "unix" scheme = "http" transport = &http.Transport{} } else { addr = d.sockPath() proto = "unix" scheme = "http" transport = &http.Transport{} } if err := sockets.ConfigureTransport(transport, proto, addr); err != nil { return nil, err } transport.DisableKeepAlives = true return &clientConfig{ transport: transport, scheme: scheme, addr: addr, }, nil }
// NewClient creates a new plugin client (http). func NewClient(addr string, tlsConfig tlsconfig.Options) (*Client, error) { tr := &http.Transport{} c, err := tlsconfig.Client(tlsConfig) if err != nil { return nil, err } tr.TLSClientConfig = c protoAndAddr := strings.Split(addr, "://") sockets.ConfigureTCPTransport(tr, protoAndAddr[0], protoAndAddr[1]) scheme := protoAndAddr[0] if scheme != "https" { scheme = "http" } return &Client{&http.Client{Transport: tr}, scheme, protoAndAddr[1]}, nil }
func getTLSConfig() (*tls.Config, error) { dockerCertPath := os.Getenv("DOCKER_CERT_PATH") if dockerCertPath == "" { return nil, fmt.Errorf("DOCKER_TLS_VERIFY specified, but no DOCKER_CERT_PATH environment variable") } option := &tlsconfig.Options{ CAFile: filepath.Join(dockerCertPath, "ca.pem"), CertFile: filepath.Join(dockerCertPath, "cert.pem"), KeyFile: filepath.Join(dockerCertPath, "key.pem"), } tlsConfig, err := tlsconfig.Client(*option) if err != nil { return nil, err } return tlsConfig, nil }
func (d *Daemon) getClientConfig() (*clientConfig, error) { var ( transport *http.Transport scheme string addr string proto string ) if d.useDefaultTLSHost { option := &tlsconfig.Options{ CAFile: "fixtures/https/ca.pem", CertFile: "fixtures/https/client-cert.pem", KeyFile: "fixtures/https/client-key.pem", } tlsConfig, err := tlsconfig.Client(*option) if err != nil { return nil, err } transport = &http.Transport{ TLSClientConfig: tlsConfig, } addr = fmt.Sprintf("%s:%d", opts.DefaultHTTPHost, opts.DefaultTLSHTTPPort) scheme = "https" proto = "tcp" } else if d.useDefaultHost { addr = opts.DefaultUnixSocket proto = "unix" scheme = "http" transport = &http.Transport{} } else { addr = filepath.Join(d.folder, "docker.sock") proto = "unix" scheme = "http" transport = &http.Transport{} } d.c.Assert(sockets.ConfigureTransport(transport, proto, addr), check.IsNil) return &clientConfig{ transport: transport, scheme: scheme, addr: addr, }, nil }
// sets up TLS for the GRPC connection to notary-signer func grpcTLS(configuration *viper.Viper) (*tls.Config, error) { rootCA := utils.GetPathRelativeToConfig(configuration, "trust_service.tls_ca_file") clientCert := utils.GetPathRelativeToConfig(configuration, "trust_service.tls_client_cert") clientKey := utils.GetPathRelativeToConfig(configuration, "trust_service.tls_client_key") if clientCert == "" && clientKey != "" || clientCert != "" && clientKey == "" { return nil, fmt.Errorf("either pass both client key and cert, or neither") } tlsConfig, err := tlsconfig.Client(tlsconfig.Options{ CAFile: rootCA, CertFile: clientCert, KeyFile: clientKey, }) if err != nil { return nil, fmt.Errorf( "Unable to configure TLS to the trust service: %s", err.Error()) } return tlsConfig, nil }
// New creates a new implementation of the STI Docker interface func New(config *api.DockerConfig, auth api.AuthConfig) (Docker, error) { var client *dockerapi.Client var httpClient *http.Client if config.CertFile != "" && config.KeyFile != "" && config.CAFile != "" { tlscOptions := tlsconfig.Options{ CAFile: config.CAFile, CertFile: config.CertFile, KeyFile: config.KeyFile, } tlsc, tlsErr := tlsconfig.Client(tlscOptions) if tlsErr != nil { return nil, tlsErr } httpClient = &http.Client{ Transport: k8snet.SetTransportDefaults(&http.Transport{ TLSClientConfig: tlsc, }), } } client, err := dockerapi.NewClient(config.Endpoint, "", httpClient, nil) if err != nil { return nil, err } k8sDocker := dockertools.ConnectToDockerOrDie(config.Endpoint, 0) return &stiDocker{ kubeDockerClient: k8sDocker, client: client, httpClient: httpClient, dialer: &net.Dialer{}, pullAuth: dockertypes.AuthConfig{ Username: auth.Username, Password: auth.Password, Email: auth.Email, ServerAddress: auth.ServerAddress, }, endpoint: config.Endpoint, }, nil }
// getTransport returns an http.RoundTripper to be used for all http requests. // It correctly handles the auth challenge/credentials required to interact // with a notary server over both HTTP Basic Auth and the JWT auth implemented // in the notary-server // The readOnly flag indicates if the operation should be performed as an // anonymous read only operation. If the command entered requires write // permissions on the server, readOnly must be false func getTransport(config *viper.Viper, gun string, readOnly bool) (http.RoundTripper, error) { // Attempt to get a root CA from the config file. Nil is the host defaults. rootCAFile := utils.GetPathRelativeToConfig(config, "remote_server.root_ca") clientCert := utils.GetPathRelativeToConfig(config, "remote_server.tls_client_cert") clientKey := utils.GetPathRelativeToConfig(config, "remote_server.tls_client_key") insecureSkipVerify := false if config.IsSet("remote_server.skipTLSVerify") { insecureSkipVerify = config.GetBool("remote_server.skipTLSVerify") } if clientCert == "" && clientKey != "" || clientCert != "" && clientKey == "" { return nil, fmt.Errorf("either pass both client key and cert, or neither") } tlsConfig, err := tlsconfig.Client(tlsconfig.Options{ CAFile: rootCAFile, InsecureSkipVerify: insecureSkipVerify, CertFile: clientCert, KeyFile: clientKey, }) if err != nil { return nil, fmt.Errorf("unable to configure TLS: %s", err.Error()) } base := &http.Transport{ Proxy: http.ProxyFromEnvironment, Dial: (&net.Dialer{ Timeout: 30 * time.Second, KeepAlive: 30 * time.Second, DualStack: true, }).Dial, TLSHandshakeTimeout: 10 * time.Second, TLSClientConfig: tlsConfig, DisableKeepAlives: true, } trustServerURL := getRemoteTrustServer(config) return tokenAuth(trustServerURL, base, gun, readOnly) }
// New creates a new implementation of the STI Docker interface func New(config *api.DockerConfig, auth api.AuthConfig) (Docker, error) { var httpClient *http.Client if config.CertFile != "" && config.KeyFile != "" && config.CAFile != "" { tlscOptions := tlsconfig.Options{ CAFile: config.CAFile, CertFile: config.CertFile, KeyFile: config.KeyFile, InsecureSkipVerify: os.Getenv("DOCKER_TLS_VERIFY") == "", } tlsc, err := tlsconfig.Client(tlscOptions) if err != nil { return nil, err } httpClient = &http.Client{ Transport: &http.Transport{ TLSClientConfig: tlsc, }, } } client, err := dockerapi.NewClient(config.Endpoint, os.Getenv("DOCKER_API_VERSION"), httpClient, nil) if err != nil { return nil, err } return &stiDocker{ client: client, pullAuth: dockertypes.AuthConfig{ Username: auth.Username, Password: auth.Password, Email: auth.Email, ServerAddress: auth.ServerAddress, }, }, nil }
func newHTTPClient(host string, tlsOptions *tlsconfig.Options) (*http.Client, error) { if tlsOptions == nil { // let the api client configure the default transport. return nil, nil } config, err := tlsconfig.Client(*tlsOptions) if err != nil { return nil, err } tr := &http.Transport{ TLSClientConfig: config, } proto, addr, _, err := client.ParseHost(host) if err != nil { return nil, err } sockets.ConfigureTransport(tr, proto, addr) return &http.Client{ Transport: tr, }, nil }
// Client returns a Docker client for the given Docker machine func Client(name string) (*docker.Client, *dockerclient.Client, error) { output, _, err := localcmd.New(dockerMachineBinary()).Args("env", name).Output() if err != nil { return nil, nil, ErrDockerMachineExec("env", err) } scanner := bufio.NewScanner(bytes.NewBufferString(output)) var ( dockerHost, certPath string tlsVerify bool ) prefix := "export " if runtime.GOOS == "windows" { prefix = "SET " } for scanner.Scan() { line := scanner.Text() if strings.HasPrefix(line, prefix) { line = strings.TrimPrefix(line, prefix) parts := strings.SplitN(line, "=", 2) if len(parts) != 2 { continue } switch strings.ToUpper(parts[0]) { case "DOCKER_HOST": dockerHost = strings.Trim(parts[1], "\"") case "DOCKER_CERT_PATH": certPath = strings.Trim(parts[1], "\"") case "DOCKER_TLS_VERIFY": tlsVerify = len(parts[1]) > 0 } } } var client *docker.Client if len(certPath) > 0 { cert := filepath.Join(certPath, "cert.pem") key := filepath.Join(certPath, "key.pem") ca := filepath.Join(certPath, "ca.pem") client, err = docker.NewVersionedTLSClient(dockerHost, cert, key, ca, "") } else { client, err = docker.NewVersionedClient(dockerHost, "") } if err != nil { return nil, nil, errors.NewError("could not get Docker client for machine %s", name).WithCause(err) } client.SkipServerVersionCheck = true var httpClient *http.Client if len(certPath) > 0 { tlscOptions := tlsconfig.Options{ CAFile: filepath.Join(certPath, "ca.pem"), CertFile: filepath.Join(certPath, "cert.pem"), KeyFile: filepath.Join(certPath, "key.pem"), InsecureSkipVerify: !tlsVerify, } tlsc, tlsErr := tlsconfig.Client(tlscOptions) if tlsErr != nil { return nil, nil, errors.NewError("could not create TLS config client for machine %s", name).WithCause(tlsErr) } httpClient = &http.Client{ Transport: net.SetTransportDefaults(&http.Transport{ TLSClientConfig: tlsc, }), } } engineAPIClient, err := dockerclient.NewClient(dockerHost, "", httpClient, nil) if err != nil { return nil, nil, errors.NewError("cannot create Docker engine API client").WithCause(err) } return client, engineAPIClient, nil }
// CreateClient creates a docker client based on the specified options. func CreateClient(c ClientOpts) (client.APIClient, error) { if c.Host == "" { if os.Getenv("DOCKER_API_VERSION") == "" { os.Setenv("DOCKER_API_VERSION", DefaultAPIVersion) } client, err := client.NewEnvClient() if err != nil { return nil, err } return client, nil } apiVersion := c.APIVersion if apiVersion == "" { apiVersion = DefaultAPIVersion } if c.TLSOptions.CAFile == "" { c.TLSOptions.CAFile = filepath.Join(dockerCertPath, defaultCaFile) } if c.TLSOptions.CertFile == "" { c.TLSOptions.CertFile = filepath.Join(dockerCertPath, defaultCertFile) } if c.TLSOptions.KeyFile == "" { c.TLSOptions.KeyFile = filepath.Join(dockerCertPath, defaultKeyFile) } if c.TrustKey == "" { c.TrustKey = filepath.Join(homedir.Get(), ".docker", defaultTrustKeyFile) } if c.TLSVerify { c.TLS = true } if c.TLS { c.TLSOptions.InsecureSkipVerify = !c.TLSVerify } var httpClient *http.Client if c.TLS { config, err := tlsconfig.Client(c.TLSOptions) if err != nil { return nil, err } tr := &http.Transport{ TLSClientConfig: config, } proto, addr, _, err := client.ParseHost(c.Host) if err != nil { return nil, err } sockets.ConfigureTransport(tr, proto, addr) httpClient = &http.Client{ Transport: tr, } } customHeaders := map[string]string{} customHeaders["User-Agent"] = fmt.Sprintf("Libcompose-Client/%s (%s)", version.VERSION, runtime.GOOS) client, err := client.NewClient(c.Host, apiVersion, httpClient, customHeaders) if err != nil { return nil, err } return client, nil }