mirror of
https://github.com/minio/minio.git
synced 2024-12-25 06:35:56 -05:00
Fix vault client to autorenew or reauthenticate (#7161)
Switch to Vault API's Renewer for token renewal.If token can no longer be renewed, reauthenticate to get a fresh token.
This commit is contained in:
parent
64b5701971
commit
3467460456
@ -23,6 +23,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
vault "github.com/hashicorp/vault/api"
|
vault "github.com/hashicorp/vault/api"
|
||||||
|
"github.com/minio/minio/cmd/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -63,6 +64,7 @@ type vaultService struct {
|
|||||||
config *VaultConfig
|
config *VaultConfig
|
||||||
client *vault.Client
|
client *vault.Client
|
||||||
leaseDuration time.Duration
|
leaseDuration time.Duration
|
||||||
|
tokenRenewer *vault.Renewer
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ KMS = (*vaultService)(nil) // compiler check that *vaultService implements KMS
|
var _ KMS = (*vaultService)(nil) // compiler check that *vaultService implements KMS
|
||||||
@ -120,42 +122,80 @@ func NewVault(config VaultConfig) (KMS, error) {
|
|||||||
if config.Namespace != "" {
|
if config.Namespace != "" {
|
||||||
client.SetNamespace(config.Namespace)
|
client.SetNamespace(config.Namespace)
|
||||||
}
|
}
|
||||||
|
v := &vaultService{client: client, config: &config}
|
||||||
|
|
||||||
payload := map[string]interface{}{
|
if err := v.authenticate(); err != nil {
|
||||||
"role_id": config.Auth.AppRole.ID,
|
|
||||||
"secret_id": config.Auth.AppRole.Secret,
|
|
||||||
}
|
|
||||||
resp, err := client.Logical().Write("auth/approle/login", payload)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if resp.Auth == nil {
|
|
||||||
return nil, ErrKMSAuthLogin
|
|
||||||
}
|
|
||||||
|
|
||||||
client.SetToken(resp.Auth.ClientToken)
|
|
||||||
v := &vaultService{client: client, config: &config, leaseDuration: time.Duration(resp.Auth.LeaseDuration)}
|
|
||||||
v.renewToken()
|
|
||||||
return v, nil
|
return v, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// renewToken starts a new go-routine which renews
|
// reauthenticate() tries to login in 1 minute
|
||||||
// the vault authentication token periodically.
|
// intervals until successful.
|
||||||
func (v *vaultService) renewToken() {
|
func (v *vaultService) reauthenticate() {
|
||||||
retryDelay := 1 * time.Minute
|
retryDelay := 1 * time.Minute
|
||||||
go func() {
|
go func() {
|
||||||
for {
|
for {
|
||||||
s, err := v.client.Auth().Token().RenewSelf(int(v.leaseDuration))
|
if err := v.authenticate(); err != nil {
|
||||||
if err != nil {
|
|
||||||
time.Sleep(retryDelay)
|
time.Sleep(retryDelay)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
nextRenew := s.Auth.LeaseDuration / 2
|
return
|
||||||
time.Sleep(time.Duration(nextRenew) * time.Second)
|
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// renewer calls vault client's renewer that automatically
|
||||||
|
// renews secret periodically
|
||||||
|
func (v *vaultService) renewer(secret *vault.Secret) {
|
||||||
|
renewer, err := v.client.NewRenewer(&vault.RenewerInput{
|
||||||
|
Secret: secret,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
logger.FatalIf(err, "crypto: hashicorp vault token renewer could not be started")
|
||||||
|
}
|
||||||
|
v.tokenRenewer = renewer
|
||||||
|
go renewer.Renew()
|
||||||
|
defer renewer.Stop()
|
||||||
|
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case err := <-renewer.DoneCh():
|
||||||
|
if err != nil {
|
||||||
|
v.reauthenticate()
|
||||||
|
renewer.Stop()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Renewal is now over
|
||||||
|
case renewal := <-renewer.RenewCh():
|
||||||
|
v.leaseDuration = time.Duration(renewal.Secret.Auth.LeaseDuration)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// authenticate logs the app to vault, and starts the auto renewer
|
||||||
|
// before secret expires
|
||||||
|
func (v *vaultService) authenticate() (err error) {
|
||||||
|
payload := map[string]interface{}{
|
||||||
|
"role_id": v.config.Auth.AppRole.ID,
|
||||||
|
"secret_id": v.config.Auth.AppRole.Secret,
|
||||||
|
}
|
||||||
|
var secret *vault.Secret
|
||||||
|
secret, err = v.client.Logical().Write("auth/approle/login", payload)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if secret.Auth == nil {
|
||||||
|
err = ErrKMSAuthLogin
|
||||||
|
return
|
||||||
|
}
|
||||||
|
v.client.SetToken(secret.Auth.ClientToken)
|
||||||
|
v.leaseDuration = time.Duration(secret.Auth.LeaseDuration)
|
||||||
|
go v.renewer(secret)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// GenerateKey returns a new plaintext key, generated by the KMS,
|
// GenerateKey returns a new plaintext key, generated by the KMS,
|
||||||
// and a sealed version of this plaintext key encrypted using the
|
// and a sealed version of this plaintext key encrypted using the
|
||||||
// named key referenced by keyID. It also binds the generated key
|
// named key referenced by keyID. It also binds the generated key
|
||||||
|
Loading…
Reference in New Issue
Block a user