diff --git a/api/client.go b/api/client.go index 0c86d15dc..4214e7ae4 100644 --- a/api/client.go +++ b/api/client.go @@ -132,6 +132,12 @@ type Config struct { // with the same client. Cloning a client will not clone this value. OutputCurlString bool + // curlCACert, curlCAPath, curlClientCert and curlClientKey are used to keep + // track of the name of the TLS certs and keys when OutputCurlString is set. + // Cloning a client will also not clone those values. + curlCACert, curlCAPath string + curlClientCert, curlClientKey string + // SRVLookup enables the client to lookup the host through DNS SRV lookup SRVLookup bool @@ -225,9 +231,9 @@ func DefaultConfig() *Config { return config } -// ConfigureTLS takes a set of TLS configurations and applies those to the -// HTTP client. -func (c *Config) ConfigureTLS(t *TLSConfig) error { +// configureTLS is a lock free version of ConfigureTLS that can be used in +// ReadEnvironment where the lock is already hold +func (c *Config) configureTLS(t *TLSConfig) error { if c.HttpClient == nil { c.HttpClient = DefaultConfig().HttpClient } @@ -244,11 +250,15 @@ func (c *Config) ConfigureTLS(t *TLSConfig) error { return err } foundClientCert = true + c.curlClientCert = t.ClientCert + c.curlClientKey = t.ClientKey case t.ClientCert != "" || t.ClientKey != "": return fmt.Errorf("both client cert and client key must be provided") } if t.CACert != "" || t.CAPath != "" { + c.curlCACert = t.CACert + c.curlCAPath = t.CAPath rootConfig := &rootcerts.Config{ CAFile: t.CACert, CAPath: t.CAPath, @@ -278,6 +288,15 @@ func (c *Config) ConfigureTLS(t *TLSConfig) error { return nil } +// ConfigureTLS takes a set of TLS configurations and applies those to the +// HTTP client. +func (c *Config) ConfigureTLS(t *TLSConfig) error { + c.modifyLock.Lock() + defer c.modifyLock.Unlock() + + return c.configureTLS(t) +} + // ReadEnvironment reads configuration information from the environment. If // there is an error, no configuration value is updated. func (c *Config) ReadEnvironment() error { @@ -382,7 +401,7 @@ func (c *Config) ReadEnvironment() error { c.SRVLookup = envSRVLookup c.Limiter = limit - if err := c.ConfigureTLS(t); err != nil { + if err := c.configureTLS(t); err != nil { return err } @@ -1122,6 +1141,10 @@ START: LastOutputStringError = &OutputStringError{ Request: req, TLSSkipVerify: c.config.HttpClient.Transport.(*http.Transport).TLSClientConfig.InsecureSkipVerify, + ClientCert: c.config.curlClientCert, + ClientKey: c.config.curlClientKey, + ClientCACert: c.config.curlCACert, + ClientCAPath: c.config.curlCAPath, } return nil, LastOutputStringError } diff --git a/api/output_string.go b/api/output_string.go index 8b654ad82..b30c06eee 100644 --- a/api/output_string.go +++ b/api/output_string.go @@ -15,9 +15,11 @@ var LastOutputStringError *OutputStringError type OutputStringError struct { *retryablehttp.Request - TLSSkipVerify bool - parsingError error - parsedCurlString string + TLSSkipVerify bool + ClientCACert, ClientCAPath string + ClientCert, ClientKey string + parsingError error + parsedCurlString string } func (d *OutputStringError) Error() string { @@ -46,6 +48,22 @@ func (d *OutputStringError) parseRequest() { if d.Request.Method != "GET" { d.parsedCurlString = fmt.Sprintf("%s-X %s ", d.parsedCurlString, d.Request.Method) } + if d.ClientCACert != "" { + clientCACert := strings.Replace(d.ClientCACert, "'", "'\"'\"'", -1) + d.parsedCurlString = fmt.Sprintf("%s--cacert '%s' ", d.parsedCurlString, clientCACert) + } + if d.ClientCAPath != "" { + clientCAPath := strings.Replace(d.ClientCAPath, "'", "'\"'\"'", -1) + d.parsedCurlString = fmt.Sprintf("%s--capath '%s' ", d.parsedCurlString, clientCAPath) + } + if d.ClientCert != "" { + clientCert := strings.Replace(d.ClientCert, "'", "'\"'\"'", -1) + d.parsedCurlString = fmt.Sprintf("%s--cert '%s' ", d.parsedCurlString, clientCert) + } + if d.ClientKey != "" { + clientKey := strings.Replace(d.ClientKey, "'", "'\"'\"'", -1) + d.parsedCurlString = fmt.Sprintf("%s--key '%s' ", d.parsedCurlString, clientKey) + } for k, v := range d.Request.Header { for _, h := range v { if strings.ToLower(k) == "x-vault-token" { diff --git a/changelog/13660.txt b/changelog/13660.txt new file mode 100644 index 000000000..1920afe34 --- /dev/null +++ b/changelog/13660.txt @@ -0,0 +1,4 @@ +```release-note:bug +core: `-output-curl-string` now properly sets cURL options for client and CA +certificates. +```