From ce6dabfea0c931ed6e55a90ab2b515fd88b0c412 Mon Sep 17 00:00:00 2001 From: Marco Mariani Date: Wed, 18 Oct 2017 17:23:28 +0200 Subject: [PATCH] add support for OS_CACERT, OS_INSECURE Signed-off-by: Marco Mariani --- docs/platform-openstack.md | 2 ++ src/cmd/linuxkit/push_openstack.go | 25 ++++++++++++---- src/cmd/linuxkit/run_openstack.go | 48 ++++++++++++++++++++++++++++-- 3 files changed, 68 insertions(+), 7 deletions(-) diff --git a/docs/platform-openstack.md b/docs/platform-openstack.md index a1a52b224..991a713dd 100644 --- a/docs/platform-openstack.md +++ b/docs/platform-openstack.md @@ -19,6 +19,8 @@ OS_PASSWORD="xxx" OS_TENANT_NAME="linuxkit" OS_AUTH_URL="https://keystone.com:5000/v3" OS_USER_DOMAIN_NAME=default +OS_CACERT=/path/to/cacert.pem +OS_INSECURE=false ``` ## Push diff --git a/src/cmd/linuxkit/push_openstack.go b/src/cmd/linuxkit/push_openstack.go index 671604ae6..68d13c419 100644 --- a/src/cmd/linuxkit/push_openstack.go +++ b/src/cmd/linuxkit/push_openstack.go @@ -31,6 +31,8 @@ func pushOpenstack(args []string) { projectNameFlag := flags.String("project", "", "Name of the Project (aka Tenant) to be used") userDomainFlag := flags.String("domain", "Default", "Domain name") usernameFlag := flags.String("username", "", "Username with permissions to upload image") + cacertFlag := flags.String("cacert", "", "CA certificate bundle file") + insecureFlag := flags.Bool("insecure", false, "Disable server certificate verification") if err := flags.Parse(args); err != nil { log.Fatal("Unable to parse args") @@ -51,6 +53,8 @@ func pushOpenstack(args []string) { projectName := getStringValue(projectNameVar, *projectNameFlag, "") userDomain := getStringValue(userDomainVar, *userDomainFlag, "") username := getStringValue(usernameVar, *usernameFlag, "") + cacert := getStringValue(cacertVar, *cacertFlag, "") + insecure := getBoolValue(insecureVar, *insecureFlag) authOpts := gophercloud.AuthOptions{ DomainName: userDomain, @@ -59,9 +63,20 @@ func pushOpenstack(args []string) { TenantName: projectName, Username: username, } - provider, err := openstack.AuthenticatedClient(authOpts) + + provider, err := openstack.NewClient(authOpts.IdentityEndpoint) if err != nil { - log.Fatalf("Failed to authenticate") + log.Fatalf("Failed to connect to OpenStack: %s", err) + } + + provider.HTTPClient, err = openstackHTTPClient(cacert, insecure) + if err != nil { + log.Fatalf("Failed to authenticate with OpenStack: %s", err) + } + + err = openstack.Authenticate(provider, authOpts) + if err != nil { + log.Fatalf("Failed to authenticate with OpenStack: %s", err) } createOpenStackImage(filePath, *imageName, provider) @@ -93,7 +108,7 @@ func createOpenStackImage(filePath string, imageName string, provider *gopherclo client, err := openstack.NewImageServiceV2(provider, gophercloud.EndpointOpts{}) if err != nil { - log.Fatalf("Unable to create Image V2 client") + log.Fatalf("Unable to create Image V2 client: %s", err) } imageOpts := images.CreateOpts{ Name: imageName, @@ -102,12 +117,12 @@ func createOpenStackImage(filePath string, imageName string, provider *gopherclo } image, err := images.Create(client, imageOpts).Extract() if err != nil { - log.Fatalf("Error creating image") + log.Fatalf("Error creating image: %s", err) } f, err := os.Open(filePath) if err != nil { - panic(err) + log.Fatalf("Can't read image file: %s", err) } defer f.Close() diff --git a/src/cmd/linuxkit/run_openstack.go b/src/cmd/linuxkit/run_openstack.go index 3b7612283..7ec1583bb 100644 --- a/src/cmd/linuxkit/run_openstack.go +++ b/src/cmd/linuxkit/run_openstack.go @@ -1,8 +1,13 @@ package main import ( + "crypto/tls" + "crypto/x509" + "errors" "flag" "fmt" + "io/ioutil" + "net/http" "os" "path/filepath" "strings" @@ -21,8 +26,32 @@ const ( passwordVar = "OS_PASSWORD" projectNameVar = "OS_PROJECT_NAME" userDomainVar = "OS_USER_DOMAIN_NAME" + cacertVar = "OS_CACERT" + insecureVar = "OS_INSECURE" ) +func openstackHTTPClient(cacert string, insecure bool) (http.Client, error) { + if cacert == "" { + return http.Client{}, nil + } + + caCertPool := x509.NewCertPool() + caCert, err := ioutil.ReadFile(cacert) + if err != nil { + return http.Client{}, errors.New("Can't read certificate file") + } + caCertPool.AppendCertsFromPEM(caCert) + + tlsConfig := &tls.Config{ + RootCAs: caCertPool, + InsecureSkipVerify: insecure, + } + tlsConfig.BuildNameToCertificate() + transport := &http.Transport{TLSClientConfig: tlsConfig} + + return http.Client{Transport: transport}, nil +} + func runOpenStack(args []string) { flags := flag.NewFlagSet("openstack", flag.ExitOnError) invoked := filepath.Base(os.Args[0]) @@ -43,6 +72,8 @@ func runOpenStack(args []string) { projectNameFlag := flags.String("project", "", "Name of the Project (aka Tenant) to be used") userDomainFlag := flags.String("domain", "Default", "Domain name") usernameFlag := flags.String("username", "", "Username with permissions to create an instance") + cacertFlag := flags.String("cacert", "", "CA certificate bundle file") + insecureFlag := flags.Bool("insecure", false, "Disable server certificate verification") if err := flags.Parse(args); err != nil { log.Fatal("Unable to parse args") @@ -65,6 +96,8 @@ func runOpenStack(args []string) { projectName := getStringValue(projectNameVar, *projectNameFlag, "") userDomain := getStringValue(userDomainVar, *userDomainFlag, "") username := getStringValue(usernameVar, *usernameFlag, "") + cacert := getStringValue(cacertVar, *cacertFlag, "") + insecure := getBoolValue(insecureVar, *insecureFlag) authOpts := gophercloud.AuthOptions{ DomainName: userDomain, @@ -73,9 +106,20 @@ func runOpenStack(args []string) { TenantName: projectName, Username: username, } - provider, err := openstack.AuthenticatedClient(authOpts) + + provider, err := openstack.NewClient(authOpts.IdentityEndpoint) if err != nil { - log.Fatalf("Failed to authenticate") + log.Fatalf("Failed to connect to OpenStack: %s", err) + } + + provider.HTTPClient, err = openstackHTTPClient(cacert, insecure) + if err != nil { + log.Fatalf("Failed to authenticate with OpenStack: %s", err) + } + + err = openstack.Authenticate(provider, authOpts) + if err != nil { + log.Fatalf("Failed to authenticate with OpenStack: %s", err) } client, err := openstack.NewComputeV2(provider, gophercloud.EndpointOpts{})