4239f9d243
up-to-date information. This allows remount to be implemented with the same source and dest, allowing mount options to be changed on the fly. If/when Vault gains the ability to HUP its configuration, this should just work for the global values as well. Need specific unit tests for this functionality.
353 lines
6.9 KiB
Go
353 lines
6.9 KiB
Go
package vault
|
|
|
|
import (
|
|
"reflect"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/hashicorp/vault/logical"
|
|
)
|
|
|
|
func TestCore_DefaultMountTable(t *testing.T) {
|
|
c, key, _ := TestCoreUnsealed(t)
|
|
verifyDefaultTable(t, c.mounts)
|
|
|
|
// 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)
|
|
}
|
|
unseal, err := c2.Unseal(key)
|
|
if err != nil {
|
|
t.Fatalf("err: %v", err)
|
|
}
|
|
if !unseal {
|
|
t.Fatalf("should be unsealed")
|
|
}
|
|
|
|
// Verify matching mount tables
|
|
if !reflect.DeepEqual(c.mounts, c2.mounts) {
|
|
t.Fatalf("mismatch: %v %v", c.mounts, c2.mounts)
|
|
}
|
|
}
|
|
|
|
func TestCore_Mount(t *testing.T) {
|
|
c, key, _ := TestCoreUnsealed(t)
|
|
me := &MountEntry{
|
|
Path: "foo",
|
|
Type: "generic",
|
|
}
|
|
err := c.mount(me)
|
|
if err != nil {
|
|
t.Fatalf("err: %v", err)
|
|
}
|
|
|
|
match := c.router.MatchingMount("foo/bar")
|
|
if match != "foo/" {
|
|
t.Fatalf("missing mount")
|
|
}
|
|
|
|
conf := &CoreConfig{
|
|
Physical: c.physical,
|
|
DisableMlock: true,
|
|
}
|
|
c2, err := NewCore(conf)
|
|
if err != nil {
|
|
t.Fatalf("err: %v", err)
|
|
}
|
|
unseal, err := c2.Unseal(key)
|
|
if err != nil {
|
|
t.Fatalf("err: %v", err)
|
|
}
|
|
if !unseal {
|
|
t.Fatalf("should be unsealed")
|
|
}
|
|
|
|
// Verify matching mount tables
|
|
if !reflect.DeepEqual(c.mounts, c2.mounts) {
|
|
t.Fatalf("mismatch: %v %v", c.mounts, c2.mounts)
|
|
}
|
|
}
|
|
|
|
func TestCore_Unmount(t *testing.T) {
|
|
c, key, _ := TestCoreUnsealed(t)
|
|
err := c.unmount("secret")
|
|
if err != nil {
|
|
t.Fatalf("err: %v", err)
|
|
}
|
|
|
|
match := c.router.MatchingMount("secret/foo")
|
|
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)
|
|
}
|
|
unseal, err := c2.Unseal(key)
|
|
if err != nil {
|
|
t.Fatalf("err: %v", err)
|
|
}
|
|
if !unseal {
|
|
t.Fatalf("should be unsealed")
|
|
}
|
|
|
|
// Verify matching mount tables
|
|
if !reflect.DeepEqual(c.mounts, c2.mounts) {
|
|
t.Fatalf("mismatch: %v %v", c.mounts, c2.mounts)
|
|
}
|
|
}
|
|
|
|
func TestCore_Unmount_Cleanup(t *testing.T) {
|
|
noop := &NoopBackend{}
|
|
c, _, root := TestCoreUnsealed(t)
|
|
c.logicalBackends["noop"] = func(*logical.BackendConfig) (logical.Backend, error) {
|
|
return noop, nil
|
|
}
|
|
|
|
// Mount the noop backend
|
|
me := &MountEntry{
|
|
Path: "test/",
|
|
Type: "noop",
|
|
}
|
|
if err := c.mount(me); err != nil {
|
|
t.Fatalf("err: %v", err)
|
|
}
|
|
|
|
// Store the view
|
|
view := c.router.MatchingView("test/")
|
|
|
|
// Inject data
|
|
se := &logical.StorageEntry{
|
|
Key: "plstodelete",
|
|
Value: []byte("test"),
|
|
}
|
|
if err := view.Put(se); err != nil {
|
|
t.Fatalf("err: %v", err)
|
|
}
|
|
|
|
// Setup response
|
|
resp := &logical.Response{
|
|
Secret: &logical.Secret{
|
|
LeaseOptions: logical.LeaseOptions{
|
|
TTL: time.Hour,
|
|
},
|
|
},
|
|
Data: map[string]interface{}{
|
|
"foo": "bar",
|
|
},
|
|
}
|
|
noop.Response = resp
|
|
|
|
// Generate leased secret
|
|
r := &logical.Request{
|
|
Operation: logical.ReadOperation,
|
|
Path: "test/foo",
|
|
ClientToken: root,
|
|
}
|
|
resp, err := c.HandleRequest(r)
|
|
if err != nil {
|
|
t.Fatalf("err: %v", err)
|
|
}
|
|
if resp.Secret.LeaseID == "" {
|
|
t.Fatalf("bad: %#v", resp)
|
|
}
|
|
|
|
// Unmount, this should cleanup
|
|
if err := c.unmount("test/"); err != nil {
|
|
t.Fatalf("err: %v", err)
|
|
}
|
|
|
|
// Rollback should be invoked
|
|
if noop.Requests[1].Operation != logical.RollbackOperation {
|
|
t.Fatalf("bad: %#v", noop.Requests)
|
|
}
|
|
|
|
// Revoke should be invoked
|
|
if noop.Requests[2].Operation != logical.RevokeOperation {
|
|
t.Fatalf("bad: %#v", noop.Requests)
|
|
}
|
|
if noop.Requests[2].Path != "foo" {
|
|
t.Fatalf("bad: %#v", noop.Requests)
|
|
}
|
|
|
|
// View should be empty
|
|
out, err := CollectKeys(view)
|
|
if err != nil {
|
|
t.Fatalf("err: %v", err)
|
|
}
|
|
if len(out) != 0 {
|
|
t.Fatalf("bad: %#v", out)
|
|
}
|
|
}
|
|
|
|
func TestCore_Remount(t *testing.T) {
|
|
c, key, _ := TestCoreUnsealed(t)
|
|
err := c.remount("secret", "foo", MountConfig{})
|
|
if err != nil {
|
|
t.Fatalf("err: %v", err)
|
|
}
|
|
|
|
match := c.router.MatchingMount("foo/bar")
|
|
if match != "foo/" {
|
|
t.Fatalf("failed remount")
|
|
}
|
|
|
|
conf := &CoreConfig{
|
|
Physical: c.physical,
|
|
DisableMlock: true,
|
|
}
|
|
c2, err := NewCore(conf)
|
|
if err != nil {
|
|
t.Fatalf("err: %v", err)
|
|
}
|
|
unseal, err := c2.Unseal(key)
|
|
if err != nil {
|
|
t.Fatalf("err: %v", err)
|
|
}
|
|
if !unseal {
|
|
t.Fatalf("should be unsealed")
|
|
}
|
|
|
|
// Verify matching mount tables
|
|
if !reflect.DeepEqual(c.mounts, c2.mounts) {
|
|
t.Fatalf("mismatch: %v %v", c.mounts, c2.mounts)
|
|
}
|
|
}
|
|
|
|
func TestCore_Remount_Cleanup(t *testing.T) {
|
|
noop := &NoopBackend{}
|
|
c, _, root := TestCoreUnsealed(t)
|
|
c.logicalBackends["noop"] = func(*logical.BackendConfig) (logical.Backend, error) {
|
|
return noop, nil
|
|
}
|
|
|
|
// Mount the noop backend
|
|
me := &MountEntry{
|
|
Path: "test/",
|
|
Type: "noop",
|
|
}
|
|
if err := c.mount(me); err != nil {
|
|
t.Fatalf("err: %v", err)
|
|
}
|
|
|
|
// Store the view
|
|
view := c.router.MatchingView("test/")
|
|
|
|
// Inject data
|
|
se := &logical.StorageEntry{
|
|
Key: "plstokeep",
|
|
Value: []byte("test"),
|
|
}
|
|
if err := view.Put(se); err != nil {
|
|
t.Fatalf("err: %v", err)
|
|
}
|
|
|
|
// Setup response
|
|
resp := &logical.Response{
|
|
Secret: &logical.Secret{
|
|
LeaseOptions: logical.LeaseOptions{
|
|
TTL: time.Hour,
|
|
},
|
|
},
|
|
Data: map[string]interface{}{
|
|
"foo": "bar",
|
|
},
|
|
}
|
|
noop.Response = resp
|
|
|
|
// Generate leased secret
|
|
r := &logical.Request{
|
|
Operation: logical.ReadOperation,
|
|
Path: "test/foo",
|
|
ClientToken: root,
|
|
}
|
|
resp, err := c.HandleRequest(r)
|
|
if err != nil {
|
|
t.Fatalf("err: %v", err)
|
|
}
|
|
if resp.Secret.LeaseID == "" {
|
|
t.Fatalf("bad: %#v", resp)
|
|
}
|
|
|
|
// Remount, this should cleanup
|
|
if err := c.remount("test/", "new/", MountConfig{}); err != nil {
|
|
t.Fatalf("err: %v", err)
|
|
}
|
|
|
|
// Rollback should be invoked
|
|
if noop.Requests[1].Operation != logical.RollbackOperation {
|
|
t.Fatalf("bad: %#v", noop.Requests)
|
|
}
|
|
|
|
// Revoke should be invoked
|
|
if noop.Requests[2].Operation != logical.RevokeOperation {
|
|
t.Fatalf("bad: %#v", noop.Requests)
|
|
}
|
|
if noop.Requests[2].Path != "foo" {
|
|
t.Fatalf("bad: %#v", noop.Requests)
|
|
}
|
|
|
|
// View should not be empty
|
|
out, err := CollectKeys(view)
|
|
if err != nil {
|
|
t.Fatalf("err: %v", err)
|
|
}
|
|
if len(out) != 1 && out[0] != "plstokeep" {
|
|
t.Fatalf("bad: %#v", out)
|
|
}
|
|
}
|
|
|
|
func TestCore_Remount_Protected(t *testing.T) {
|
|
c, _, _ := TestCoreUnsealed(t)
|
|
err := c.remount("sys", "foo", MountConfig{})
|
|
if err.Error() != "cannot remount 'sys/'" {
|
|
t.Fatalf("err: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestDefaultMountTable(t *testing.T) {
|
|
table := defaultMountTable()
|
|
verifyDefaultTable(t, table)
|
|
}
|
|
|
|
func verifyDefaultTable(t *testing.T, table *MountTable) {
|
|
if len(table.Entries) != 2 {
|
|
t.Fatalf("bad: %v", table.Entries)
|
|
}
|
|
for idx, entry := range table.Entries {
|
|
switch idx {
|
|
case 0:
|
|
if entry.Path != "secret/" {
|
|
t.Fatalf("bad: %v", entry)
|
|
}
|
|
if entry.Type != "generic" {
|
|
t.Fatalf("bad: %v", entry)
|
|
}
|
|
case 1:
|
|
if entry.Path != "sys/" {
|
|
t.Fatalf("bad: %v", entry)
|
|
}
|
|
if entry.Type != "system" {
|
|
t.Fatalf("bad: %v", entry)
|
|
}
|
|
}
|
|
if entry.Description == "" {
|
|
t.Fatalf("bad: %v", entry)
|
|
}
|
|
if entry.UUID == "" {
|
|
t.Fatalf("bad: %v", entry)
|
|
}
|
|
}
|
|
|
|
}
|