Files
opentf/builtin/providers/openstack/config.go
Gavin Williams c63ad9c0f8 state/remote/swift: Support Openstack request logging (#13583)
* provider/openstack: Expose LogRoundTripper fields externally

* state/remote/swift: Add support for debugging Openstack calls using
OS_DEBUG env variable.

* provider/openstack: Update LogRoundTripper to log headers aswell as body.

* Add `RedactHeaders` function in order to redact sensitive http Headers.
Refactor `logRequest` and `logResponse` to use `RedactHeaders` func.
2017-04-15 17:11:28 +03:00

193 lines
4.8 KiB
Go

package openstack
import (
"crypto/tls"
"crypto/x509"
"fmt"
"net/http"
"os"
"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/openstack"
"github.com/gophercloud/gophercloud/openstack/objectstorage/v1/swauth"
"github.com/hashicorp/terraform/helper/pathorcontents"
)
type Config struct {
CACertFile string
ClientCertFile string
ClientKeyFile string
DomainID string
DomainName string
EndpointType string
IdentityEndpoint string
Insecure bool
Password string
Swauth bool
TenantID string
TenantName string
Token string
Username string
UserID string
osClient *gophercloud.ProviderClient
}
func (c *Config) loadAndValidate() error {
validEndpoint := false
validEndpoints := []string{
"internal", "internalURL",
"admin", "adminURL",
"public", "publicURL",
"",
}
for _, endpoint := range validEndpoints {
if c.EndpointType == endpoint {
validEndpoint = true
}
}
if !validEndpoint {
return fmt.Errorf("Invalid endpoint type provided")
}
ao := gophercloud.AuthOptions{
DomainID: c.DomainID,
DomainName: c.DomainName,
IdentityEndpoint: c.IdentityEndpoint,
Password: c.Password,
TenantID: c.TenantID,
TenantName: c.TenantName,
TokenID: c.Token,
Username: c.Username,
UserID: c.UserID,
}
client, err := openstack.NewClient(ao.IdentityEndpoint)
if err != nil {
return err
}
config := &tls.Config{}
if c.CACertFile != "" {
caCert, _, err := pathorcontents.Read(c.CACertFile)
if err != nil {
return fmt.Errorf("Error reading CA Cert: %s", err)
}
caCertPool := x509.NewCertPool()
caCertPool.AppendCertsFromPEM([]byte(caCert))
config.RootCAs = caCertPool
}
if c.Insecure {
config.InsecureSkipVerify = true
}
if c.ClientCertFile != "" && c.ClientKeyFile != "" {
clientCert, _, err := pathorcontents.Read(c.ClientCertFile)
if err != nil {
return fmt.Errorf("Error reading Client Cert: %s", err)
}
clientKey, _, err := pathorcontents.Read(c.ClientKeyFile)
if err != nil {
return fmt.Errorf("Error reading Client Key: %s", err)
}
cert, err := tls.X509KeyPair([]byte(clientCert), []byte(clientKey))
if err != nil {
return err
}
config.Certificates = []tls.Certificate{cert}
config.BuildNameToCertificate()
}
// if OS_DEBUG is set, log the requests and responses
var osDebug bool
if os.Getenv("OS_DEBUG") != "" {
osDebug = true
}
transport := &http.Transport{Proxy: http.ProxyFromEnvironment, TLSClientConfig: config}
client.HTTPClient = http.Client{
Transport: &LogRoundTripper{
Rt: transport,
OsDebug: osDebug,
},
}
// If using Swift Authentication, there's no need to validate authentication normally.
if !c.Swauth {
err = openstack.Authenticate(client, ao)
if err != nil {
return err
}
}
c.osClient = client
return nil
}
func (c *Config) blockStorageV1Client(region string) (*gophercloud.ServiceClient, error) {
return openstack.NewBlockStorageV1(c.osClient, gophercloud.EndpointOpts{
Region: region,
Availability: c.getEndpointType(),
})
}
func (c *Config) blockStorageV2Client(region string) (*gophercloud.ServiceClient, error) {
return openstack.NewBlockStorageV2(c.osClient, gophercloud.EndpointOpts{
Region: region,
Availability: c.getEndpointType(),
})
}
func (c *Config) computeV2Client(region string) (*gophercloud.ServiceClient, error) {
return openstack.NewComputeV2(c.osClient, gophercloud.EndpointOpts{
Region: region,
Availability: c.getEndpointType(),
})
}
func (c *Config) imageV2Client(region string) (*gophercloud.ServiceClient, error) {
return openstack.NewImageServiceV2(c.osClient, gophercloud.EndpointOpts{
Region: region,
Availability: c.getEndpointType(),
})
}
func (c *Config) networkingV2Client(region string) (*gophercloud.ServiceClient, error) {
return openstack.NewNetworkV2(c.osClient, gophercloud.EndpointOpts{
Region: region,
Availability: c.getEndpointType(),
})
}
func (c *Config) objectStorageV1Client(region string) (*gophercloud.ServiceClient, error) {
// If Swift Authentication is being used, return a swauth client.
if c.Swauth {
return swauth.NewObjectStorageV1(c.osClient, swauth.AuthOpts{
User: c.Username,
Key: c.Password,
})
}
return openstack.NewObjectStorageV1(c.osClient, gophercloud.EndpointOpts{
Region: region,
Availability: c.getEndpointType(),
})
}
func (c *Config) getEndpointType() gophercloud.Availability {
if c.EndpointType == "internal" || c.EndpointType == "internalURL" {
return gophercloud.AvailabilityInternal
}
if c.EndpointType == "admin" || c.EndpointType == "adminURL" {
return gophercloud.AvailabilityAdmin
}
return gophercloud.AvailabilityPublic
}