Add support for OS_CACERT in Openstack driver

This enables using docker-machine's openstack driver without having to
resort to using the --insecure flag.

Signed-off-by: Mathias Nyman <mathias.nyman@iki.fi>
This commit is contained in:
Mathias Nyman 2016-06-02 16:16:02 +03:00
parent c17f42fab5
commit bdd3b24cdc
3 changed files with 46 additions and 9 deletions

View File

@ -25,6 +25,7 @@ Options:
- `--openstack-active-timeout`: The timeout in seconds until the OpenStack instance must be active. - `--openstack-active-timeout`: The timeout in seconds until the OpenStack instance must be active.
- `--openstack-availability-zone`: The availability zone in which to launch the server. - `--openstack-availability-zone`: The availability zone in which to launch the server.
- `--openstack-cacert`: The CA certificate bundle to verify against.
- `--openstack-domain-name` or `--openstack-domain-id`: Domain to use for authentication (Keystone v3 only). - `--openstack-domain-name` or `--openstack-domain-id`: Domain to use for authentication (Keystone v3 only).
- `--openstack-endpoint-type`: Endpoint type can be `internalURL`, `adminURL` on `publicURL`. If is a helper for the driver - `--openstack-endpoint-type`: Endpoint type can be `internalURL`, `adminURL` on `publicURL`. If is a helper for the driver
to choose the right URL in the OpenStack service catalog. If not provided the default id `publicURL` to choose the right URL in the OpenStack service catalog. If not provided the default id `publicURL`
@ -52,6 +53,7 @@ Environment variables and default values:
| `--openstack-active-timeout` | `OS_ACTIVE_TIMEOUT` | `200` | | `--openstack-active-timeout` | `OS_ACTIVE_TIMEOUT` | `200` |
| `--openstack-auth-url` | `OS_AUTH_URL` | - | | `--openstack-auth-url` | `OS_AUTH_URL` | - |
| `--openstack-availability-zone` | `OS_AVAILABILITY_ZONE` | - | | `--openstack-availability-zone` | `OS_AVAILABILITY_ZONE` | - |
| `--openstack-cacert` | `OS_CACERT | - |
| `--openstack-domain-id` | `OS_DOMAIN_ID` | - | | `--openstack-domain-id` | `OS_DOMAIN_ID` | - |
| `--openstack-domain-name` | `OS_DOMAIN_NAME` | - | | `--openstack-domain-name` | `OS_DOMAIN_NAME` | - |
| `--openstack-endpoint-type` | `OS_ENDPOINT_TYPE` | `publicURL` | | `--openstack-endpoint-type` | `OS_ENDPOINT_TYPE` | `publicURL` |

View File

@ -2,7 +2,9 @@ package openstack
import ( import (
"crypto/tls" "crypto/tls"
"crypto/x509"
"fmt" "fmt"
"io/ioutil"
"net/http" "net/http"
"time" "time"
@ -532,6 +534,7 @@ func (c *GenericClient) Authenticate(d *Driver) error {
log.Debug("Authenticating...", map[string]interface{}{ log.Debug("Authenticating...", map[string]interface{}{
"AuthUrl": d.AuthUrl, "AuthUrl": d.AuthUrl,
"Insecure": d.Insecure, "Insecure": d.Insecure,
"CaCert": d.CaCert,
"DomainID": d.DomainID, "DomainID": d.DomainID,
"DomainName": d.DomainName, "DomainName": d.DomainName,
"Username": d.Username, "Username": d.Username,
@ -555,21 +558,45 @@ func (c *GenericClient) Authenticate(d *Driver) error {
return err return err
} }
provider.UserAgent.Prepend(fmt.Sprintf("docker-machine/v%d", version.APIVersion)) c.Provider = provider
if d.Insecure { c.Provider.UserAgent.Prepend(fmt.Sprintf("docker-machine/v%d", version.APIVersion))
// Configure custom TLS settings.
config := &tls.Config{InsecureSkipVerify: true}
transport := &http.Transport{TLSClientConfig: config}
provider.HTTPClient.Transport = transport
}
err = openstack.Authenticate(provider, opts) err = c.SetTLSConfig(d)
if err != nil { if err != nil {
return err return err
} }
c.Provider = provider err = openstack.Authenticate(c.Provider, opts)
if err != nil {
return err
}
return nil return nil
} }
func (c *GenericClient) SetTLSConfig(d *Driver) error {
config := &tls.Config{}
config.InsecureSkipVerify = d.Insecure
if d.CaCert != "" {
// Use custom CA certificate(s) for root of trust
certpool := x509.NewCertPool()
pem, err := ioutil.ReadFile(d.CaCert)
if err != nil {
log.Error("Unable to read specified CA certificate(s)")
return err
}
ok := certpool.AppendCertsFromPEM(pem)
if !ok {
return fmt.Errorf("Ill-formed CA certificate(s) PEM file")
}
config.RootCAs = certpool
}
transport := &http.Transport{TLSClientConfig: config}
c.Provider.HTTPClient.Transport = transport
return nil
}

View File

@ -20,6 +20,7 @@ type Driver struct {
AuthUrl string AuthUrl string
ActiveTimeout int ActiveTimeout int
Insecure bool Insecure bool
CaCert string
DomainID string DomainID string
DomainName string DomainName string
Username string Username string
@ -66,6 +67,12 @@ func (d *Driver) GetCreateFlags() []mcnflag.Flag {
Name: "openstack-insecure", Name: "openstack-insecure",
Usage: "Disable TLS credential checking.", Usage: "Disable TLS credential checking.",
}, },
mcnflag.StringFlag{
EnvVar: "OS_CACERT",
Name: "openstack-cacert",
Usage: "CA certificate bundle to verify against",
Value: "",
},
mcnflag.StringFlag{ mcnflag.StringFlag{
EnvVar: "OS_DOMAIN_ID", EnvVar: "OS_DOMAIN_ID",
Name: "openstack-domain-id", Name: "openstack-domain-id",
@ -252,6 +259,7 @@ func (d *Driver) SetConfigFromFlags(flags drivers.DriverOptions) error {
d.AuthUrl = flags.String("openstack-auth-url") d.AuthUrl = flags.String("openstack-auth-url")
d.ActiveTimeout = flags.Int("openstack-active-timeout") d.ActiveTimeout = flags.Int("openstack-active-timeout")
d.Insecure = flags.Bool("openstack-insecure") d.Insecure = flags.Bool("openstack-insecure")
d.CaCert = flags.String("openstack-cacert")
d.DomainID = flags.String("openstack-domain-id") d.DomainID = flags.String("openstack-domain-id")
d.DomainName = flags.String("openstack-domain-name") d.DomainName = flags.String("openstack-domain-name")
d.Username = flags.String("openstack-username") d.Username = flags.String("openstack-username")