Fix: Optionally reload x509 key-pair from disk on agent auto-auth (#19002)
* Optionally reload x509 key-pair from disk * Document 'reload' config value * Added changelog release note
This commit is contained in:
parent
2fcaec4b21
commit
7469b0828a
|
@ -0,0 +1,3 @@
|
||||||
|
```release-note:improvement
|
||||||
|
agent: Added `reload` option to cert auth configuration in case of external renewals of local x509 key-pairs.
|
||||||
|
```
|
|
@ -23,6 +23,7 @@ type certMethod struct {
|
||||||
caCert string
|
caCert string
|
||||||
clientCert string
|
clientCert string
|
||||||
clientKey string
|
clientKey string
|
||||||
|
reload bool
|
||||||
|
|
||||||
// Client is the cached client to use if cert info was provided.
|
// Client is the cached client to use if cert info was provided.
|
||||||
client *api.Client
|
client *api.Client
|
||||||
|
@ -76,6 +77,14 @@ func NewCertAuthMethod(conf *auth.AuthConfig) (auth.AuthMethod, error) {
|
||||||
return nil, errors.New("could not convert 'cert_key' config value to string")
|
return nil, errors.New("could not convert 'cert_key' config value to string")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
reload, ok := conf.Config["reload"]
|
||||||
|
if ok {
|
||||||
|
c.reload, ok = reload.(bool)
|
||||||
|
if !ok {
|
||||||
|
return nil, errors.New("could not convert 'reload' config value to bool")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return c, nil
|
return c, nil
|
||||||
|
@ -111,7 +120,7 @@ func (c *certMethod) AuthClient(client *api.Client) (*api.Client, error) {
|
||||||
|
|
||||||
if c.caCert != "" || (c.clientKey != "" && c.clientCert != "") {
|
if c.caCert != "" || (c.clientKey != "" && c.clientCert != "") {
|
||||||
// Return cached client if present
|
// Return cached client if present
|
||||||
if c.client != nil {
|
if c.client != nil && !c.reload {
|
||||||
return c.client, nil
|
return c.client, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -133,3 +133,59 @@ func TestCertAuthMethod_AuthClient_withCerts(t *testing.T) {
|
||||||
t.Fatal("expected client from AuthClient to return back a cached client")
|
t.Fatal("expected client from AuthClient to return back a cached client")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCertAuthMethod_AuthClient_withCertsReload(t *testing.T) {
|
||||||
|
clientCert, err := os.Open("./test-fixtures/keys/cert.pem")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
defer clientCert.Close()
|
||||||
|
|
||||||
|
clientKey, err := os.Open("./test-fixtures/keys/key.pem")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
defer clientKey.Close()
|
||||||
|
|
||||||
|
config := &auth.AuthConfig{
|
||||||
|
Logger: hclog.NewNullLogger(),
|
||||||
|
MountPath: "cert-test",
|
||||||
|
Config: map[string]interface{}{
|
||||||
|
"name": "with-certs-reloaded",
|
||||||
|
"client_cert": clientCert.Name(),
|
||||||
|
"client_key": clientKey.Name(),
|
||||||
|
"reload": true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
method, err := NewCertAuthMethod(config)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
client, err := api.NewClient(nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
clientToUse, err := method.(auth.AuthMethodWithClient).AuthClient(client)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if client == clientToUse {
|
||||||
|
t.Fatal("expected client from AuthClient to be different from original client")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call AuthClient again to get back a new client with reloaded certificates
|
||||||
|
reloadedClient, err := method.(auth.AuthMethodWithClient).AuthClient(client)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if reloadedClient == clientToUse {
|
||||||
|
t.Fatal("expected client from AuthClient to return back a new client")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -30,3 +30,6 @@ Stanza](/vault/docs/agent#vault-stanza).
|
||||||
|
|
||||||
- `client_key` `(string: optional)` - Path on the local disk to a single
|
- `client_key` `(string: optional)` - Path on the local disk to a single
|
||||||
PEM-encoded private key matching the client certificate from client_cert.
|
PEM-encoded private key matching the client certificate from client_cert.
|
||||||
|
|
||||||
|
- `reload` `(bool: optional, default: false)` - If true, causes the local x509 key-pair to be reloaded from disk on each authentication attempt.
|
||||||
|
This is useful in situations where client certificates are short-lived and automatically renewed.
|
||||||
|
|
Loading…
Reference in New Issue