open-vault/command/agent/auth/auth_test.go

197 lines
4.6 KiB
Go
Raw Normal View History

2018-07-25 02:02:27 +00:00
package auth
import (
"context"
"net/http"
2018-07-25 02:02:27 +00:00
"testing"
"time"
"github.com/hashicorp/go-hclog"
2018-07-25 02:02:27 +00:00
"github.com/hashicorp/vault/api"
"github.com/hashicorp/vault/builtin/credential/userpass"
vaulthttp "github.com/hashicorp/vault/http"
"github.com/hashicorp/vault/sdk/helper/logging"
"github.com/hashicorp/vault/sdk/logical"
2018-07-25 02:02:27 +00:00
"github.com/hashicorp/vault/vault"
)
type userpassTestMethod struct{}
func newUserpassTestMethod(t *testing.T, client *api.Client) AuthMethod {
err := client.Sys().EnableAuthWithOptions("userpass", &api.EnableAuthOptions{
Type: "userpass",
Config: api.AuthConfigInput{
DefaultLeaseTTL: "1s",
MaxLeaseTTL: "3s",
},
})
if err != nil {
t.Fatal(err)
}
return &userpassTestMethod{}
}
func (u *userpassTestMethod) Authenticate(_ context.Context, client *api.Client) (string, http.Header, map[string]interface{}, error) {
_, err := client.Logical().Write("auth/userpass/users/foo", map[string]interface{}{
2018-07-25 02:02:27 +00:00
"password": "bar",
})
if err != nil {
return "", nil, nil, err
2018-07-25 02:02:27 +00:00
}
return "auth/userpass/login/foo", nil, map[string]interface{}{
2018-07-25 02:02:27 +00:00
"password": "bar",
}, nil
}
func (u *userpassTestMethod) NewCreds() chan struct{} {
return nil
}
func (u *userpassTestMethod) CredSuccess() {
}
func (u *userpassTestMethod) Shutdown() {
}
func TestAuthHandler(t *testing.T) {
logger := logging.NewVaultLogger(hclog.Trace)
coreConfig := &vault.CoreConfig{
Logger: logger,
CredentialBackends: map[string]logical.Factory{
"userpass": userpass.Factory,
},
}
cluster := vault.NewTestCluster(t, coreConfig, &vault.TestClusterOptions{
HandlerFunc: vaulthttp.Handler,
})
cluster.Start()
defer cluster.Cleanup()
vault.TestWaitActive(t, cluster.Cores[0].Core)
client := cluster.Cores[0].Client
ctx, cancelFunc := context.WithCancel(context.Background())
ah := NewAuthHandler(&AuthHandlerConfig{
Logger: logger.Named("auth.handler"),
Client: client,
})
am := newUserpassTestMethod(t, client)
errCh := make(chan error)
go func() {
errCh <- ah.Run(ctx, am)
}()
2018-07-25 02:02:27 +00:00
// Consume tokens so we don't block
stopTime := time.Now().Add(5 * time.Second)
closed := false
consumption:
for {
select {
case err := <-errCh:
if err != nil {
t.Fatal(err)
}
break consumption
2018-07-25 02:02:27 +00:00
case <-ah.OutputCh:
Vault Agent Template (#7652) * Vault Agent Template: parse templates (#7540) * add template config parsing, but it's wrong b/c it's not using mapstructure * parsing consul templates in agent config * add additional test to configuration parsing, to cover basics * another test fixture, rework simple test into table * refactor into table test * rename test * remove flattenKeys and add other test fixture * Update command/agent/config/config.go Co-Authored-By: Jim Kalafut <jkalafut@hashicorp.com> * return the decode error instead of swallowing it * Update command/agent/config/config_test.go Co-Authored-By: Jim Kalafut <jkalafut@hashicorp.com> * go mod tidy * change error checking style * Add agent template doc * TemplateServer: render secrets with Consul Template (#7621) * add template config parsing, but it's wrong b/c it's not using mapstructure * parsing consul templates in agent config * add additional test to configuration parsing, to cover basics * another test fixture, rework simple test into table * refactor into table test * rename test * remove flattenKeys and add other test fixture * add template package * WIP: add runner * fix panic, actually copy templates, etc * rework how the config.Vault is created and enable reading from the environment * this was supposed to be a part of the prior commit * move/add methods to testhelpers for converting some values to pointers * use new methods in testhelpers * add an unblock channel to block agent until a template has been rendered * add note * unblock if there are no templates * cleanups * go mod tidy * remove dead code * simple test to starT * add simple, empty templates test * Update package doc, error logs, and add missing close() on channel * update code comment to be clear what I'm referring to * have template.NewServer return a (<- chan) type, even though it's a normal chan, as a better practice to enforce reading only * Update command/agent.go Co-Authored-By: Jim Kalafut <jkalafut@hashicorp.com> * update with test * Add README and doc.go to the command/agent directory (#7503) * Add README and doc.go to the command/agent directory * Add link to website * address feedback for agent.go * updated with feedback from Calvin * Rework template.Server to export the unblock channel, and remove it from the NewServer function * apply feedback from Nick * fix/restructure rendering test * Add pointerutil package for converting types to their pointers * Remove pointer helper methods; use sdk/helper/pointerutil instead * update newRunnerConfig to use pointerutil and empty strings * only wait for unblock if template server is initialized * drain the token channel in this test * conditionally send on channel
2019-10-18 21:21:46 +00:00
case <-ah.TemplateTokenCh:
// Nothing
2018-07-25 02:02:27 +00:00
case <-time.After(stopTime.Sub(time.Now())):
if !closed {
cancelFunc()
closed = true
}
}
}
}
func TestAgentBackoff(t *testing.T) {
max := 1024 * time.Second
backoff := newAgentBackoff(defaultMinBackoff, max)
// Test initial value
if backoff.current != defaultMinBackoff {
t.Fatalf("expected 1s initial backoff, got: %v", backoff.current)
}
// Test that backoff values are in expected range (75-100% of 2*previous)
for i := 0; i < 9; i++ {
old := backoff.current
backoff.next()
expMax := 2 * old
expMin := 3 * expMax / 4
if backoff.current < expMin || backoff.current > expMax {
t.Fatalf("expected backoff in range %v to %v, got: %v", expMin, expMax, backoff)
}
}
// Test that backoff is capped
for i := 0; i < 100; i++ {
backoff.next()
if backoff.current > max {
t.Fatalf("backoff exceeded max of 100s: %v", backoff)
}
}
// Test reset
backoff.reset()
if backoff.current != defaultMinBackoff {
t.Fatalf("expected 1s backoff after reset, got: %v", backoff.current)
}
}
func TestAgentMinBackoffCustom(t *testing.T) {
type test struct {
minBackoff time.Duration
want time.Duration
}
tests := []test{
{minBackoff: 0 * time.Second, want: 1 * time.Second},
{minBackoff: 1 * time.Second, want: 1 * time.Second},
{minBackoff: 5 * time.Second, want: 5 * time.Second},
{minBackoff: 10 * time.Second, want: 10 * time.Second},
}
for _, test := range tests {
max := 1024 * time.Second
backoff := newAgentBackoff(test.minBackoff, max)
// Test initial value
if backoff.current != test.want {
t.Fatalf("expected %d initial backoff, got: %v", test.want, backoff.current)
}
// Test that backoff values are in expected range (75-100% of 2*previous)
for i := 0; i < 5; i++ {
old := backoff.current
backoff.next()
expMax := 2 * old
expMin := 3 * expMax / 4
if backoff.current < expMin || backoff.current > expMax {
t.Fatalf("expected backoff in range %v to %v, got: %v", expMin, expMax, backoff)
}
}
// Test that backoff is capped
for i := 0; i < 100; i++ {
backoff.next()
if backoff.current > max {
t.Fatalf("backoff exceeded max of 100s: %v", backoff)
}
}
// Test reset
backoff.reset()
if backoff.current != test.want {
t.Fatalf("expected %d backoff after reset, got: %v", test.want, backoff.current)
}
}
}