mirror of
https://github.com/hashicorp/vault.git
synced 2025-08-13 18:17:02 +02:00
* Adding explicit MPL license for sub-package. This directory and its subdirectories (packages) contain files licensed with the MPLv2 `LICENSE` file in this directory and are intentionally licensed separately from the BSL `LICENSE` file at the root of this repository. * Adding explicit MPL license for sub-package. This directory and its subdirectories (packages) contain files licensed with the MPLv2 `LICENSE` file in this directory and are intentionally licensed separately from the BSL `LICENSE` file at the root of this repository. * Updating the license from MPL to Business Source License. Going forward, this project will be licensed under the Business Source License v1.1. Please see our blog post for more details at https://hashi.co/bsl-blog, FAQ at www.hashicorp.com/licensing-faq, and details of the license at www.hashicorp.com/bsl. * add missing license headers * Update copyright file headers to BUS-1.1 * Fix test that expected exact offset on hcl file --------- Co-authored-by: hashicorp-copywrite[bot] <110428419+hashicorp-copywrite[bot]@users.noreply.github.com> Co-authored-by: Sarah Thompson <sthompson@hashicorp.com> Co-authored-by: Brian Kassouf <bkassouf@hashicorp.com>
198 lines
4.6 KiB
Go
198 lines
4.6 KiB
Go
// Copyright (c) HashiCorp, Inc.
|
|
// SPDX-License-Identifier: BUSL-1.1
|
|
|
|
package auth
|
|
|
|
import (
|
|
"context"
|
|
"net/http"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/hashicorp/go-hclog"
|
|
"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"
|
|
"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{}{
|
|
"password": "bar",
|
|
})
|
|
if err != nil {
|
|
return "", nil, nil, err
|
|
}
|
|
return "auth/userpass/login/foo", nil, map[string]interface{}{
|
|
"password": "bar",
|
|
}, nil
|
|
}
|
|
|
|
func (u *userpassTestMethod) NewCreds() chan struct{} {
|
|
return nil
|
|
}
|
|
|
|
func (u *userpassTestMethod) CredSuccess() {
|
|
}
|
|
|
|
func (u *userpassTestMethod) Shutdown() {
|
|
}
|
|
|
|
func TestAuthHandler(t *testing.T) {
|
|
coreConfig := &vault.CoreConfig{
|
|
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: logging.NewVaultLogger(hclog.Trace).Named("auth.handler"),
|
|
Client: client,
|
|
})
|
|
|
|
am := newUserpassTestMethod(t, client)
|
|
errCh := make(chan error)
|
|
go func() {
|
|
errCh <- ah.Run(ctx, am)
|
|
}()
|
|
|
|
// 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
|
|
case <-ah.OutputCh:
|
|
case <-ah.TemplateTokenCh:
|
|
// Nothing
|
|
case <-time.After(stopTime.Sub(time.Now())):
|
|
if !closed {
|
|
cancelFunc()
|
|
closed = true
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestAgentBackoff(t *testing.T) {
|
|
max := 1024 * time.Second
|
|
backoff := newAutoAuthBackoff(defaultMinBackoff, max, false)
|
|
|
|
// 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 := newAutoAuthBackoff(test.minBackoff, max, false)
|
|
|
|
// 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)
|
|
}
|
|
}
|
|
}
|