diff --git a/vault/barrier_view.go b/vault/barrier_view.go index 987763e90d..7dfe0b7bb7 100644 --- a/vault/barrier_view.go +++ b/vault/barrier_view.go @@ -21,6 +21,12 @@ func NewBarrierView(barrier SecurityBarrier, prefix string) *BarrierView { } } +// SubView constructs a nested sub-view using the given prefix +func (v *BarrierView) SubView(prefix string) *BarrierView { + sub := v.expandKey(prefix) + return &BarrierView{barrier: v.barrier, prefix: sub} +} + // Put is used to insert or update an entry func (v *BarrierView) Put(entry *Entry) error { nested := &Entry{ diff --git a/vault/barrier_view_test.go b/vault/barrier_view_test.go index ec2091b237..f272d1dfd0 100644 --- a/vault/barrier_view_test.go +++ b/vault/barrier_view_test.go @@ -67,3 +67,65 @@ func TestBarrierView(t *testing.T) { t.Fatalf("root test missing") } } + +func TestBarrierView_SubView(t *testing.T) { + _, barrier, _ := mockBarrier(t) + root := NewBarrierView(barrier, "foo/") + view := root.SubView("bar/") + + // List should have no visibility + keys, err := view.List("") + if err != nil { + t.Fatalf("err: %v", err) + } + if len(keys) != 0 { + t.Fatalf("bad: %v", err) + } + + // Get should have no visibility + out, err := view.Get("test") + if err != nil { + t.Fatalf("err: %v", err) + } + if out != nil { + t.Fatalf("bad: %v", out) + } + + // Try to put the same entry via the view + entry := &Entry{Key: "test", Value: []byte("test")} + if err := view.Put(entry); err != nil { + t.Fatalf("err: %v", err) + } + + // Check it is nested + out, err = barrier.Get("foo/bar/test") + if err != nil { + t.Fatalf("err: %v", err) + } + if out == nil { + t.Fatalf("missing nested foo/bar/test") + } + + // Check for visibility in root + out, err = root.Get("bar/test") + if err != nil { + t.Fatalf("err: %v", err) + } + if out == nil { + t.Fatalf("missing nested bar/test") + } + + // Delete nested + if err := view.Delete("test"); err != nil { + t.Fatalf("err: %v", err) + } + + // Check the nested key + out, err = barrier.Get("foo/bar/test") + if err != nil { + t.Fatalf("err: %v", err) + } + if out != nil { + t.Fatalf("nested foo/bar/test should be gone") + } +}