Add support for client certificates to -output-curl-string (#13660)
* Add support for client certificates to -output-curl-string I did not write tests for this feature as -output-curl-string was not already tested and this is a simple change. Because the name of the certificates would be lost once loaded I added fields to Config to keep track of them. I did not add a public method for the user to set them explicitely as I don't think anyone would need this functionnality outside of the Vault CLI. Closes https://github.com/hashicorp/vault/issues/13376 * Add changelog * Add lock in ConfigureTLS
This commit is contained in:
parent
974dbf6082
commit
fb4b85d921
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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" {
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
```release-note:bug
|
||||
core: `-output-curl-string` now properly sets cURL options for client and CA
|
||||
certificates.
|
||||
```
|
Loading…
Reference in New Issue