From 1de9eb2cfdcf2911fa2b303c307d0f185d390add Mon Sep 17 00:00:00 2001 From: r_takaishi Date: Wed, 24 May 2017 10:23:12 +0900 Subject: [PATCH 1/8] support client certificate file When AUTH_URL and each endpoints need SSL client authentication, we have to specify cert file and private key file. So, add optional config, cert and key. --- builder/openstack/access_config.go | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/builder/openstack/access_config.go b/builder/openstack/access_config.go index 10b4fd02e..a1ab96b93 100644 --- a/builder/openstack/access_config.go +++ b/builder/openstack/access_config.go @@ -24,6 +24,8 @@ type AccessConfig struct { Insecure bool `mapstructure:"insecure"` Region string `mapstructure:"region"` EndpointType string `mapstructure:"endpoint_type"` + ClientCertFile string `mapstructure:"cert"` + ClientKeyFile string `mapstructure:"key"` osClient *gophercloud.ProviderClient } @@ -53,6 +55,12 @@ func (c *AccessConfig) Prepare(ctx *interpolate.Context) []error { if c.Username == "" { c.Username = os.Getenv("SDK_USERNAME") } + if c.ClientCertFile == "" { + c.ClientCertFile = os.Getenv("OS_CERT") + } + if c.ClientKeyFile == "" { + c.ClientKeyFile = os.Getenv("OS_KEY") + } // Get as much as possible from the end ao, _ := openstack.AuthOptionsFromEnv() @@ -85,13 +93,24 @@ func (c *AccessConfig) Prepare(ctx *interpolate.Context) []error { return []error{err} } + tls_config := &tls.Config{} + // If we have insecure set, then create a custom HTTP client that // ignores SSL errors. if c.Insecure { - config := &tls.Config{InsecureSkipVerify: true} - transport := &http.Transport{TLSClientConfig: config} - client.HTTPClient.Transport = transport + tls_config.InsecureSkipVerify = true + } + + if c.ClientCertFile != "" && c.ClientKeyFile != "" { + cert, err := tls.LoadX509KeyPair(c.ClientCertFile, c.ClientKeyFile) + if err != nil { + return []error{err} + } + + tls_config.Certificates = []tls.Certificate{cert} } + transport := &http.Transport{TLSClientConfig: tls_config} + client.HTTPClient.Transport = transport // Auth err = openstack.Authenticate(client, ao) From a36d9d6b4450aa6b9c89ab8a56cddbaeec744c11 Mon Sep 17 00:00:00 2001 From: r_takaishi Date: Wed, 24 May 2017 10:27:29 +0900 Subject: [PATCH 2/8] add docs --- website/source/docs/builders/openstack.html.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/website/source/docs/builders/openstack.html.md b/website/source/docs/builders/openstack.html.md index 85c60d797..77fac9c38 100644 --- a/website/source/docs/builders/openstack.html.md +++ b/website/source/docs/builders/openstack.html.md @@ -79,6 +79,9 @@ builder. - `config_drive` (boolean) - Whether or not nova should use ConfigDrive for cloud-init metadata. +- `cert` (string) - Client certificate file path for SSL client authentication. + If omitted the OS_CERT environment variable is used. + - `domain_name` or `domain_id` (string) - The Domain name or ID you are authenticating with. OpenStack installations require this if identity v3 is used. Packer will use the environment variable `OS_DOMAIN_NAME` or `OS_DOMAIN_ID`, if set. @@ -102,6 +105,9 @@ builder. - `insecure` (boolean) - Whether or not the connection to OpenStack can be done over an insecure connection. By default this is false. +- `key` (string) - Cleint private key file path for SSL client authentication. + If ommited the OS_KEY environment variable is used. + - `metadata` (object of key/value strings) - Glance metadata that will be applied to the image. From c909a27e7bfc6d348ef93a2b8251146df292582e Mon Sep 17 00:00:00 2001 From: r_takaishi Date: Wed, 24 May 2017 14:07:12 +0900 Subject: [PATCH 3/8] fix docs --- website/source/docs/builders/openstack.html.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/website/source/docs/builders/openstack.html.md b/website/source/docs/builders/openstack.html.md index 77fac9c38..14dfed447 100644 --- a/website/source/docs/builders/openstack.html.md +++ b/website/source/docs/builders/openstack.html.md @@ -80,7 +80,7 @@ builder. cloud-init metadata. - `cert` (string) - Client certificate file path for SSL client authentication. - If omitted the OS_CERT environment variable is used. + If omitted the OS_CERT environment variable can be used. - `domain_name` or `domain_id` (string) - The Domain name or ID you are authenticating with. OpenStack installations require this if identity v3 is used. @@ -105,8 +105,8 @@ builder. - `insecure` (boolean) - Whether or not the connection to OpenStack can be done over an insecure connection. By default this is false. -- `key` (string) - Cleint private key file path for SSL client authentication. - If ommited the OS_KEY environment variable is used. +- `key` (string) - Client private key file path for SSL client authentication. + If ommited the OS_KEY environment variable can be used. - `metadata` (object of key/value strings) - Glance metadata that will be applied to the image. From 67ce2da59eb778aecc2b6682d919d05b32bfecd8 Mon Sep 17 00:00:00 2001 From: r_takaishi Date: Wed, 24 May 2017 14:21:16 +0900 Subject: [PATCH 4/8] add cacert config to specify custom CA certificate file --- builder/openstack/access_config.go | 16 ++++++++++++++++ website/source/docs/builders/openstack.html.md | 3 +++ 2 files changed, 19 insertions(+) diff --git a/builder/openstack/access_config.go b/builder/openstack/access_config.go index a1ab96b93..9af9b6959 100644 --- a/builder/openstack/access_config.go +++ b/builder/openstack/access_config.go @@ -9,6 +9,8 @@ import ( "github.com/gophercloud/gophercloud" "github.com/gophercloud/gophercloud/openstack" "github.com/hashicorp/packer/template/interpolate" + "io/ioutil" + "crypto/x509" ) // AccessConfig is for common configuration related to openstack access @@ -24,6 +26,7 @@ type AccessConfig struct { Insecure bool `mapstructure:"insecure"` Region string `mapstructure:"region"` EndpointType string `mapstructure:"endpoint_type"` + CACertFile string `mapstructure:"cacert"` ClientCertFile string `mapstructure:"cert"` ClientKeyFile string `mapstructure:"key"` @@ -55,6 +58,9 @@ func (c *AccessConfig) Prepare(ctx *interpolate.Context) []error { if c.Username == "" { c.Username = os.Getenv("SDK_USERNAME") } + if c.CACertFile == "" { + c.CACertFile = os.Getenv("OS_CACERT") + } if c.ClientCertFile == "" { c.ClientCertFile = os.Getenv("OS_CERT") } @@ -95,6 +101,16 @@ func (c *AccessConfig) Prepare(ctx *interpolate.Context) []error { tls_config := &tls.Config{} + if c.CACertFile != "" { + caCert, err := ioutil.ReadFile(c.CACertFile) + if err != nil { + return []error{err} + } + caCertPool := x509.NewCertPool() + caCertPool.AppendCertsFromPEM(caCert) + tls_config.RootCAs = caCertPool + } + // If we have insecure set, then create a custom HTTP client that // ignores SSL errors. if c.Insecure { diff --git a/website/source/docs/builders/openstack.html.md b/website/source/docs/builders/openstack.html.md index 14dfed447..f042921f5 100644 --- a/website/source/docs/builders/openstack.html.md +++ b/website/source/docs/builders/openstack.html.md @@ -76,6 +76,9 @@ builder. server in. If this isn't specified, the default enforced by your OpenStack cluster will be used. This may be required for some OpenStack clusters. +- `cacert` (string) - Custom CA certificate file path. + If ommited the OS_CACERT environment variable can be used. + - `config_drive` (boolean) - Whether or not nova should use ConfigDrive for cloud-init metadata. From 37e6539bffd49a8ea7f5186af223a1db5f128f4b Mon Sep 17 00:00:00 2001 From: r_takaishi Date: Wed, 24 May 2017 16:19:30 +0900 Subject: [PATCH 5/8] use DefaultTransport --- builder/openstack/access_config.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/builder/openstack/access_config.go b/builder/openstack/access_config.go index 9af9b6959..e653813c7 100644 --- a/builder/openstack/access_config.go +++ b/builder/openstack/access_config.go @@ -125,8 +125,10 @@ func (c *AccessConfig) Prepare(ctx *interpolate.Context) []error { tls_config.Certificates = []tls.Certificate{cert} } - transport := &http.Transport{TLSClientConfig: tls_config} - client.HTTPClient.Transport = transport + + var transport http.Transport = *http.DefaultTransport.(*http.Transport) + transport.TLSClientConfig = tls_config + client.HTTPClient.Transport = &transport // Auth err = openstack.Authenticate(client, ao) From db58854b0b45dbd5e4205b07174c8365683b0475 Mon Sep 17 00:00:00 2001 From: r_takaishi Date: Wed, 24 May 2017 16:28:13 +0900 Subject: [PATCH 6/8] make fmt --- builder/openstack/access_config.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builder/openstack/access_config.go b/builder/openstack/access_config.go index e653813c7..cde357c5d 100644 --- a/builder/openstack/access_config.go +++ b/builder/openstack/access_config.go @@ -6,11 +6,11 @@ import ( "net/http" "os" + "crypto/x509" "github.com/gophercloud/gophercloud" "github.com/gophercloud/gophercloud/openstack" "github.com/hashicorp/packer/template/interpolate" "io/ioutil" - "crypto/x509" ) // AccessConfig is for common configuration related to openstack access From 4fc0616bc937a05f8875e25b6a24c4773f4889f0 Mon Sep 17 00:00:00 2001 From: r_takaishi Date: Wed, 24 May 2017 17:57:21 +0900 Subject: [PATCH 7/8] fix go vet fail --- builder/openstack/access_config.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/builder/openstack/access_config.go b/builder/openstack/access_config.go index cde357c5d..70cb419ef 100644 --- a/builder/openstack/access_config.go +++ b/builder/openstack/access_config.go @@ -126,9 +126,9 @@ func (c *AccessConfig) Prepare(ctx *interpolate.Context) []error { tls_config.Certificates = []tls.Certificate{cert} } - var transport http.Transport = *http.DefaultTransport.(*http.Transport) + transport := http.DefaultTransport.(*http.Transport) transport.TLSClientConfig = tls_config - client.HTTPClient.Transport = &transport + client.HTTPClient.Transport = transport // Auth err = openstack.Authenticate(client, ao) From f6eb4e1b40fdcf01da7b7edf440c0bd12f92253c Mon Sep 17 00:00:00 2001 From: Matthew Hooker Date: Wed, 24 May 2017 11:05:59 -0700 Subject: [PATCH 8/8] use cleanhttp to get a default transport. --- builder/openstack/access_config.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/builder/openstack/access_config.go b/builder/openstack/access_config.go index 70cb419ef..5d9c2b39b 100644 --- a/builder/openstack/access_config.go +++ b/builder/openstack/access_config.go @@ -3,14 +3,15 @@ package openstack import ( "crypto/tls" "fmt" - "net/http" "os" "crypto/x509" + "io/ioutil" + "github.com/gophercloud/gophercloud" "github.com/gophercloud/gophercloud/openstack" + "github.com/hashicorp/go-cleanhttp" "github.com/hashicorp/packer/template/interpolate" - "io/ioutil" ) // AccessConfig is for common configuration related to openstack access @@ -126,7 +127,7 @@ func (c *AccessConfig) Prepare(ctx *interpolate.Context) []error { tls_config.Certificates = []tls.Certificate{cert} } - transport := http.DefaultTransport.(*http.Transport) + transport := cleanhttp.DefaultTransport() transport.TLSClientConfig = tls_config client.HTTPClient.Transport = transport