From 774ab1f22e867292481749e918347ca1b06c46e9 Mon Sep 17 00:00:00 2001 From: Michael Kuzmin Date: Tue, 22 Nov 2016 13:18:09 +0100 Subject: [PATCH] provider/docker: authentication via values instead of files (#10151) * Docker authentication via values * Rename parameters to ca_material, cert_material, and key_material. Add environment variables. --- builtin/providers/docker/config.go | 28 +++++++++++++------ builtin/providers/docker/provider.go | 25 +++++++++++++++++ .../docs/providers/docker/index.html.markdown | 3 ++ 3 files changed, 48 insertions(+), 8 deletions(-) diff --git a/builtin/providers/docker/config.go b/builtin/providers/docker/config.go index 1991827440f7..d3a6cb1212a0 100644 --- a/builtin/providers/docker/config.go +++ b/builtin/providers/docker/config.go @@ -1,6 +1,7 @@ package docker import ( + "fmt" "path/filepath" dc "github.com/fsouza/go-dockerclient" @@ -10,21 +11,32 @@ import ( // Docker API compatible host. type Config struct { Host string + Ca string + Cert string + Key string CertPath string } // NewClient() returns a new Docker client. func (c *Config) NewClient() (*dc.Client, error) { - // If there is no cert information, then just return the direct client - if c.CertPath == "" { - return dc.NewClient(c.Host) + if c.Ca != "" || c.Cert != "" || c.Key != "" { + if c.Ca == "" || c.Cert == "" || c.Key == "" { + return nil, fmt.Errorf("ca_material, cert_material, and key_material must be specified") + } + + return dc.NewTLSClientFromBytes(c.Host, []byte(c.Cert), []byte(c.Key), []byte(c.Ca)) } - // If there is cert information, load it and use it. - ca := filepath.Join(c.CertPath, "ca.pem") - cert := filepath.Join(c.CertPath, "cert.pem") - key := filepath.Join(c.CertPath, "key.pem") - return dc.NewTLSClient(c.Host, cert, key, ca) + if c.CertPath != "" { + // If there is cert information, load it and use it. + ca := filepath.Join(c.CertPath, "ca.pem") + cert := filepath.Join(c.CertPath, "cert.pem") + key := filepath.Join(c.CertPath, "key.pem") + return dc.NewTLSClient(c.Host, cert, key, ca) + } + + // If there is no cert information, then just return the direct client + return dc.NewClient(c.Host) } // Data ia structure for holding data that we fetch from Docker. diff --git a/builtin/providers/docker/provider.go b/builtin/providers/docker/provider.go index cee438ae3989..61486530730e 100644 --- a/builtin/providers/docker/provider.go +++ b/builtin/providers/docker/provider.go @@ -17,6 +17,28 @@ func Provider() terraform.ResourceProvider { Description: "The Docker daemon address", }, + "ca_material": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + DefaultFunc: schema.EnvDefaultFunc("DOCKER_CA_MATERIAL", ""), + ConflictsWith: []string{"cert_path"}, + Description: "PEM-encoded content of Docker host CA certificate", + }, + "cert_material": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + DefaultFunc: schema.EnvDefaultFunc("DOCKER_CERT_MATERIAL", ""), + ConflictsWith: []string{"cert_path"}, + Description: "PEM-encoded content of Docker client certificate", + }, + "key_material": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + DefaultFunc: schema.EnvDefaultFunc("DOCKER_KEY_MATERIAL", ""), + ConflictsWith: []string{"cert_path"}, + Description: "PEM-encoded content of Docker client private key", + }, + "cert_path": &schema.Schema{ Type: schema.TypeString, Optional: true, @@ -43,6 +65,9 @@ func Provider() terraform.ResourceProvider { func providerConfigure(d *schema.ResourceData) (interface{}, error) { config := Config{ Host: d.Get("host").(string), + Ca: d.Get("ca_material").(string), + Cert: d.Get("cert_material").(string), + Key: d.Get("key_material").(string), CertPath: d.Get("cert_path").(string), } diff --git a/website/source/docs/providers/docker/index.html.markdown b/website/source/docs/providers/docker/index.html.markdown index 1b92cb1b74bf..f16a04f10505 100644 --- a/website/source/docs/providers/docker/index.html.markdown +++ b/website/source/docs/providers/docker/index.html.markdown @@ -57,6 +57,9 @@ The following arguments are supported: for connecting to the Docker host via TLS. If this is blank, the `DOCKER_CERT_PATH` will also be checked. +* `ca_material`, `cert_material`, `key_material`, - (Optional) Content of `ca.pem`, `cert.pem`, and `key.pem` files + for TLS authentication. Cannot be used together with `cert_path`. + ~> **NOTE on Certificates and `docker-machine`:** As per [Docker Remote API documentation](https://docs.docker.com/engine/reference/api/docker_remote_api/), in any docker-machine environment, the Docker daemon uses an encrypted TCP