github.com/vnpaycloud-console/gophercloud/v2@v2.0.5/openstack/config/clouds/tls.go (about)

     1  package clouds
     2  
     3  import (
     4  	"bytes"
     5  	"crypto/tls"
     6  	"crypto/x509"
     7  	"fmt"
     8  	"os"
     9  	"path"
    10  	"strings"
    11  )
    12  
    13  func computeTLSConfig(cloud Cloud, options cloudOpts) (*tls.Config, error) {
    14  	tlsConfig := new(tls.Config)
    15  	if caCertPath := coalesce(options.caCertPath, os.Getenv("OS_CACERT"), cloud.CACertFile); caCertPath != "" {
    16  		caCertPath, err := resolveTilde(caCertPath)
    17  		if err != nil {
    18  			return nil, fmt.Errorf("failed to resolve user home directory: %w", err)
    19  		}
    20  
    21  		caCert, err := os.ReadFile(caCertPath)
    22  		if err != nil {
    23  			return nil, fmt.Errorf("failed to open the CA cert file: %w", err)
    24  		}
    25  
    26  		caCertPool := x509.NewCertPool()
    27  		if ok := caCertPool.AppendCertsFromPEM(bytes.TrimSpace(caCert)); !ok {
    28  			return nil, fmt.Errorf("failed to parse the CA Cert from %q", caCertPath)
    29  		}
    30  		tlsConfig.RootCAs = caCertPool
    31  	}
    32  
    33  	tlsConfig.InsecureSkipVerify = func() bool {
    34  		if options.insecure != nil {
    35  			return *options.insecure
    36  		}
    37  		if cloud.Verify != nil {
    38  			return !*cloud.Verify
    39  		}
    40  		return false
    41  	}()
    42  
    43  	if clientCertPath, clientKeyPath := coalesce(options.clientCertPath, os.Getenv("OS_CERT"), cloud.ClientCertFile), coalesce(options.clientKeyPath, os.Getenv("OS_KEY"), cloud.ClientKeyFile); clientCertPath != "" && clientKeyPath != "" {
    44  		clientCertPath, err := resolveTilde(clientCertPath)
    45  		if err != nil {
    46  			return nil, fmt.Errorf("failed to resolve user home directory in client cert path: %w", err)
    47  		}
    48  		clientKeyPath, err := resolveTilde(clientKeyPath)
    49  		if err != nil {
    50  			return nil, fmt.Errorf("failed to resolve user home directory in client cert key path: %w", err)
    51  		}
    52  
    53  		clientCert, err := os.ReadFile(clientCertPath)
    54  		if err != nil {
    55  			return nil, fmt.Errorf("failed to read the client cert file: %w", err)
    56  		}
    57  
    58  		clientKey, err := os.ReadFile(clientKeyPath)
    59  		if err != nil {
    60  			return nil, fmt.Errorf("failed to read the client cert key file: %w", err)
    61  		}
    62  
    63  		cert, err := tls.X509KeyPair(clientCert, clientKey)
    64  		if err != nil {
    65  			return nil, err
    66  		}
    67  
    68  		tlsConfig.Certificates = []tls.Certificate{cert}
    69  	} else if clientCertPath != "" && clientKeyPath == "" {
    70  		return nil, fmt.Errorf("client cert is set, but client cert key is missing")
    71  	} else if clientCertPath == "" && clientKeyPath != "" {
    72  		return nil, fmt.Errorf("client cert key is set, but client cert is missing")
    73  	}
    74  
    75  	return tlsConfig, nil
    76  }
    77  
    78  func resolveTilde(p string) (string, error) {
    79  	if after := strings.TrimPrefix(p, "~/"); after != p {
    80  		h, err := os.UserHomeDir()
    81  		if err != nil {
    82  			return "", fmt.Errorf("failed to resolve user home directory: %w", err)
    83  		}
    84  		return path.Join(h, after), nil
    85  	}
    86  	return p, nil
    87  }