259 lines
6.2 KiB
Go
259 lines
6.2 KiB
Go
// Copyright (c) HashiCorp, Inc.
|
|
// SPDX-License-Identifier: MPL-2.0
|
|
|
|
package vault_test
|
|
|
|
import (
|
|
"fmt"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/go-test/deep"
|
|
"github.com/hashicorp/go-hclog"
|
|
"github.com/hashicorp/vault/api"
|
|
"github.com/hashicorp/vault/helper/testhelpers/corehelpers"
|
|
vaulthttp "github.com/hashicorp/vault/http"
|
|
"github.com/hashicorp/vault/sdk/helper/logging"
|
|
"github.com/hashicorp/vault/sdk/physical"
|
|
"github.com/hashicorp/vault/sdk/physical/inmem"
|
|
"github.com/hashicorp/vault/vault"
|
|
"github.com/hashicorp/vault/version"
|
|
)
|
|
|
|
func TestSystemBackend_InternalUIResultantACL(t *testing.T) {
|
|
t.Parallel()
|
|
cluster := vault.NewTestCluster(t, nil, &vault.TestClusterOptions{
|
|
HandlerFunc: vaulthttp.Handler,
|
|
NumCores: 1,
|
|
})
|
|
cluster.Start()
|
|
defer cluster.Cleanup()
|
|
client := cluster.Cores[0].Client
|
|
|
|
resp, err := client.Auth().Token().Create(&api.TokenCreateRequest{
|
|
Policies: []string{"default"},
|
|
})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if resp == nil {
|
|
t.Fatal("nil response")
|
|
}
|
|
if resp.Auth == nil {
|
|
t.Fatal("nil auth")
|
|
}
|
|
if resp.Auth.ClientToken == "" {
|
|
t.Fatal("empty client token")
|
|
}
|
|
|
|
client.SetToken(resp.Auth.ClientToken)
|
|
|
|
resp, err = client.Logical().Read("sys/internal/ui/resultant-acl")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if resp == nil {
|
|
t.Fatal("nil response")
|
|
}
|
|
if resp.Data == nil {
|
|
t.Fatal("nil data")
|
|
}
|
|
|
|
exp := map[string]interface{}{
|
|
"exact_paths": map[string]interface{}{
|
|
"auth/token/lookup-self": map[string]interface{}{
|
|
"capabilities": []interface{}{
|
|
"read",
|
|
},
|
|
},
|
|
"auth/token/renew-self": map[string]interface{}{
|
|
"capabilities": []interface{}{
|
|
"update",
|
|
},
|
|
},
|
|
"auth/token/revoke-self": map[string]interface{}{
|
|
"capabilities": []interface{}{
|
|
"update",
|
|
},
|
|
},
|
|
"sys/capabilities-self": map[string]interface{}{
|
|
"capabilities": []interface{}{
|
|
"update",
|
|
},
|
|
},
|
|
"sys/control-group/request": map[string]interface{}{
|
|
"capabilities": []interface{}{
|
|
"update",
|
|
},
|
|
},
|
|
"sys/internal/ui/resultant-acl": map[string]interface{}{
|
|
"capabilities": []interface{}{
|
|
"read",
|
|
},
|
|
},
|
|
"sys/leases/lookup": map[string]interface{}{
|
|
"capabilities": []interface{}{
|
|
"update",
|
|
},
|
|
},
|
|
"sys/leases/renew": map[string]interface{}{
|
|
"capabilities": []interface{}{
|
|
"update",
|
|
},
|
|
},
|
|
"sys/renew": map[string]interface{}{
|
|
"capabilities": []interface{}{
|
|
"update",
|
|
},
|
|
},
|
|
"sys/tools/hash": map[string]interface{}{
|
|
"capabilities": []interface{}{
|
|
"update",
|
|
},
|
|
},
|
|
"sys/wrapping/lookup": map[string]interface{}{
|
|
"capabilities": []interface{}{
|
|
"update",
|
|
},
|
|
},
|
|
"sys/wrapping/unwrap": map[string]interface{}{
|
|
"capabilities": []interface{}{
|
|
"update",
|
|
},
|
|
},
|
|
"sys/wrapping/wrap": map[string]interface{}{
|
|
"capabilities": []interface{}{
|
|
"update",
|
|
},
|
|
},
|
|
},
|
|
"glob_paths": map[string]interface{}{
|
|
"cubbyhole/": map[string]interface{}{
|
|
"capabilities": []interface{}{
|
|
"create",
|
|
"delete",
|
|
"list",
|
|
"read",
|
|
"update",
|
|
},
|
|
},
|
|
"sys/tools/hash/": map[string]interface{}{
|
|
"capabilities": []interface{}{
|
|
"update",
|
|
},
|
|
},
|
|
},
|
|
"root": false,
|
|
}
|
|
|
|
if diff := deep.Equal(resp.Data, exp); diff != nil {
|
|
t.Fatal(diff)
|
|
}
|
|
}
|
|
|
|
func TestSystemBackend_HAStatus(t *testing.T) {
|
|
logger := logging.NewVaultLogger(hclog.Trace)
|
|
inm, err := inmem.NewTransactionalInmem(nil, logger)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
inmha, err := inmem.NewInmemHA(nil, logger)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
conf := &vault.CoreConfig{
|
|
Physical: inm,
|
|
HAPhysical: inmha.(physical.HABackend),
|
|
}
|
|
opts := &vault.TestClusterOptions{
|
|
HandlerFunc: vaulthttp.Handler,
|
|
}
|
|
cluster := vault.NewTestCluster(t, conf, opts)
|
|
cluster.Start()
|
|
defer cluster.Cleanup()
|
|
|
|
corehelpers.RetryUntil(t, 15*time.Second, func() error {
|
|
// Use standby deliberately to make sure it forwards
|
|
client := cluster.Cores[1].Client
|
|
resp, err := client.Sys().HAStatus()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if len(resp.Nodes) != len(cluster.Cores) {
|
|
return fmt.Errorf("expected %d nodes, got %d", len(cluster.Cores), len(resp.Nodes))
|
|
}
|
|
return nil
|
|
})
|
|
}
|
|
|
|
// TestSystemBackend_VersionHistory_unauthenticated tests the sys/version-history
|
|
// endpoint without providing a token. Requests to the endpoint must be
|
|
// authenticated and thus a 403 response is expected.
|
|
func TestSystemBackend_VersionHistory_unauthenticated(t *testing.T) {
|
|
t.Parallel()
|
|
cluster := vault.NewTestCluster(t, nil, &vault.TestClusterOptions{
|
|
HandlerFunc: vaulthttp.Handler,
|
|
NumCores: 1,
|
|
})
|
|
cluster.Start()
|
|
defer cluster.Cleanup()
|
|
client := cluster.Cores[0].Client
|
|
|
|
client.SetToken("")
|
|
resp, err := client.Logical().List("sys/version-history")
|
|
|
|
if resp != nil {
|
|
t.Fatalf("expected nil response, resp: %#v", resp)
|
|
}
|
|
|
|
respErr, ok := err.(*api.ResponseError)
|
|
if !ok {
|
|
t.Fatalf("unexpected error type: err: %#v", err)
|
|
}
|
|
|
|
if respErr.StatusCode != 403 {
|
|
t.Fatalf("expected response status to be 403, actual: %d", respErr.StatusCode)
|
|
}
|
|
}
|
|
|
|
// TestSystemBackend_VersionHistory_authenticated tests the sys/version-history
|
|
// endpoint with authentication. Without synthetically altering the underlying
|
|
// core/versions storage entries, a single version entry should exist.
|
|
func TestSystemBackend_VersionHistory_authenticated(t *testing.T) {
|
|
t.Parallel()
|
|
cluster := vault.NewTestCluster(t, nil, &vault.TestClusterOptions{
|
|
HandlerFunc: vaulthttp.Handler,
|
|
NumCores: 1,
|
|
})
|
|
cluster.Start()
|
|
defer cluster.Cleanup()
|
|
client := cluster.Cores[0].Client
|
|
|
|
resp, err := client.Logical().List("sys/version-history")
|
|
if err != nil || resp == nil {
|
|
t.Fatalf("request failed, err: %v, resp: %#v", err, resp)
|
|
}
|
|
|
|
var ok bool
|
|
var keys []interface{}
|
|
var keyInfo map[string]interface{}
|
|
|
|
if keys, ok = resp.Data["keys"].([]interface{}); !ok {
|
|
t.Fatalf("expected keys to be array, actual: %#v", resp.Data["keys"])
|
|
}
|
|
|
|
if keyInfo, ok = resp.Data["key_info"].(map[string]interface{}); !ok {
|
|
t.Fatalf("expected key_info to be map, actual: %#v", resp.Data["key_info"])
|
|
}
|
|
|
|
if len(keys) != 1 {
|
|
t.Fatalf("expected single version history entry for %q", version.Version)
|
|
}
|
|
|
|
if keyInfo[version.Version] == nil {
|
|
t.Fatalf("expected version %s to be present in key_info, actual: %#v", version.Version, keyInfo)
|
|
}
|
|
}
|