mirror of
				https://github.com/optim-enterprises-bv/vault.git
				synced 2025-10-31 18:48:08 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			379 lines
		
	
	
		
			8.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			379 lines
		
	
	
		
			8.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package vault
 | |
| 
 | |
| import (
 | |
| 	"reflect"
 | |
| 	"strings"
 | |
| 	"testing"
 | |
| 
 | |
| 	"github.com/hashicorp/vault/helper/jsonutil"
 | |
| 	"github.com/hashicorp/vault/logical"
 | |
| )
 | |
| 
 | |
| func TestCore_DefaultAuthTable(t *testing.T) {
 | |
| 	c, keys, _ := TestCoreUnsealed(t)
 | |
| 	verifyDefaultAuthTable(t, c.auth)
 | |
| 
 | |
| 	// Start a second core with same physical
 | |
| 	conf := &CoreConfig{
 | |
| 		Physical:     c.physical,
 | |
| 		DisableMlock: true,
 | |
| 	}
 | |
| 	c2, err := NewCore(conf)
 | |
| 	if err != nil {
 | |
| 		t.Fatalf("err: %v", err)
 | |
| 	}
 | |
| 	for i, key := range keys {
 | |
| 		unseal, err := TestCoreUnseal(c2, key)
 | |
| 		if err != nil {
 | |
| 			t.Fatalf("err: %v", err)
 | |
| 		}
 | |
| 		if i+1 == len(keys) && !unseal {
 | |
| 			t.Fatalf("should be unsealed")
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	// Verify matching mount tables
 | |
| 	if !reflect.DeepEqual(c.auth, c2.auth) {
 | |
| 		t.Fatalf("mismatch: %v %v", c.auth, c2.auth)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestCore_EnableCredential(t *testing.T) {
 | |
| 	c, keys, _ := TestCoreUnsealed(t)
 | |
| 	c.credentialBackends["noop"] = func(*logical.BackendConfig) (logical.Backend, error) {
 | |
| 		return &NoopBackend{}, nil
 | |
| 	}
 | |
| 
 | |
| 	me := &MountEntry{
 | |
| 		Table: credentialTableType,
 | |
| 		Path:  "foo",
 | |
| 		Type:  "noop",
 | |
| 	}
 | |
| 	err := c.enableCredential(me)
 | |
| 	if err != nil {
 | |
| 		t.Fatalf("err: %v", err)
 | |
| 	}
 | |
| 
 | |
| 	match := c.router.MatchingMount("auth/foo/bar")
 | |
| 	if match != "auth/foo/" {
 | |
| 		t.Fatalf("missing mount")
 | |
| 	}
 | |
| 
 | |
| 	conf := &CoreConfig{
 | |
| 		Physical:     c.physical,
 | |
| 		DisableMlock: true,
 | |
| 	}
 | |
| 	c2, err := NewCore(conf)
 | |
| 	if err != nil {
 | |
| 		t.Fatalf("err: %v", err)
 | |
| 	}
 | |
| 	c2.credentialBackends["noop"] = func(*logical.BackendConfig) (logical.Backend, error) {
 | |
| 		return &NoopBackend{}, nil
 | |
| 	}
 | |
| 	for i, key := range keys {
 | |
| 		unseal, err := TestCoreUnseal(c2, key)
 | |
| 		if err != nil {
 | |
| 			t.Fatalf("err: %v", err)
 | |
| 		}
 | |
| 		if i+1 == len(keys) && !unseal {
 | |
| 			t.Fatalf("should be unsealed")
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	// Verify matching auth tables
 | |
| 	if !reflect.DeepEqual(c.auth, c2.auth) {
 | |
| 		t.Fatalf("mismatch: %v %v", c.auth, c2.auth)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // Test that the local table actually gets populated as expected with local
 | |
| // entries, and that upon reading the entries from both are recombined
 | |
| // correctly
 | |
| func TestCore_EnableCredential_Local(t *testing.T) {
 | |
| 	c, _, _ := TestCoreUnsealed(t)
 | |
| 	c.credentialBackends["noop"] = func(*logical.BackendConfig) (logical.Backend, error) {
 | |
| 		return &NoopBackend{}, nil
 | |
| 	}
 | |
| 
 | |
| 	c.auth = &MountTable{
 | |
| 		Type: credentialTableType,
 | |
| 		Entries: []*MountEntry{
 | |
| 			&MountEntry{
 | |
| 				Table: credentialTableType,
 | |
| 				Path:  "noop/",
 | |
| 				Type:  "noop",
 | |
| 				UUID:  "abcd",
 | |
| 			},
 | |
| 			&MountEntry{
 | |
| 				Table: credentialTableType,
 | |
| 				Path:  "noop2/",
 | |
| 				Type:  "noop",
 | |
| 				UUID:  "bcde",
 | |
| 			},
 | |
| 		},
 | |
| 	}
 | |
| 
 | |
| 	// Both should set up successfully
 | |
| 	err := c.setupCredentials()
 | |
| 	if err != nil {
 | |
| 		t.Fatal(err)
 | |
| 	}
 | |
| 
 | |
| 	rawLocal, err := c.barrier.Get(coreLocalAuthConfigPath)
 | |
| 	if err != nil {
 | |
| 		t.Fatal(err)
 | |
| 	}
 | |
| 	if rawLocal == nil {
 | |
| 		t.Fatal("expected non-nil local credential")
 | |
| 	}
 | |
| 	localCredentialTable := &MountTable{}
 | |
| 	if err := jsonutil.DecodeJSON(rawLocal.Value, localCredentialTable); err != nil {
 | |
| 		t.Fatal(err)
 | |
| 	}
 | |
| 	if len(localCredentialTable.Entries) > 0 {
 | |
| 		t.Fatalf("expected no entries in local credential table, got %#v", localCredentialTable)
 | |
| 	}
 | |
| 
 | |
| 	c.auth.Entries[1].Local = true
 | |
| 	if err := c.persistAuth(c.auth, false); err != nil {
 | |
| 		t.Fatal(err)
 | |
| 	}
 | |
| 
 | |
| 	rawLocal, err = c.barrier.Get(coreLocalAuthConfigPath)
 | |
| 	if err != nil {
 | |
| 		t.Fatal(err)
 | |
| 	}
 | |
| 	if rawLocal == nil {
 | |
| 		t.Fatal("expected non-nil local credential")
 | |
| 	}
 | |
| 	localCredentialTable = &MountTable{}
 | |
| 	if err := jsonutil.DecodeJSON(rawLocal.Value, localCredentialTable); err != nil {
 | |
| 		t.Fatal(err)
 | |
| 	}
 | |
| 	if len(localCredentialTable.Entries) != 1 {
 | |
| 		t.Fatalf("expected one entry in local credential table, got %#v", localCredentialTable)
 | |
| 	}
 | |
| 
 | |
| 	oldCredential := c.auth
 | |
| 	if err := c.loadCredentials(); err != nil {
 | |
| 		t.Fatal(err)
 | |
| 	}
 | |
| 
 | |
| 	if !reflect.DeepEqual(oldCredential, c.auth) {
 | |
| 		t.Fatalf("expected\n%#v\ngot\n%#v\n", oldCredential, c.auth)
 | |
| 	}
 | |
| 
 | |
| 	if len(c.auth.Entries) != 2 {
 | |
| 		t.Fatalf("expected two credential entries, got %#v", localCredentialTable)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestCore_EnableCredential_twice_409(t *testing.T) {
 | |
| 	c, _, _ := TestCoreUnsealed(t)
 | |
| 	c.credentialBackends["noop"] = func(*logical.BackendConfig) (logical.Backend, error) {
 | |
| 		return &NoopBackend{}, nil
 | |
| 	}
 | |
| 
 | |
| 	me := &MountEntry{
 | |
| 		Table: credentialTableType,
 | |
| 		Path:  "foo",
 | |
| 		Type:  "noop",
 | |
| 	}
 | |
| 	err := c.enableCredential(me)
 | |
| 	if err != nil {
 | |
| 		t.Fatalf("err: %v", err)
 | |
| 	}
 | |
| 
 | |
| 	// 2nd should be a 409 error
 | |
| 	err2 := c.enableCredential(me)
 | |
| 	switch err2.(type) {
 | |
| 	case logical.HTTPCodedError:
 | |
| 		if err2.(logical.HTTPCodedError).Code() != 409 {
 | |
| 			t.Fatalf("invalid code given")
 | |
| 		}
 | |
| 	default:
 | |
| 		t.Fatalf("expected a different error type")
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestCore_EnableCredential_Token(t *testing.T) {
 | |
| 	c, _, _ := TestCoreUnsealed(t)
 | |
| 	me := &MountEntry{
 | |
| 		Table: credentialTableType,
 | |
| 		Path:  "foo",
 | |
| 		Type:  "token",
 | |
| 	}
 | |
| 	err := c.enableCredential(me)
 | |
| 	if err.Error() != "token credential backend cannot be instantiated" {
 | |
| 		t.Fatalf("err: %v", err)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestCore_DisableCredential(t *testing.T) {
 | |
| 	c, keys, _ := TestCoreUnsealed(t)
 | |
| 	c.credentialBackends["noop"] = func(*logical.BackendConfig) (logical.Backend, error) {
 | |
| 		return &NoopBackend{}, nil
 | |
| 	}
 | |
| 
 | |
| 	existed, err := c.disableCredential("foo")
 | |
| 	if existed || (err != nil && !strings.HasPrefix(err.Error(), "no matching backend")) {
 | |
| 		t.Fatalf("existed: %v; err: %v", existed, err)
 | |
| 	}
 | |
| 
 | |
| 	me := &MountEntry{
 | |
| 		Table: credentialTableType,
 | |
| 		Path:  "foo",
 | |
| 		Type:  "noop",
 | |
| 	}
 | |
| 	err = c.enableCredential(me)
 | |
| 	if err != nil {
 | |
| 		t.Fatalf("err: %v", err)
 | |
| 	}
 | |
| 
 | |
| 	existed, err = c.disableCredential("foo")
 | |
| 	if !existed || err != nil {
 | |
| 		t.Fatalf("existed: %v; err: %v", existed, err)
 | |
| 	}
 | |
| 
 | |
| 	match := c.router.MatchingMount("auth/foo/bar")
 | |
| 	if match != "" {
 | |
| 		t.Fatalf("backend present")
 | |
| 	}
 | |
| 
 | |
| 	conf := &CoreConfig{
 | |
| 		Physical:     c.physical,
 | |
| 		DisableMlock: true,
 | |
| 	}
 | |
| 	c2, err := NewCore(conf)
 | |
| 	if err != nil {
 | |
| 		t.Fatalf("err: %v", err)
 | |
| 	}
 | |
| 	for i, key := range keys {
 | |
| 		unseal, err := TestCoreUnseal(c2, key)
 | |
| 		if err != nil {
 | |
| 			t.Fatalf("err: %v", err)
 | |
| 		}
 | |
| 		if i+1 == len(keys) && !unseal {
 | |
| 			t.Fatalf("should be unsealed")
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	// Verify matching mount tables
 | |
| 	if !reflect.DeepEqual(c.auth, c2.auth) {
 | |
| 		t.Fatalf("mismatch: %v %v", c.auth, c2.auth)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestCore_DisableCredential_Protected(t *testing.T) {
 | |
| 	c, _, _ := TestCoreUnsealed(t)
 | |
| 	existed, err := c.disableCredential("token")
 | |
| 	if !existed || err.Error() != "token credential backend cannot be disabled" {
 | |
| 		t.Fatalf("existed: %v; err: %v", existed, err)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestCore_DisableCredential_Cleanup(t *testing.T) {
 | |
| 	noop := &NoopBackend{
 | |
| 		Login: []string{"login"},
 | |
| 	}
 | |
| 	c, _, _ := TestCoreUnsealed(t)
 | |
| 	c.credentialBackends["noop"] = func(*logical.BackendConfig) (logical.Backend, error) {
 | |
| 		return noop, nil
 | |
| 	}
 | |
| 
 | |
| 	me := &MountEntry{
 | |
| 		Table: credentialTableType,
 | |
| 		Path:  "foo",
 | |
| 		Type:  "noop",
 | |
| 	}
 | |
| 	err := c.enableCredential(me)
 | |
| 	if err != nil {
 | |
| 		t.Fatalf("err: %v", err)
 | |
| 	}
 | |
| 
 | |
| 	// Store the view
 | |
| 	view := c.router.MatchingStorageView("auth/foo/")
 | |
| 
 | |
| 	// Inject data
 | |
| 	se := &logical.StorageEntry{
 | |
| 		Key:   "plstodelete",
 | |
| 		Value: []byte("test"),
 | |
| 	}
 | |
| 	if err := view.Put(se); err != nil {
 | |
| 		t.Fatalf("err: %v", err)
 | |
| 	}
 | |
| 
 | |
| 	// Generate a new token auth
 | |
| 	noop.Response = &logical.Response{
 | |
| 		Auth: &logical.Auth{
 | |
| 			Policies: []string{"foo"},
 | |
| 		},
 | |
| 	}
 | |
| 	r := &logical.Request{
 | |
| 		Operation: logical.ReadOperation,
 | |
| 		Path:      "auth/foo/login",
 | |
| 	}
 | |
| 	resp, err := c.HandleRequest(r)
 | |
| 	if err != nil {
 | |
| 		t.Fatalf("err: %v", err)
 | |
| 	}
 | |
| 	if resp.Auth.ClientToken == "" {
 | |
| 		t.Fatalf("bad: %#v", resp)
 | |
| 	}
 | |
| 
 | |
| 	// Disable should cleanup
 | |
| 	existed, err := c.disableCredential("foo")
 | |
| 	if !existed || err != nil {
 | |
| 		t.Fatalf("existed: %v; err: %v", existed, err)
 | |
| 	}
 | |
| 
 | |
| 	// Token should be revoked
 | |
| 	te, err := c.tokenStore.Lookup(resp.Auth.ClientToken)
 | |
| 	if err != nil {
 | |
| 		t.Fatalf("err: %v", err)
 | |
| 	}
 | |
| 	if te != nil {
 | |
| 		t.Fatalf("bad: %#v", te)
 | |
| 	}
 | |
| 
 | |
| 	// View should be empty
 | |
| 	out, err := logical.CollectKeys(view)
 | |
| 	if err != nil {
 | |
| 		t.Fatalf("err: %v", err)
 | |
| 	}
 | |
| 	if len(out) != 0 {
 | |
| 		t.Fatalf("bad: %#v", out)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestDefaultAuthTable(t *testing.T) {
 | |
| 	table := defaultAuthTable()
 | |
| 	verifyDefaultAuthTable(t, table)
 | |
| }
 | |
| 
 | |
| func verifyDefaultAuthTable(t *testing.T, table *MountTable) {
 | |
| 	if len(table.Entries) != 1 {
 | |
| 		t.Fatalf("bad: %v", table.Entries)
 | |
| 	}
 | |
| 	if table.Type != credentialTableType {
 | |
| 		t.Fatalf("bad: %v", *table)
 | |
| 	}
 | |
| 	for idx, entry := range table.Entries {
 | |
| 		switch idx {
 | |
| 		case 0:
 | |
| 			if entry.Path != "token/" {
 | |
| 				t.Fatalf("bad: %v", entry)
 | |
| 			}
 | |
| 			if entry.Type != "token" {
 | |
| 				t.Fatalf("bad: %v", entry)
 | |
| 			}
 | |
| 		}
 | |
| 		if entry.Description == "" {
 | |
| 			t.Fatalf("bad: %v", entry)
 | |
| 		}
 | |
| 		if entry.UUID == "" {
 | |
| 			t.Fatalf("bad: %v", entry)
 | |
| 		}
 | |
| 	}
 | |
| }
 | 
