c732b215f0
The `namespace` field was not included in the equality check between old and new Vault configurations, which meant that a Vault config change that only changed the namespace would not be detected as a change and the clients would not be reloaded. Also, the comparison for boolean fields such as `enabled` and `allow_unauthenticated` was on the pointer and not the value of that pointer, which results in spurious reloads in real config reload that is easily missed in typical test scenarios. Includes a minor refactor of the order of fields for `Copy` and `Merge` to match the struct fields in hopes it makes it harder to make this mistake in the future, as well as additional test coverage.
150 lines
4.4 KiB
Go
150 lines
4.4 KiB
Go
package nomad
|
|
|
|
import (
|
|
"context"
|
|
"time"
|
|
|
|
"github.com/hashicorp/nomad/nomad/structs"
|
|
"github.com/hashicorp/nomad/nomad/structs/config"
|
|
vapi "github.com/hashicorp/vault/api"
|
|
)
|
|
|
|
// TestVaultClient is a Vault client appropriate for use during testing. Its
|
|
// behavior is programmable such that endpoints can be tested under various
|
|
// circumstances.
|
|
type TestVaultClient struct {
|
|
// LookupTokenErrors maps a token to an error that will be returned by the
|
|
// LookupToken call
|
|
LookupTokenErrors map[string]error
|
|
|
|
// LookupTokenSecret maps a token to the Vault secret that will be returned
|
|
// by the LookupToken call
|
|
LookupTokenSecret map[string]*vapi.Secret
|
|
|
|
// CreateTokenErrors maps a token to an error that will be returned by the
|
|
// CreateToken call
|
|
CreateTokenErrors map[string]map[string]error
|
|
|
|
// CreateTokenSecret maps a token to the Vault secret that will be returned
|
|
// by the CreateToken call
|
|
CreateTokenSecret map[string]map[string]*vapi.Secret
|
|
|
|
RevokedTokens []*structs.VaultAccessor
|
|
}
|
|
|
|
func (v *TestVaultClient) LookupToken(ctx context.Context, token string) (*vapi.Secret, error) {
|
|
var secret *vapi.Secret
|
|
var err error
|
|
|
|
if v.LookupTokenSecret != nil {
|
|
secret = v.LookupTokenSecret[token]
|
|
}
|
|
if v.LookupTokenErrors != nil {
|
|
err = v.LookupTokenErrors[token]
|
|
}
|
|
|
|
return secret, err
|
|
}
|
|
|
|
// SetLookupTokenError sets the error that will be returned by the token
|
|
// lookup
|
|
func (v *TestVaultClient) SetLookupTokenError(token string, err error) {
|
|
if v.LookupTokenErrors == nil {
|
|
v.LookupTokenErrors = make(map[string]error)
|
|
}
|
|
|
|
v.LookupTokenErrors[token] = err
|
|
}
|
|
|
|
// SetLookupTokenSecret sets the secret that will be returned by the token
|
|
// lookup
|
|
func (v *TestVaultClient) SetLookupTokenSecret(token string, secret *vapi.Secret) {
|
|
if v.LookupTokenSecret == nil {
|
|
v.LookupTokenSecret = make(map[string]*vapi.Secret)
|
|
}
|
|
|
|
v.LookupTokenSecret[token] = secret
|
|
}
|
|
|
|
// SetLookupTokenAllowedPolicies is a helper that adds a secret that allows the
|
|
// given policies
|
|
func (v *TestVaultClient) SetLookupTokenAllowedPolicies(token string, policies []string) {
|
|
s := &vapi.Secret{
|
|
Data: map[string]interface{}{
|
|
"policies": policies,
|
|
},
|
|
}
|
|
|
|
v.SetLookupTokenSecret(token, s)
|
|
}
|
|
|
|
func (v *TestVaultClient) CreateToken(ctx context.Context, a *structs.Allocation, task string) (*vapi.Secret, error) {
|
|
var secret *vapi.Secret
|
|
var err error
|
|
|
|
if v.CreateTokenSecret != nil {
|
|
tasks := v.CreateTokenSecret[a.ID]
|
|
if tasks != nil {
|
|
secret = tasks[task]
|
|
}
|
|
}
|
|
if v.CreateTokenErrors != nil {
|
|
tasks := v.CreateTokenErrors[a.ID]
|
|
if tasks != nil {
|
|
err = tasks[task]
|
|
}
|
|
}
|
|
|
|
return secret, err
|
|
}
|
|
|
|
// SetCreateTokenError sets the error that will be returned by the token
|
|
// creation
|
|
func (v *TestVaultClient) SetCreateTokenError(allocID, task string, err error) {
|
|
if v.CreateTokenErrors == nil {
|
|
v.CreateTokenErrors = make(map[string]map[string]error)
|
|
}
|
|
|
|
tasks := v.CreateTokenErrors[allocID]
|
|
if tasks == nil {
|
|
tasks = make(map[string]error)
|
|
v.CreateTokenErrors[allocID] = tasks
|
|
}
|
|
|
|
v.CreateTokenErrors[allocID][task] = err
|
|
}
|
|
|
|
// SetCreateTokenSecret sets the secret that will be returned by the token
|
|
// creation
|
|
func (v *TestVaultClient) SetCreateTokenSecret(allocID, task string, secret *vapi.Secret) {
|
|
if v.CreateTokenSecret == nil {
|
|
v.CreateTokenSecret = make(map[string]map[string]*vapi.Secret)
|
|
}
|
|
|
|
tasks := v.CreateTokenSecret[allocID]
|
|
if tasks == nil {
|
|
tasks = make(map[string]*vapi.Secret)
|
|
v.CreateTokenSecret[allocID] = tasks
|
|
}
|
|
|
|
v.CreateTokenSecret[allocID][task] = secret
|
|
}
|
|
|
|
func (v *TestVaultClient) RevokeTokens(ctx context.Context, accessors []*structs.VaultAccessor, committed bool) error {
|
|
v.RevokedTokens = append(v.RevokedTokens, accessors...)
|
|
return nil
|
|
}
|
|
|
|
func (v *TestVaultClient) MarkForRevocation(accessors []*structs.VaultAccessor) error {
|
|
v.RevokedTokens = append(v.RevokedTokens, accessors...)
|
|
return nil
|
|
}
|
|
|
|
func (v *TestVaultClient) Stop() {}
|
|
func (v *TestVaultClient) SetActive(enabled bool) {}
|
|
func (v *TestVaultClient) GetConfig() *config.VaultConfig { return nil }
|
|
func (v *TestVaultClient) SetConfig(config *config.VaultConfig) error { return nil }
|
|
func (v *TestVaultClient) Running() bool { return true }
|
|
func (v *TestVaultClient) Stats() map[string]string { return map[string]string{} }
|
|
func (v *TestVaultClient) EmitStats(period time.Duration, stopCh <-chan struct{}) {}
|