Skip to content

Commit 94d3ed0

Browse files
committed
provider/openstack: Support client certificates
Official OpenStack clients commonly support specifing a client certificate/key to enable SSL client authentication when communicating with OpenStack services. This patch enables such feature in Terraform with new parameters and environment variables: * 'cert' provider parameter or OS_CERT env variable to specify client certificate file, * 'key' provider parameter or OS_KEY env variable to specify client certificate private key file.
1 parent 77f5648 commit 94d3ed0

3 files changed

Lines changed: 34 additions & 11 deletions

File tree

builtin/providers/openstack/config.go

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ type Config struct {
2525
Insecure bool
2626
EndpointType string
2727
CACertFile string
28+
ClientCertFile string
29+
ClientKeyFile string
2830

2931
osClient *gophercloud.ProviderClient
3032
}
@@ -56,6 +58,7 @@ func (c *Config) loadAndValidate() error {
5658
return err
5759
}
5860

61+
config := &tls.Config{}
5962
if c.CACertFile != "" {
6063

6164
caCert, err := ioutil.ReadFile(c.CACertFile)
@@ -65,21 +68,23 @@ func (c *Config) loadAndValidate() error {
6568

6669
caCertPool := x509.NewCertPool()
6770
caCertPool.AppendCertsFromPEM(caCert)
71+
config.RootCAs = caCertPool
72+
}
73+
if c.Insecure {
74+
config.InsecureSkipVerify = true
75+
}
6876

69-
config := &tls.Config{
70-
RootCAs: caCertPool,
77+
if c.ClientCertFile != "" && c.ClientKeyFile != "" {
78+
cert, err := tls.LoadX509KeyPair(c.ClientCertFile, c.ClientKeyFile)
79+
if err != nil {
80+
return err
7181
}
7282

73-
transport := &http.Transport{TLSClientConfig: config}
74-
client.HTTPClient.Transport = transport
75-
}
76-
77-
if c.Insecure {
78-
// Configure custom TLS settings.
79-
config := &tls.Config{InsecureSkipVerify: true}
80-
transport := &http.Transport{TLSClientConfig: config}
81-
client.HTTPClient.Transport = transport
83+
config.Certificates = []tls.Certificate{cert}
84+
config.BuildNameToCertificate()
8285
}
86+
transport := &http.Transport{TLSClientConfig: config}
87+
client.HTTPClient.Transport = transport
8388

8489
err = openstack.Authenticate(client, ao)
8590
if err != nil {

builtin/providers/openstack/provider.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,16 @@ func Provider() terraform.ResourceProvider {
7878
Optional: true,
7979
DefaultFunc: schema.EnvDefaultFunc("OS_CACERT", ""),
8080
},
81+
"cert": &schema.Schema{
82+
Type: schema.TypeString,
83+
Optional: true,
84+
DefaultFunc: schema.EnvDefaultFunc("OS_CERT", ""),
85+
},
86+
"key": &schema.Schema{
87+
Type: schema.TypeString,
88+
Optional: true,
89+
DefaultFunc: schema.EnvDefaultFunc("OS_KEY", ""),
90+
},
8191
},
8292

8393
ResourcesMap: map[string]*schema.Resource{
@@ -123,6 +133,8 @@ func configureProvider(d *schema.ResourceData) (interface{}, error) {
123133
Insecure: d.Get("insecure").(bool),
124134
EndpointType: d.Get("endpoint_type").(string),
125135
CACertFile: d.Get("cacert_file").(string),
136+
ClientCertFile: d.Get("cert").(string),
137+
ClientKeyFile: d.Get("key").(string),
126138
}
127139

128140
if err := config.loadAndValidate(); err != nil {

website/source/docs/providers/openstack/index.html.markdown

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,12 @@ The following arguments are supported:
7676
* `cacert_file` - (Optional) Specify a custom CA certificate when communicating
7777
over SSL. If omitted, the `OS_CACERT` environment variable is used.
7878

79+
* `cert` - (Optional) Specify client certificate file for SSL client
80+
authentication. If omitted the `OS_CERT` environment variable is used.
81+
82+
* `key` - (Optional) Specify client private key file for SSL client
83+
authentication. If omitted the `OS_KEY` environment variable is used.
84+
7985
* `endpoint_type` - (Optional) Specify which type of endpoint to use from the
8086
service catalog. It can be set using the OS_ENDPOINT_TYPE environment
8187
variable. If not set, public endpoints is used.

0 commit comments

Comments
 (0)