open-vault/vault/logical_passthrough_test.go

245 lines
5.8 KiB
Go

// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
package vault
import (
"context"
"encoding/json"
"reflect"
"testing"
"time"
"github.com/hashicorp/go-secure-stdlib/parseutil"
"github.com/hashicorp/vault/sdk/logical"
)
func TestPassthroughBackend_RootPaths(t *testing.T) {
b := testPassthroughBackend()
test := func(b logical.Backend) {
root := b.SpecialPaths()
if len(root.Root) != 0 {
t.Fatalf("unexpected: %v", root)
}
}
test(b)
b = testPassthroughLeasedBackend()
test(b)
}
func TestPassthroughBackend_Write(t *testing.T) {
test := func(b logical.Backend) {
req := logical.TestRequest(t, logical.UpdateOperation, "foo")
req.Data["raw"] = "test"
resp, err := b.HandleRequest(context.Background(), req)
if err != nil {
t.Fatalf("err: %v", err)
}
if resp != nil {
t.Fatalf("bad: %v", resp)
}
out, err := req.Storage.Get(context.Background(), "foo")
if err != nil {
t.Fatalf("err: %v", err)
}
if out == nil {
t.Fatalf("failed to write to view")
}
}
b := testPassthroughBackend()
test(b)
b = testPassthroughLeasedBackend()
test(b)
}
func TestPassthroughBackend_Read(t *testing.T) {
test := func(b logical.Backend, ttlType string, ttl interface{}, leased bool) {
req := logical.TestRequest(t, logical.UpdateOperation, "foo")
req.Data["raw"] = "test"
var reqTTL interface{}
switch ttl.(type) {
case int64:
reqTTL = ttl.(int64)
case string:
reqTTL = ttl.(string)
default:
t.Fatal("unknown ttl type")
}
req.Data[ttlType] = reqTTL
storage := req.Storage
if _, err := b.HandleRequest(context.Background(), req); err != nil {
t.Fatalf("err: %v", err)
}
req = logical.TestRequest(t, logical.ReadOperation, "foo")
req.Storage = storage
resp, err := b.HandleRequest(context.Background(), req)
if err != nil {
t.Fatalf("err: %v", err)
}
expectedTTL, err := parseutil.ParseDurationSecond(ttl)
if err != nil {
t.Fatal(err)
}
// What comes back if an int is passed in is a json.Number which is
// actually aliased as a string so to make the deep equal happy if it's
// actually a number we set it to an int64
var respTTL interface{} = resp.Data[ttlType]
_, ok := respTTL.(json.Number)
if ok {
respTTL, err = respTTL.(json.Number).Int64()
if err != nil {
t.Fatal(err)
}
resp.Data[ttlType] = respTTL
}
expected := &logical.Response{
Secret: &logical.Secret{
LeaseOptions: logical.LeaseOptions{
Renewable: true,
TTL: expectedTTL,
},
},
Data: map[string]interface{}{
"raw": "test",
ttlType: reqTTL,
},
}
if !leased {
expected.Secret.Renewable = false
}
resp.Secret.InternalData = nil
resp.Secret.LeaseID = ""
if !reflect.DeepEqual(resp, expected) {
t.Fatalf("bad response.\n\nexpected:\n%#v\n\nGot:\n%#v", expected, resp)
}
}
b := testPassthroughLeasedBackend()
test(b, "lease", "1h", true)
test(b, "ttl", "5", true)
b = testPassthroughBackend()
test(b, "lease", int64(10), false)
test(b, "ttl", "40s", false)
}
func TestPassthroughBackend_Delete(t *testing.T) {
test := func(b logical.Backend) {
req := logical.TestRequest(t, logical.UpdateOperation, "foo")
req.Data["raw"] = "test"
storage := req.Storage
if _, err := b.HandleRequest(context.Background(), req); err != nil {
t.Fatalf("err: %v", err)
}
req = logical.TestRequest(t, logical.DeleteOperation, "foo")
req.Storage = storage
resp, err := b.HandleRequest(context.Background(), req)
if err != nil {
t.Fatalf("err: %v", err)
}
if resp != nil {
t.Fatalf("bad: %v", resp)
}
req = logical.TestRequest(t, logical.ReadOperation, "foo")
req.Storage = storage
resp, err = b.HandleRequest(context.Background(), req)
if err != nil {
t.Fatalf("err: %v", err)
}
if resp != nil {
t.Fatalf("bad: %v", resp)
}
}
b := testPassthroughBackend()
test(b)
b = testPassthroughLeasedBackend()
test(b)
}
func TestPassthroughBackend_List(t *testing.T) {
test := func(b logical.Backend) {
req := logical.TestRequest(t, logical.UpdateOperation, "foo")
req.Data["raw"] = "test"
storage := req.Storage
if _, err := b.HandleRequest(context.Background(), req); err != nil {
t.Fatalf("err: %v", err)
}
req = logical.TestRequest(t, logical.ListOperation, "")
req.Storage = storage
resp, err := b.HandleRequest(context.Background(), req)
if err != nil {
t.Fatalf("err: %v", err)
}
expected := &logical.Response{
Data: map[string]interface{}{
"keys": []string{"foo"},
},
}
if !reflect.DeepEqual(resp, expected) {
t.Fatalf("bad response.\n\nexpected: %#v\n\nGot: %#v", expected, resp)
}
}
b := testPassthroughBackend()
test(b)
b = testPassthroughLeasedBackend()
test(b)
}
func TestPassthroughBackend_Revoke(t *testing.T) {
test := func(t *testing.T, b logical.Backend) {
t.Helper()
req := logical.TestRequest(t, logical.RevokeOperation, "kv")
req.Secret = &logical.Secret{
InternalData: map[string]interface{}{
"secret_type": "kv",
},
}
if _, err := b.HandleRequest(context.Background(), req); err != nil {
t.Fatalf("err: %v", err)
}
}
t.Run("passthrough", func(t *testing.T) {
test(t, testPassthroughBackend())
})
t.Run("passthrough-leased", func(t *testing.T) {
test(t, testPassthroughLeasedBackend())
})
}
func testPassthroughBackend() logical.Backend {
b, _ := PassthroughBackendFactory(context.Background(), &logical.BackendConfig{
Logger: nil,
System: logical.StaticSystemView{
DefaultLeaseTTLVal: time.Hour * 24,
MaxLeaseTTLVal: time.Hour * 24 * 32,
},
})
return b
}
func testPassthroughLeasedBackend() logical.Backend {
b, _ := LeasedPassthroughBackendFactory(context.Background(), &logical.BackendConfig{
Logger: nil,
System: logical.StaticSystemView{
DefaultLeaseTTLVal: time.Hour * 24,
MaxLeaseTTLVal: time.Hour * 24 * 32,
},
})
return b
}