diff --git a/builtin/providers/openstack/config.go b/builtin/providers/openstack/config.go index 5001c8eca..6f9e0fa63 100644 --- a/builtin/providers/openstack/config.go +++ b/builtin/providers/openstack/config.go @@ -25,6 +25,8 @@ type Config struct { Insecure bool EndpointType string CACertFile string + ClientCertFile string + ClientKeyFile string osClient *gophercloud.ProviderClient } @@ -56,6 +58,7 @@ func (c *Config) loadAndValidate() error { return err } + config := &tls.Config{} if c.CACertFile != "" { caCert, err := ioutil.ReadFile(c.CACertFile) @@ -65,21 +68,23 @@ func (c *Config) loadAndValidate() error { caCertPool := x509.NewCertPool() caCertPool.AppendCertsFromPEM(caCert) + config.RootCAs = caCertPool + } + if c.Insecure { + config.InsecureSkipVerify = true + } - config := &tls.Config{ - RootCAs: caCertPool, + if c.ClientCertFile != "" && c.ClientKeyFile != "" { + cert, err := tls.LoadX509KeyPair(c.ClientCertFile, c.ClientKeyFile) + if err != nil { + return err } - transport := &http.Transport{TLSClientConfig: config} - client.HTTPClient.Transport = transport - } - - if c.Insecure { - // Configure custom TLS settings. - config := &tls.Config{InsecureSkipVerify: true} - transport := &http.Transport{TLSClientConfig: config} - client.HTTPClient.Transport = transport + config.Certificates = []tls.Certificate{cert} + config.BuildNameToCertificate() } + transport := &http.Transport{TLSClientConfig: config} + client.HTTPClient.Transport = transport err = openstack.Authenticate(client, ao) if err != nil { diff --git a/builtin/providers/openstack/provider.go b/builtin/providers/openstack/provider.go index 8b72ba22a..5d8dfc59b 100644 --- a/builtin/providers/openstack/provider.go +++ b/builtin/providers/openstack/provider.go @@ -78,6 +78,16 @@ func Provider() terraform.ResourceProvider { Optional: true, DefaultFunc: schema.EnvDefaultFunc("OS_CACERT", ""), }, + "cert": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + DefaultFunc: schema.EnvDefaultFunc("OS_CERT", ""), + }, + "key": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + DefaultFunc: schema.EnvDefaultFunc("OS_KEY", ""), + }, }, ResourcesMap: map[string]*schema.Resource{ @@ -125,6 +135,8 @@ func configureProvider(d *schema.ResourceData) (interface{}, error) { Insecure: d.Get("insecure").(bool), EndpointType: d.Get("endpoint_type").(string), CACertFile: d.Get("cacert_file").(string), + ClientCertFile: d.Get("cert").(string), + ClientKeyFile: d.Get("key").(string), } if err := config.loadAndValidate(); err != nil { diff --git a/website/source/docs/providers/openstack/index.html.markdown b/website/source/docs/providers/openstack/index.html.markdown index 2800bfaf5..c9e23a765 100644 --- a/website/source/docs/providers/openstack/index.html.markdown +++ b/website/source/docs/providers/openstack/index.html.markdown @@ -76,6 +76,12 @@ The following arguments are supported: * `cacert_file` - (Optional) Specify a custom CA certificate when communicating over SSL. If omitted, the `OS_CACERT` environment variable is used. +* `cert` - (Optional) Specify client certificate file for SSL client + authentication. If omitted the `OS_CERT` environment variable is used. + +* `key` - (Optional) Specify client private key file for SSL client + authentication. If omitted the `OS_KEY` environment variable is used. + * `endpoint_type` - (Optional) Specify which type of endpoint to use from the service catalog. It can be set using the OS_ENDPOINT_TYPE environment variable. If not set, public endpoints is used.