2015-03-15 21:42:05 +00:00
package vault
import (
2018-01-08 18:31:38 +00:00
"context"
2015-11-19 01:26:03 +00:00
"crypto/sha256"
2017-10-20 14:59:17 +00:00
"encoding/base64"
2017-04-12 17:39:18 +00:00
"encoding/hex"
"fmt"
"io/ioutil"
2020-05-27 18:28:00 +00:00
"net/http"
2017-04-12 17:39:18 +00:00
"os"
"path/filepath"
2015-03-15 21:42:05 +00:00
"reflect"
2016-04-19 20:26:26 +00:00
"strings"
2015-03-15 21:42:05 +00:00
"testing"
2015-08-31 18:27:49 +00:00
"time"
2015-03-15 21:42:05 +00:00
2015-09-01 22:29:30 +00:00
"github.com/fatih/structs"
2018-10-15 16:56:24 +00:00
"github.com/go-test/deep"
2018-04-03 00:46:59 +00:00
hclog "github.com/hashicorp/go-hclog"
2015-03-31 23:45:00 +00:00
"github.com/hashicorp/vault/audit"
2017-04-12 17:39:18 +00:00
"github.com/hashicorp/vault/helper/builtinplugins"
2019-04-10 21:46:17 +00:00
"github.com/hashicorp/vault/helper/identity"
2018-09-18 03:03:00 +00:00
"github.com/hashicorp/vault/helper/namespace"
2020-06-17 20:24:38 +00:00
"github.com/hashicorp/vault/helper/random"
2019-04-13 07:44:06 +00:00
"github.com/hashicorp/vault/sdk/framework"
"github.com/hashicorp/vault/sdk/helper/consts"
"github.com/hashicorp/vault/sdk/helper/jsonutil"
2019-04-12 21:54:35 +00:00
"github.com/hashicorp/vault/sdk/helper/salt"
"github.com/hashicorp/vault/sdk/logical"
"github.com/hashicorp/vault/sdk/version"
2017-05-04 02:03:42 +00:00
"github.com/mitchellh/mapstructure"
2015-03-15 21:42:05 +00:00
)
func TestSystemBackend_RootPaths ( t * testing . T ) {
expected := [ ] string {
2015-03-20 19:48:19 +00:00
"auth/*" ,
2015-03-15 21:42:05 +00:00
"remount" ,
2015-03-31 23:45:00 +00:00
"audit" ,
"audit/*" ,
2017-09-15 04:21:35 +00:00
"raw" ,
2015-04-02 00:44:43 +00:00
"raw/*" ,
2017-02-17 04:36:06 +00:00
"replication/primary/secondary-token" ,
2018-09-18 03:03:00 +00:00
"replication/performance/primary/secondary-token" ,
"replication/dr/primary/secondary-token" ,
2017-02-17 04:36:06 +00:00
"replication/reindex" ,
2018-09-18 03:03:00 +00:00
"replication/dr/reindex" ,
"replication/performance/reindex" ,
2015-05-28 00:53:42 +00:00
"rotate" ,
2017-06-17 05:51:42 +00:00
"config/cors" ,
2017-02-02 19:49:20 +00:00
"config/auditing/*" ,
2018-04-03 18:07:43 +00:00
"config/ui/headers/*" ,
2017-04-24 19:47:40 +00:00
"plugins/catalog/*" ,
2017-05-04 02:03:42 +00:00
"revoke-prefix/*" ,
2017-07-25 15:59:43 +00:00
"revoke-force/*" ,
2017-05-04 02:03:42 +00:00
"leases/revoke-prefix/*" ,
"leases/revoke-force/*" ,
"leases/lookup/*" ,
2020-10-16 18:57:11 +00:00
"storage/raft/snapshot-auto/config/*" ,
2015-03-15 21:42:05 +00:00
}
b := testSystemBackend ( t )
2015-03-31 00:46:18 +00:00
actual := b . SpecialPaths ( ) . Root
2015-03-15 21:42:05 +00:00
if ! reflect . DeepEqual ( actual , expected ) {
2018-04-03 18:07:43 +00:00
t . Fatalf ( "bad: mismatch\nexpected:\n%#v\ngot:\n%#v" , expected , actual )
2015-03-15 21:42:05 +00:00
}
}
2017-06-17 04:04:55 +00:00
func TestSystemConfigCORS ( t * testing . T ) {
b := testSystemBackend ( t )
2017-06-17 05:26:25 +00:00
_ , barrier , _ := mockBarrier ( t )
view := NewBarrierView ( barrier , "" )
b . ( * SystemBackend ) . Core . systemBarrierView = view
2017-06-17 04:04:55 +00:00
req := logical . TestRequest ( t , logical . UpdateOperation , "config/cors" )
req . Data [ "allowed_origins" ] = "http://www.example.com"
2017-08-07 14:03:30 +00:00
req . Data [ "allowed_headers" ] = "X-Custom-Header"
2018-11-05 16:11:32 +00:00
_ , err := b . HandleRequest ( namespace . RootContext ( nil ) , req )
2017-06-17 04:04:55 +00:00
if err != nil {
t . Fatal ( err )
}
expected := & logical . Response {
Data : map [ string ] interface { } {
"enabled" : true ,
2017-06-17 05:26:25 +00:00
"allowed_origins" : [ ] string { "http://www.example.com" } ,
2017-08-07 19:02:08 +00:00
"allowed_headers" : append ( StdAllowedHeaders , "X-Custom-Header" ) ,
2017-06-17 04:04:55 +00:00
} ,
}
req = logical . TestRequest ( t , logical . ReadOperation , "config/cors" )
2018-11-05 16:11:32 +00:00
actual , err := b . HandleRequest ( namespace . RootContext ( nil ) , req )
2017-06-17 04:04:55 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
if ! reflect . DeepEqual ( actual , expected ) {
2017-06-17 05:26:25 +00:00
t . Fatalf ( "bad: %#v" , actual )
2017-06-17 04:04:55 +00:00
}
2019-02-11 18:10:26 +00:00
// Do it again. Bug #6182
req = logical . TestRequest ( t , logical . UpdateOperation , "config/cors" )
req . Data [ "allowed_origins" ] = "http://www.example.com"
req . Data [ "allowed_headers" ] = "X-Custom-Header"
_ , err = b . HandleRequest ( namespace . RootContext ( nil ) , req )
if err != nil {
t . Fatal ( err )
}
req = logical . TestRequest ( t , logical . ReadOperation , "config/cors" )
actual , err = b . HandleRequest ( namespace . RootContext ( nil ) , req )
if err != nil {
t . Fatalf ( "err: %v" , err )
}
if ! reflect . DeepEqual ( actual , expected ) {
t . Fatalf ( "bad: %#v" , actual )
}
2017-06-17 04:04:55 +00:00
req = logical . TestRequest ( t , logical . DeleteOperation , "config/cors" )
2018-11-05 16:11:32 +00:00
_ , err = b . HandleRequest ( namespace . RootContext ( nil ) , req )
2017-06-17 04:04:55 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
req = logical . TestRequest ( t , logical . ReadOperation , "config/cors" )
2018-11-05 16:11:32 +00:00
actual , err = b . HandleRequest ( namespace . RootContext ( nil ) , req )
2017-06-17 04:04:55 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
expected = & logical . Response {
Data : map [ string ] interface { } {
2017-06-17 05:26:25 +00:00
"enabled" : false ,
2017-06-17 04:04:55 +00:00
} ,
}
if ! reflect . DeepEqual ( actual , expected ) {
t . Fatalf ( "DELETE FAILED -- bad: %#v" , actual )
}
}
2015-03-15 21:42:05 +00:00
func TestSystemBackend_mounts ( t * testing . T ) {
b := testSystemBackend ( t )
req := logical . TestRequest ( t , logical . ReadOperation , "mounts" )
2018-11-05 16:11:32 +00:00
resp , err := b . HandleRequest ( namespace . RootContext ( nil ) , req )
2015-03-15 21:42:05 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
2015-09-01 22:29:30 +00:00
// We can't know the pointer address ahead of time so simply
// copy what's given
2015-03-15 21:42:05 +00:00
exp := map [ string ] interface { } {
2015-08-31 18:27:49 +00:00
"secret/" : map [ string ] interface { } {
2019-11-07 16:54:34 +00:00
"type" : "kv" ,
2019-10-17 17:33:00 +00:00
"external_entropy_access" : false ,
2019-11-07 16:54:34 +00:00
"description" : "key/value secret storage" ,
"accessor" : resp . Data [ "secret/" ] . ( map [ string ] interface { } ) [ "accessor" ] ,
"uuid" : resp . Data [ "secret/" ] . ( map [ string ] interface { } ) [ "uuid" ] ,
2015-08-31 18:27:49 +00:00
"config" : map [ string ] interface { } {
2016-06-21 00:08:12 +00:00
"default_lease_ttl" : resp . Data [ "secret/" ] . ( map [ string ] interface { } ) [ "config" ] . ( map [ string ] interface { } ) [ "default_lease_ttl" ] . ( int64 ) ,
"max_lease_ttl" : resp . Data [ "secret/" ] . ( map [ string ] interface { } ) [ "config" ] . ( map [ string ] interface { } ) [ "max_lease_ttl" ] . ( int64 ) ,
2017-03-08 14:20:09 +00:00
"force_no_cache" : false ,
2015-08-31 18:27:49 +00:00
} ,
2017-11-13 16:22:22 +00:00
"local" : false ,
"seal_wrap" : false ,
2018-03-21 19:04:27 +00:00
"options" : map [ string ] string {
2018-04-09 20:14:44 +00:00
"version" : "1" ,
2018-03-21 19:04:27 +00:00
} ,
2015-03-15 21:42:05 +00:00
} ,
2015-08-31 18:27:49 +00:00
"sys/" : map [ string ] interface { } {
2019-11-07 16:54:34 +00:00
"type" : "system" ,
2019-10-17 17:33:00 +00:00
"external_entropy_access" : false ,
2019-11-07 16:54:34 +00:00
"description" : "system endpoints used for control, policy and debugging" ,
"accessor" : resp . Data [ "sys/" ] . ( map [ string ] interface { } ) [ "accessor" ] ,
"uuid" : resp . Data [ "sys/" ] . ( map [ string ] interface { } ) [ "uuid" ] ,
2015-08-31 18:27:49 +00:00
"config" : map [ string ] interface { } {
2019-02-20 20:12:21 +00:00
"default_lease_ttl" : resp . Data [ "sys/" ] . ( map [ string ] interface { } ) [ "config" ] . ( map [ string ] interface { } ) [ "default_lease_ttl" ] . ( int64 ) ,
"max_lease_ttl" : resp . Data [ "sys/" ] . ( map [ string ] interface { } ) [ "config" ] . ( map [ string ] interface { } ) [ "max_lease_ttl" ] . ( int64 ) ,
"force_no_cache" : false ,
2019-02-15 19:14:45 +00:00
"passthrough_request_headers" : [ ] string { "Accept" } ,
2015-08-31 18:27:49 +00:00
} ,
2017-11-13 16:22:22 +00:00
"local" : false ,
"seal_wrap" : false ,
2018-03-21 19:04:27 +00:00
"options" : map [ string ] string ( nil ) ,
2015-03-15 21:42:05 +00:00
} ,
2015-09-10 01:58:09 +00:00
"cubbyhole/" : map [ string ] interface { } {
2019-11-07 16:54:34 +00:00
"description" : "per-token private secret storage" ,
"type" : "cubbyhole" ,
2019-10-17 17:33:00 +00:00
"external_entropy_access" : false ,
2019-11-07 16:54:34 +00:00
"accessor" : resp . Data [ "cubbyhole/" ] . ( map [ string ] interface { } ) [ "accessor" ] ,
"uuid" : resp . Data [ "cubbyhole/" ] . ( map [ string ] interface { } ) [ "uuid" ] ,
2015-09-10 01:58:09 +00:00
"config" : map [ string ] interface { } {
2016-06-21 00:08:12 +00:00
"default_lease_ttl" : resp . Data [ "cubbyhole/" ] . ( map [ string ] interface { } ) [ "config" ] . ( map [ string ] interface { } ) [ "default_lease_ttl" ] . ( int64 ) ,
"max_lease_ttl" : resp . Data [ "cubbyhole/" ] . ( map [ string ] interface { } ) [ "config" ] . ( map [ string ] interface { } ) [ "max_lease_ttl" ] . ( int64 ) ,
2017-03-08 14:20:09 +00:00
"force_no_cache" : false ,
2015-09-10 01:58:09 +00:00
} ,
2017-11-13 16:22:22 +00:00
"local" : true ,
"seal_wrap" : false ,
2018-03-21 19:04:27 +00:00
"options" : map [ string ] string ( nil ) ,
2015-09-10 01:58:09 +00:00
} ,
2017-10-11 17:21:20 +00:00
"identity/" : map [ string ] interface { } {
2019-11-07 16:54:34 +00:00
"description" : "identity store" ,
"type" : "identity" ,
2019-10-17 17:33:00 +00:00
"external_entropy_access" : false ,
2019-11-07 16:54:34 +00:00
"accessor" : resp . Data [ "identity/" ] . ( map [ string ] interface { } ) [ "accessor" ] ,
"uuid" : resp . Data [ "identity/" ] . ( map [ string ] interface { } ) [ "uuid" ] ,
2017-10-11 17:21:20 +00:00
"config" : map [ string ] interface { } {
"default_lease_ttl" : resp . Data [ "identity/" ] . ( map [ string ] interface { } ) [ "config" ] . ( map [ string ] interface { } ) [ "default_lease_ttl" ] . ( int64 ) ,
"max_lease_ttl" : resp . Data [ "identity/" ] . ( map [ string ] interface { } ) [ "config" ] . ( map [ string ] interface { } ) [ "max_lease_ttl" ] . ( int64 ) ,
"force_no_cache" : false ,
} ,
2017-11-13 16:22:22 +00:00
"local" : false ,
"seal_wrap" : false ,
2018-03-21 19:04:27 +00:00
"options" : map [ string ] string ( nil ) ,
2017-10-11 17:21:20 +00:00
} ,
2015-03-15 21:42:05 +00:00
}
2019-02-15 19:14:45 +00:00
if diff := deep . Equal ( resp . Data , exp ) ; len ( diff ) > 0 {
t . Fatalf ( "bad, diff: %#v" , diff )
2015-03-15 21:42:05 +00:00
}
}
func TestSystemBackend_mount ( t * testing . T ) {
b := testSystemBackend ( t )
2016-01-07 15:30:47 +00:00
req := logical . TestRequest ( t , logical . UpdateOperation , "mounts/prod/secret/" )
2017-09-15 13:02:29 +00:00
req . Data [ "type" ] = "kv"
2018-02-22 15:26:29 +00:00
req . Data [ "config" ] = map [ string ] interface { } {
"default_lease_ttl" : "35m" ,
"max_lease_ttl" : "45m" ,
}
2017-11-13 16:22:22 +00:00
req . Data [ "local" ] = true
req . Data [ "seal_wrap" ] = true
2018-03-21 19:04:27 +00:00
req . Data [ "options" ] = map [ string ] string {
2018-04-09 20:14:44 +00:00
"version" : "1" ,
2018-03-21 19:04:27 +00:00
}
2015-03-15 21:42:05 +00:00
2018-11-05 16:11:32 +00:00
resp , err := b . HandleRequest ( namespace . RootContext ( nil ) , req )
2015-03-15 21:42:05 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
if resp != nil {
t . Fatalf ( "bad: %v" , resp )
}
2017-11-13 16:22:22 +00:00
req = logical . TestRequest ( t , logical . ReadOperation , "mounts" )
2018-11-05 16:11:32 +00:00
resp , err = b . HandleRequest ( namespace . RootContext ( nil ) , req )
2017-11-13 16:22:22 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
// We can't know the pointer address ahead of time so simply
// copy what's given
exp := map [ string ] interface { } {
"secret/" : map [ string ] interface { } {
2019-11-07 16:54:34 +00:00
"type" : "kv" ,
2019-10-17 17:33:00 +00:00
"external_entropy_access" : false ,
2019-11-07 16:54:34 +00:00
"description" : "key/value secret storage" ,
"accessor" : resp . Data [ "secret/" ] . ( map [ string ] interface { } ) [ "accessor" ] ,
"uuid" : resp . Data [ "secret/" ] . ( map [ string ] interface { } ) [ "uuid" ] ,
2017-11-13 16:22:22 +00:00
"config" : map [ string ] interface { } {
"default_lease_ttl" : resp . Data [ "secret/" ] . ( map [ string ] interface { } ) [ "config" ] . ( map [ string ] interface { } ) [ "default_lease_ttl" ] . ( int64 ) ,
"max_lease_ttl" : resp . Data [ "secret/" ] . ( map [ string ] interface { } ) [ "config" ] . ( map [ string ] interface { } ) [ "max_lease_ttl" ] . ( int64 ) ,
"force_no_cache" : false ,
} ,
"local" : false ,
"seal_wrap" : false ,
2018-03-21 19:04:27 +00:00
"options" : map [ string ] string {
2018-04-09 20:14:44 +00:00
"version" : "1" ,
2018-03-21 19:04:27 +00:00
} ,
2017-11-13 16:22:22 +00:00
} ,
"sys/" : map [ string ] interface { } {
2019-11-07 16:54:34 +00:00
"type" : "system" ,
2019-10-17 17:33:00 +00:00
"external_entropy_access" : false ,
2019-11-07 16:54:34 +00:00
"description" : "system endpoints used for control, policy and debugging" ,
"accessor" : resp . Data [ "sys/" ] . ( map [ string ] interface { } ) [ "accessor" ] ,
"uuid" : resp . Data [ "sys/" ] . ( map [ string ] interface { } ) [ "uuid" ] ,
2017-11-13 16:22:22 +00:00
"config" : map [ string ] interface { } {
2019-02-20 20:12:21 +00:00
"default_lease_ttl" : resp . Data [ "sys/" ] . ( map [ string ] interface { } ) [ "config" ] . ( map [ string ] interface { } ) [ "default_lease_ttl" ] . ( int64 ) ,
"max_lease_ttl" : resp . Data [ "sys/" ] . ( map [ string ] interface { } ) [ "config" ] . ( map [ string ] interface { } ) [ "max_lease_ttl" ] . ( int64 ) ,
"force_no_cache" : false ,
2019-02-15 19:14:45 +00:00
"passthrough_request_headers" : [ ] string { "Accept" } ,
2017-11-13 16:22:22 +00:00
} ,
"local" : false ,
"seal_wrap" : false ,
2018-03-21 19:04:27 +00:00
"options" : map [ string ] string ( nil ) ,
2017-11-13 16:22:22 +00:00
} ,
"cubbyhole/" : map [ string ] interface { } {
2019-11-07 16:54:34 +00:00
"description" : "per-token private secret storage" ,
"type" : "cubbyhole" ,
2019-10-17 17:33:00 +00:00
"external_entropy_access" : false ,
2019-11-07 16:54:34 +00:00
"accessor" : resp . Data [ "cubbyhole/" ] . ( map [ string ] interface { } ) [ "accessor" ] ,
"uuid" : resp . Data [ "cubbyhole/" ] . ( map [ string ] interface { } ) [ "uuid" ] ,
2017-11-13 16:22:22 +00:00
"config" : map [ string ] interface { } {
"default_lease_ttl" : resp . Data [ "cubbyhole/" ] . ( map [ string ] interface { } ) [ "config" ] . ( map [ string ] interface { } ) [ "default_lease_ttl" ] . ( int64 ) ,
"max_lease_ttl" : resp . Data [ "cubbyhole/" ] . ( map [ string ] interface { } ) [ "config" ] . ( map [ string ] interface { } ) [ "max_lease_ttl" ] . ( int64 ) ,
"force_no_cache" : false ,
} ,
"local" : true ,
"seal_wrap" : false ,
2018-03-21 19:04:27 +00:00
"options" : map [ string ] string ( nil ) ,
2017-11-13 16:22:22 +00:00
} ,
"identity/" : map [ string ] interface { } {
2019-11-07 16:54:34 +00:00
"description" : "identity store" ,
"type" : "identity" ,
2019-10-17 17:33:00 +00:00
"external_entropy_access" : false ,
2019-11-07 16:54:34 +00:00
"accessor" : resp . Data [ "identity/" ] . ( map [ string ] interface { } ) [ "accessor" ] ,
"uuid" : resp . Data [ "identity/" ] . ( map [ string ] interface { } ) [ "uuid" ] ,
2017-11-13 16:22:22 +00:00
"config" : map [ string ] interface { } {
"default_lease_ttl" : resp . Data [ "identity/" ] . ( map [ string ] interface { } ) [ "config" ] . ( map [ string ] interface { } ) [ "default_lease_ttl" ] . ( int64 ) ,
"max_lease_ttl" : resp . Data [ "identity/" ] . ( map [ string ] interface { } ) [ "config" ] . ( map [ string ] interface { } ) [ "max_lease_ttl" ] . ( int64 ) ,
"force_no_cache" : false ,
} ,
"local" : false ,
"seal_wrap" : false ,
2018-03-21 19:04:27 +00:00
"options" : map [ string ] string ( nil ) ,
2017-11-13 16:22:22 +00:00
} ,
"prod/secret/" : map [ string ] interface { } {
2019-11-07 16:54:34 +00:00
"description" : "" ,
"type" : "kv" ,
2019-10-17 17:33:00 +00:00
"external_entropy_access" : false ,
2019-11-07 16:54:34 +00:00
"accessor" : resp . Data [ "prod/secret/" ] . ( map [ string ] interface { } ) [ "accessor" ] ,
"uuid" : resp . Data [ "prod/secret/" ] . ( map [ string ] interface { } ) [ "uuid" ] ,
2017-11-13 16:22:22 +00:00
"config" : map [ string ] interface { } {
2018-02-22 15:26:29 +00:00
"default_lease_ttl" : int64 ( 2100 ) ,
"max_lease_ttl" : int64 ( 2700 ) ,
2017-11-13 16:22:22 +00:00
"force_no_cache" : false ,
} ,
"local" : true ,
"seal_wrap" : true ,
2018-03-21 19:04:27 +00:00
"options" : map [ string ] string {
2018-04-09 20:14:44 +00:00
"version" : "1" ,
2018-03-21 19:04:27 +00:00
} ,
2017-11-13 16:22:22 +00:00
} ,
}
2019-02-15 19:14:45 +00:00
if diff := deep . Equal ( resp . Data , exp ) ; len ( diff ) > 0 {
t . Fatalf ( "bad: diff: %#v" , diff )
2017-11-13 16:22:22 +00:00
}
2015-03-15 21:42:05 +00:00
}
2017-03-08 14:20:09 +00:00
func TestSystemBackend_mount_force_no_cache ( t * testing . T ) {
core , b , _ := testCoreSystemBackend ( t )
req := logical . TestRequest ( t , logical . UpdateOperation , "mounts/prod/secret/" )
2017-09-15 13:02:29 +00:00
req . Data [ "type" ] = "kv"
2017-03-08 14:20:09 +00:00
req . Data [ "config" ] = map [ string ] interface { } {
"force_no_cache" : true ,
}
2018-11-05 16:11:32 +00:00
resp , err := b . HandleRequest ( namespace . RootContext ( nil ) , req )
2017-03-08 14:20:09 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
if resp != nil {
t . Fatalf ( "bad: %v" , resp )
}
2018-11-05 16:11:32 +00:00
mountEntry := core . router . MatchingMountEntry ( namespace . RootContext ( nil ) , "prod/secret/" )
2017-03-08 14:20:09 +00:00
if mountEntry == nil {
t . Fatalf ( "missing mount entry" )
}
if ! mountEntry . Config . ForceNoCache {
t . Fatalf ( "bad config %#v" , mountEntry )
}
}
2015-03-15 21:42:05 +00:00
func TestSystemBackend_mount_invalid ( t * testing . T ) {
b := testSystemBackend ( t )
2016-01-07 15:30:47 +00:00
req := logical . TestRequest ( t , logical . UpdateOperation , "mounts/prod/secret/" )
2015-03-15 21:42:05 +00:00
req . Data [ "type" ] = "nope"
2018-11-05 16:11:32 +00:00
resp , err := b . HandleRequest ( namespace . RootContext ( nil ) , req )
2015-03-15 21:53:41 +00:00
if err != logical . ErrInvalidRequest {
2015-03-15 21:42:05 +00:00
t . Fatalf ( "err: %v" , err )
}
2018-11-07 01:21:24 +00:00
if resp . Data [ "error" ] != ` plugin not found in the catalog: nope ` {
2015-03-15 21:42:05 +00:00
t . Fatalf ( "bad: %v" , resp )
}
}
func TestSystemBackend_unmount ( t * testing . T ) {
b := testSystemBackend ( t )
2015-03-16 17:52:35 +00:00
req := logical . TestRequest ( t , logical . DeleteOperation , "mounts/secret/" )
2018-11-05 16:11:32 +00:00
resp , err := b . HandleRequest ( namespace . RootContext ( nil ) , req )
2015-03-15 21:42:05 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
if resp != nil {
t . Fatalf ( "bad: %v" , resp )
}
}
2016-03-18 15:58:06 +00:00
var capabilitiesPolicy = `
name = "test"
path "foo/bar*" {
capabilities = [ "create" , "sudo" , "update" ]
}
path "sys/capabilities*" {
capabilities = [ "update" ]
}
2018-03-01 16:14:56 +00:00
path "bar/baz" {
capabilities = [ "read" , "update" ]
}
path "bar/baz" {
capabilities = [ "delete" ]
}
2016-03-18 15:58:06 +00:00
`
2018-03-01 16:14:56 +00:00
func TestSystemBackend_PathCapabilities ( t * testing . T ) {
var resp * logical . Response
var err error
core , b , rootToken := testCoreSystemBackend ( t )
2018-09-18 03:03:00 +00:00
policy , _ := ParseACLPolicy ( namespace . RootNamespace , capabilitiesPolicy )
2018-11-05 16:11:32 +00:00
err = core . policyStore . SetPolicy ( namespace . RootContext ( nil ) , policy )
2018-03-01 16:14:56 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
path1 := "foo/bar"
path2 := "foo/bar/sample"
path3 := "sys/capabilities"
path4 := "bar/baz"
rootCheckFunc := func ( t * testing . T , resp * logical . Response ) {
// All the paths should have "root" as the capability
expectedRoot := [ ] string { "root" }
if ! reflect . DeepEqual ( resp . Data [ path1 ] , expectedRoot ) ||
! reflect . DeepEqual ( resp . Data [ path2 ] , expectedRoot ) ||
! reflect . DeepEqual ( resp . Data [ path3 ] , expectedRoot ) ||
! reflect . DeepEqual ( resp . Data [ path4 ] , expectedRoot ) {
t . Fatalf ( "bad: capabilities; expected: %#v, actual: %#v" , expectedRoot , resp . Data )
}
}
// Check the capabilities using the root token
2018-11-05 16:11:32 +00:00
resp , err = b . HandleRequest ( namespace . RootContext ( nil ) , & logical . Request {
2018-03-01 16:14:56 +00:00
Path : "capabilities" ,
Operation : logical . UpdateOperation ,
Data : map [ string ] interface { } {
"paths" : [ ] string { path1 , path2 , path3 , path4 } ,
"token" : rootToken ,
} ,
} )
if err != nil || ( resp != nil && resp . IsError ( ) ) {
t . Fatalf ( "bad: resp: %#v\nerr: %v" , resp , err )
}
rootCheckFunc ( t , resp )
// Check the capabilities using capabilities-self
2018-11-05 16:11:32 +00:00
resp , err = b . HandleRequest ( namespace . RootContext ( nil ) , & logical . Request {
2018-03-01 16:14:56 +00:00
ClientToken : rootToken ,
Path : "capabilities-self" ,
Operation : logical . UpdateOperation ,
Data : map [ string ] interface { } {
"paths" : [ ] string { path1 , path2 , path3 , path4 } ,
} ,
} )
if err != nil || ( resp != nil && resp . IsError ( ) ) {
t . Fatalf ( "bad: resp: %#v\nerr: %v" , resp , err )
}
rootCheckFunc ( t , resp )
// Lookup the accessor of the root token
2018-11-05 16:11:32 +00:00
te , err := core . tokenStore . Lookup ( namespace . RootContext ( nil ) , rootToken )
2018-03-01 16:14:56 +00:00
if err != nil {
t . Fatal ( err )
}
// Check the capabilities using capabilities-accessor endpoint
2018-11-05 16:11:32 +00:00
resp , err = b . HandleRequest ( namespace . RootContext ( nil ) , & logical . Request {
2018-03-01 16:14:56 +00:00
Path : "capabilities-accessor" ,
Operation : logical . UpdateOperation ,
Data : map [ string ] interface { } {
"paths" : [ ] string { path1 , path2 , path3 , path4 } ,
"accessor" : te . Accessor ,
} ,
} )
if err != nil || ( resp != nil && resp . IsError ( ) ) {
t . Fatalf ( "bad: resp: %#v\nerr: %v" , resp , err )
}
rootCheckFunc ( t , resp )
// Create a non-root token
2018-10-15 16:56:24 +00:00
testMakeServiceTokenViaBackend ( t , core . tokenStore , rootToken , "tokenid" , "" , [ ] string { "test" } )
2018-03-01 16:14:56 +00:00
nonRootCheckFunc := func ( t * testing . T , resp * logical . Response ) {
expected1 := [ ] string { "create" , "sudo" , "update" }
expected2 := expected1
expected3 := [ ] string { "update" }
expected4 := [ ] string { "delete" , "read" , "update" }
if ! reflect . DeepEqual ( resp . Data [ path1 ] , expected1 ) ||
! reflect . DeepEqual ( resp . Data [ path2 ] , expected2 ) ||
! reflect . DeepEqual ( resp . Data [ path3 ] , expected3 ) ||
! reflect . DeepEqual ( resp . Data [ path4 ] , expected4 ) {
t . Fatalf ( "bad: capabilities; actual: %#v" , resp . Data )
}
}
// Check the capabilities using a non-root token
2018-11-05 16:11:32 +00:00
resp , err = b . HandleRequest ( namespace . RootContext ( nil ) , & logical . Request {
2018-03-01 16:14:56 +00:00
Path : "capabilities" ,
Operation : logical . UpdateOperation ,
Data : map [ string ] interface { } {
"paths" : [ ] string { path1 , path2 , path3 , path4 } ,
"token" : "tokenid" ,
} ,
} )
if err != nil || ( resp != nil && resp . IsError ( ) ) {
t . Fatalf ( "bad: resp: %#v\nerr: %v" , resp , err )
}
nonRootCheckFunc ( t , resp )
// Check the capabilities of a non-root token using capabilities-self
// endpoint
2018-11-05 16:11:32 +00:00
resp , err = b . HandleRequest ( namespace . RootContext ( nil ) , & logical . Request {
2018-03-01 16:14:56 +00:00
ClientToken : "tokenid" ,
Path : "capabilities-self" ,
Operation : logical . UpdateOperation ,
Data : map [ string ] interface { } {
"paths" : [ ] string { path1 , path2 , path3 , path4 } ,
} ,
} )
if err != nil || ( resp != nil && resp . IsError ( ) ) {
t . Fatalf ( "bad: resp: %#v\nerr: %v" , resp , err )
}
nonRootCheckFunc ( t , resp )
// Lookup the accessor of the non-root token
2018-11-05 16:11:32 +00:00
te , err = core . tokenStore . Lookup ( namespace . RootContext ( nil ) , "tokenid" )
2018-03-01 16:14:56 +00:00
if err != nil {
t . Fatal ( err )
}
// Check the capabilities using a non-root token using
// capabilities-accessor endpoint
2018-11-05 16:11:32 +00:00
resp , err = b . HandleRequest ( namespace . RootContext ( nil ) , & logical . Request {
2018-03-01 16:14:56 +00:00
Path : "capabilities-accessor" ,
Operation : logical . UpdateOperation ,
Data : map [ string ] interface { } {
"paths" : [ ] string { path1 , path2 , path3 , path4 } ,
"accessor" : te . Accessor ,
} ,
} )
if err != nil || ( resp != nil && resp . IsError ( ) ) {
t . Fatalf ( "bad: resp: %#v\nerr: %v" , resp , err )
}
nonRootCheckFunc ( t , resp )
}
func TestSystemBackend_Capabilities_BC ( t * testing . T ) {
2016-03-18 15:58:06 +00:00
testCapabilities ( t , "capabilities" )
testCapabilities ( t , "capabilities-self" )
}
func testCapabilities ( t * testing . T , endpoint string ) {
core , b , rootToken := testCoreSystemBackend ( t )
req := logical . TestRequest ( t , logical . UpdateOperation , endpoint )
2018-03-01 16:14:56 +00:00
if endpoint == "capabilities-self" {
req . ClientToken = rootToken
} else {
req . Data [ "token" ] = rootToken
}
2016-03-18 15:58:06 +00:00
req . Data [ "path" ] = "any_path"
2018-11-05 16:11:32 +00:00
resp , err := b . HandleRequest ( namespace . RootContext ( nil ) , req )
2016-03-18 15:58:06 +00:00
if err != nil {
t . Fatal ( err )
}
if resp == nil {
t . Fatalf ( "bad: %v" , resp )
}
actual := resp . Data [ "capabilities" ]
expected := [ ] string { "root" }
if ! reflect . DeepEqual ( actual , expected ) {
t . Fatalf ( "bad: got\n%#v\nexpected\n%#v\n" , actual , expected )
}
2018-09-18 03:03:00 +00:00
policy , _ := ParseACLPolicy ( namespace . RootNamespace , capabilitiesPolicy )
2018-11-05 16:11:32 +00:00
err = core . policyStore . SetPolicy ( namespace . RootContext ( nil ) , policy )
2016-03-18 15:58:06 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
2018-10-15 16:56:24 +00:00
testMakeServiceTokenViaBackend ( t , core . tokenStore , rootToken , "tokenid" , "" , [ ] string { "test" } )
2016-03-18 15:58:06 +00:00
req = logical . TestRequest ( t , logical . UpdateOperation , endpoint )
2018-03-01 16:14:56 +00:00
if endpoint == "capabilities-self" {
req . ClientToken = "tokenid"
} else {
req . Data [ "token" ] = "tokenid"
}
2016-03-18 15:58:06 +00:00
req . Data [ "path" ] = "foo/bar"
2018-11-05 16:11:32 +00:00
resp , err = b . HandleRequest ( namespace . RootContext ( nil ) , req )
2016-03-18 15:58:06 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
if resp == nil {
t . Fatalf ( "bad: %v" , resp )
}
actual = resp . Data [ "capabilities" ]
2016-03-18 16:40:17 +00:00
expected = [ ] string { "create" , "sudo" , "update" }
2016-03-18 15:58:06 +00:00
if ! reflect . DeepEqual ( actual , expected ) {
t . Fatalf ( "bad: got\n%#v\nexpected\n%#v\n" , actual , expected )
}
}
2018-03-01 16:14:56 +00:00
func TestSystemBackend_CapabilitiesAccessor_BC ( t * testing . T ) {
2016-03-18 15:58:06 +00:00
core , b , rootToken := testCoreSystemBackend ( t )
2018-11-05 16:11:32 +00:00
te , err := core . tokenStore . Lookup ( namespace . RootContext ( nil ) , rootToken )
2016-03-18 15:58:06 +00:00
if err != nil {
t . Fatal ( err )
}
2016-03-18 14:37:49 +00:00
req := logical . TestRequest ( t , logical . UpdateOperation , "capabilities-accessor" )
2016-03-18 15:58:06 +00:00
// Accessor of root token
req . Data [ "accessor" ] = te . Accessor
req . Data [ "path" ] = "any_path"
2018-11-05 16:11:32 +00:00
resp , err := b . HandleRequest ( namespace . RootContext ( nil ) , req )
2016-03-18 14:37:49 +00:00
if err != nil {
2016-03-18 15:58:06 +00:00
t . Fatalf ( "err: %v" , err )
}
if resp == nil {
t . Fatalf ( "bad: %v" , resp )
}
actual := resp . Data [ "capabilities" ]
expected := [ ] string { "root" }
if ! reflect . DeepEqual ( actual , expected ) {
t . Fatalf ( "bad: got\n%#v\nexpected\n%#v\n" , actual , expected )
}
2018-09-18 03:03:00 +00:00
policy , _ := ParseACLPolicy ( namespace . RootNamespace , capabilitiesPolicy )
2018-11-05 16:11:32 +00:00
err = core . policyStore . SetPolicy ( namespace . RootContext ( nil ) , policy )
2016-03-18 15:58:06 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
2018-10-15 16:56:24 +00:00
testMakeServiceTokenViaBackend ( t , core . tokenStore , rootToken , "tokenid" , "" , [ ] string { "test" } )
2016-03-18 15:58:06 +00:00
2018-11-05 16:11:32 +00:00
te , err = core . tokenStore . Lookup ( namespace . RootContext ( nil ) , "tokenid" )
2016-03-18 15:58:06 +00:00
if err != nil {
t . Fatal ( err )
}
req = logical . TestRequest ( t , logical . UpdateOperation , "capabilities-accessor" )
req . Data [ "accessor" ] = te . Accessor
req . Data [ "path" ] = "foo/bar"
2018-11-05 16:11:32 +00:00
resp , err = b . HandleRequest ( namespace . RootContext ( nil ) , req )
2016-03-18 15:58:06 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
if resp == nil {
t . Fatalf ( "bad: %v" , resp )
}
actual = resp . Data [ "capabilities" ]
2016-03-18 16:40:17 +00:00
expected = [ ] string { "create" , "sudo" , "update" }
2016-03-18 15:58:06 +00:00
if ! reflect . DeepEqual ( actual , expected ) {
t . Fatalf ( "bad: got\n%#v\nexpected\n%#v\n" , actual , expected )
2016-03-18 14:37:49 +00:00
}
}
2015-03-15 21:42:05 +00:00
func TestSystemBackend_remount ( t * testing . T ) {
b := testSystemBackend ( t )
2016-01-07 15:30:47 +00:00
req := logical . TestRequest ( t , logical . UpdateOperation , "remount" )
2015-03-15 21:42:05 +00:00
req . Data [ "from" ] = "secret"
req . Data [ "to" ] = "foo"
2015-09-01 22:29:30 +00:00
req . Data [ "config" ] = structs . Map ( MountConfig { } )
2018-11-05 16:11:32 +00:00
resp , err := b . HandleRequest ( namespace . RootContext ( nil ) , req )
2015-03-15 21:42:05 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
if resp != nil {
t . Fatalf ( "bad: %v" , resp )
}
}
func TestSystemBackend_remount_invalid ( t * testing . T ) {
b := testSystemBackend ( t )
2016-01-07 15:30:47 +00:00
req := logical . TestRequest ( t , logical . UpdateOperation , "remount" )
2015-03-15 21:42:05 +00:00
req . Data [ "from" ] = "unknown"
req . Data [ "to" ] = "foo"
2015-09-01 22:29:30 +00:00
req . Data [ "config" ] = structs . Map ( MountConfig { } )
2018-11-05 16:11:32 +00:00
resp , err := b . HandleRequest ( namespace . RootContext ( nil ) , req )
2015-03-15 21:53:41 +00:00
if err != logical . ErrInvalidRequest {
2015-03-15 21:42:05 +00:00
t . Fatalf ( "err: %v" , err )
}
2018-04-06 00:43:29 +00:00
if resp . Data [ "error" ] != ` no matching mount at "unknown/" ` {
2015-03-15 21:42:05 +00:00
t . Fatalf ( "bad: %v" , resp )
}
}
func TestSystemBackend_remount_system ( t * testing . T ) {
b := testSystemBackend ( t )
2016-01-07 15:30:47 +00:00
req := logical . TestRequest ( t , logical . UpdateOperation , "remount" )
2015-03-15 21:42:05 +00:00
req . Data [ "from" ] = "sys"
req . Data [ "to" ] = "foo"
2018-11-05 16:11:32 +00:00
resp , err := b . HandleRequest ( namespace . RootContext ( nil ) , req )
2015-03-15 21:53:41 +00:00
if err != logical . ErrInvalidRequest {
2015-03-15 21:42:05 +00:00
t . Fatalf ( "err: %v" , err )
}
2018-04-06 00:43:29 +00:00
if resp . Data [ "error" ] != ` cannot remount "sys/" ` {
2015-03-15 21:42:05 +00:00
t . Fatalf ( "bad: %v" , resp )
}
}
2020-10-29 18:06:07 +00:00
func TestSystemBackend_remount_clean ( t * testing . T ) {
b := testSystemBackend ( t )
req := logical . TestRequest ( t , logical . UpdateOperation , "remount" )
req . Data [ "from" ] = "foo"
req . Data [ "to" ] = "foo//bar"
req . Data [ "config" ] = structs . Map ( MountConfig { } )
resp , err := b . HandleRequest ( namespace . RootContext ( nil ) , req )
if err != logical . ErrInvalidRequest {
t . Fatalf ( "err: %v" , err )
}
if resp . Data [ "error" ] != ` 'to' path 'foo//bar' does not match cleaned path 'foo/bar' ` {
t . Fatalf ( "bad: %v" , resp )
}
}
func TestSystemBackend_remount_nonPrintable ( t * testing . T ) {
b := testSystemBackend ( t )
req := logical . TestRequest ( t , logical . UpdateOperation , "remount" )
req . Data [ "from" ] = "foo"
req . Data [ "to" ] = "foo\nbar"
req . Data [ "config" ] = structs . Map ( MountConfig { } )
resp , err := b . HandleRequest ( namespace . RootContext ( nil ) , req )
if err != logical . ErrInvalidRequest {
t . Fatalf ( "err: %v" , err )
}
if resp . Data [ "error" ] != ` 'to' path cannot contain non-printable characters ` {
t . Fatalf ( "bad: %v" , resp )
}
}
2017-05-04 02:03:42 +00:00
func TestSystemBackend_leases ( t * testing . T ) {
core , b , root := testCoreSystemBackend ( t )
// Create a key with a lease
req := logical . TestRequest ( t , logical . UpdateOperation , "secret/foo" )
req . Data [ "foo" ] = "bar"
req . ClientToken = root
2018-11-05 16:11:32 +00:00
resp , err := core . HandleRequest ( namespace . RootContext ( nil ) , req )
2017-05-04 02:03:42 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
if resp != nil {
t . Fatalf ( "bad: %#v" , resp )
}
// Read a key with a LeaseID
req = logical . TestRequest ( t , logical . ReadOperation , "secret/foo" )
req . ClientToken = root
2018-10-15 16:56:24 +00:00
req . SetTokenEntry ( & logical . TokenEntry { ID : root , NamespaceID : "root" , Policies : [ ] string { "root" } } )
2018-11-05 16:11:32 +00:00
resp , err = core . HandleRequest ( namespace . RootContext ( nil ) , req )
2017-05-04 02:03:42 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
if resp == nil || resp . Secret == nil || resp . Secret . LeaseID == "" {
t . Fatalf ( "bad: %#v" , resp )
}
// Read lease
req = logical . TestRequest ( t , logical . UpdateOperation , "leases/lookup" )
req . Data [ "lease_id" ] = resp . Secret . LeaseID
2018-11-05 16:11:32 +00:00
resp , err = b . HandleRequest ( namespace . RootContext ( nil ) , req )
2017-05-04 02:03:42 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
if resp . Data [ "renewable" ] == nil || resp . Data [ "renewable" ] . ( bool ) {
2017-09-15 13:02:29 +00:00
t . Fatal ( "kv leases are not renewable" )
2017-05-04 02:03:42 +00:00
}
// Invalid lease
req = logical . TestRequest ( t , logical . UpdateOperation , "leases/lookup" )
req . Data [ "lease_id" ] = "invalid"
2018-11-05 16:11:32 +00:00
resp , err = b . HandleRequest ( namespace . RootContext ( nil ) , req )
2017-05-04 02:03:42 +00:00
if err != logical . ErrInvalidRequest {
t . Fatalf ( "expected invalid request, got err: %v" , err )
}
}
func TestSystemBackend_leases_list ( t * testing . T ) {
core , b , root := testCoreSystemBackend ( t )
// Create a key with a lease
req := logical . TestRequest ( t , logical . UpdateOperation , "secret/foo" )
req . Data [ "foo" ] = "bar"
req . ClientToken = root
2018-11-05 16:11:32 +00:00
resp , err := core . HandleRequest ( namespace . RootContext ( nil ) , req )
2017-05-04 02:03:42 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
if resp != nil {
t . Fatalf ( "bad: %#v" , resp )
}
// Read a key with a LeaseID
req = logical . TestRequest ( t , logical . ReadOperation , "secret/foo" )
req . ClientToken = root
2018-10-15 16:56:24 +00:00
req . SetTokenEntry ( & logical . TokenEntry { ID : root , NamespaceID : "root" , Policies : [ ] string { "root" } } )
2018-11-05 16:11:32 +00:00
resp , err = core . HandleRequest ( namespace . RootContext ( nil ) , req )
2017-05-04 02:03:42 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
if resp == nil || resp . Secret == nil || resp . Secret . LeaseID == "" {
t . Fatalf ( "bad: %#v" , resp )
}
// List top level
req = logical . TestRequest ( t , logical . ListOperation , "leases/lookup/" )
2018-11-05 16:11:32 +00:00
resp , err = b . HandleRequest ( namespace . RootContext ( nil ) , req )
2017-05-04 02:03:42 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
if resp == nil || resp . Data == nil {
t . Fatalf ( "bad: %#v" , resp )
}
var keys [ ] string
if err := mapstructure . WeakDecode ( resp . Data [ "keys" ] , & keys ) ; err != nil {
t . Fatalf ( "err: %v" , err )
}
if len ( keys ) != 1 {
t . Fatalf ( "Expected 1 subkey lease, got %d: %#v" , len ( keys ) , keys )
}
if keys [ 0 ] != "secret/" {
t . Fatal ( "Expected only secret subkey" )
}
// List lease
req = logical . TestRequest ( t , logical . ListOperation , "leases/lookup/secret/foo" )
2018-11-05 16:11:32 +00:00
resp , err = b . HandleRequest ( namespace . RootContext ( nil ) , req )
2017-05-04 02:03:42 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
if resp == nil || resp . Data == nil {
t . Fatalf ( "bad: %#v" , resp )
}
keys = [ ] string { }
if err := mapstructure . WeakDecode ( resp . Data [ "keys" ] , & keys ) ; err != nil {
t . Fatalf ( "err: %v" , err )
}
if len ( keys ) != 1 {
t . Fatalf ( "Expected 1 secret lease, got %d: %#v" , len ( keys ) , keys )
}
// Generate multiple leases
req = logical . TestRequest ( t , logical . ReadOperation , "secret/foo" )
req . ClientToken = root
2018-10-15 16:56:24 +00:00
req . SetTokenEntry ( & logical . TokenEntry { ID : root , NamespaceID : "root" , Policies : [ ] string { "root" } } )
2018-11-05 16:11:32 +00:00
resp , err = core . HandleRequest ( namespace . RootContext ( nil ) , req )
2017-05-04 02:03:42 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
if resp == nil || resp . Secret == nil || resp . Secret . LeaseID == "" {
t . Fatalf ( "bad: %#v" , resp )
}
req = logical . TestRequest ( t , logical . ReadOperation , "secret/foo" )
req . ClientToken = root
2018-10-15 16:56:24 +00:00
req . SetTokenEntry ( & logical . TokenEntry { ID : root , NamespaceID : "root" , Policies : [ ] string { "root" } } )
2018-11-05 16:11:32 +00:00
resp , err = core . HandleRequest ( namespace . RootContext ( nil ) , req )
2017-05-04 02:03:42 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
if resp == nil || resp . Secret == nil || resp . Secret . LeaseID == "" {
t . Fatalf ( "bad: %#v" , resp )
}
req = logical . TestRequest ( t , logical . ListOperation , "leases/lookup/secret/foo" )
2018-11-05 16:11:32 +00:00
resp , err = b . HandleRequest ( namespace . RootContext ( nil ) , req )
2017-05-04 02:03:42 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
if resp == nil || resp . Data == nil {
t . Fatalf ( "bad: %#v" , resp )
}
keys = [ ] string { }
if err := mapstructure . WeakDecode ( resp . Data [ "keys" ] , & keys ) ; err != nil {
t . Fatalf ( "err: %v" , err )
}
if len ( keys ) != 3 {
t . Fatalf ( "Expected 3 secret lease, got %d: %#v" , len ( keys ) , keys )
}
// Listing subkeys
req = logical . TestRequest ( t , logical . UpdateOperation , "secret/bar" )
req . Data [ "foo" ] = "bar"
req . ClientToken = root
2018-11-05 16:11:32 +00:00
resp , err = core . HandleRequest ( namespace . RootContext ( nil ) , req )
2017-05-04 02:03:42 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
if resp != nil {
t . Fatalf ( "bad: %#v" , resp )
}
// Read a key with a LeaseID
req = logical . TestRequest ( t , logical . ReadOperation , "secret/bar" )
req . ClientToken = root
2018-10-15 16:56:24 +00:00
req . SetTokenEntry ( & logical . TokenEntry { ID : root , NamespaceID : "root" , Policies : [ ] string { "root" } } )
2018-11-05 16:11:32 +00:00
resp , err = core . HandleRequest ( namespace . RootContext ( nil ) , req )
2017-05-04 02:03:42 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
if resp == nil || resp . Secret == nil || resp . Secret . LeaseID == "" {
t . Fatalf ( "bad: %#v" , resp )
}
req = logical . TestRequest ( t , logical . ListOperation , "leases/lookup/secret" )
2018-11-05 16:11:32 +00:00
resp , err = b . HandleRequest ( namespace . RootContext ( nil ) , req )
2017-05-04 02:03:42 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
if resp == nil || resp . Data == nil {
t . Fatalf ( "bad: %#v" , resp )
}
keys = [ ] string { }
if err := mapstructure . WeakDecode ( resp . Data [ "keys" ] , & keys ) ; err != nil {
t . Fatalf ( "err: %v" , err )
}
if len ( keys ) != 2 {
t . Fatalf ( "Expected 2 secret lease, got %d: %#v" , len ( keys ) , keys )
}
expected := [ ] string { "bar/" , "foo/" }
if ! reflect . DeepEqual ( expected , keys ) {
t . Fatalf ( "exp: %#v, act: %#v" , expected , keys )
}
}
2015-03-16 23:11:55 +00:00
func TestSystemBackend_renew ( t * testing . T ) {
2015-03-24 18:37:07 +00:00
core , b , root := testCoreSystemBackend ( t )
2015-03-16 23:11:55 +00:00
// Create a key with a lease
2016-01-07 15:30:47 +00:00
req := logical . TestRequest ( t , logical . UpdateOperation , "secret/foo" )
2015-03-16 23:11:55 +00:00
req . Data [ "foo" ] = "bar"
2015-03-24 18:37:07 +00:00
req . ClientToken = root
2018-11-05 16:11:32 +00:00
resp , err := core . HandleRequest ( namespace . RootContext ( nil ) , req )
2015-03-16 23:11:55 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
if resp != nil {
t . Fatalf ( "bad: %#v" , resp )
}
2015-04-08 20:35:32 +00:00
// Read a key with a LeaseID
2015-03-16 23:11:55 +00:00
req = logical . TestRequest ( t , logical . ReadOperation , "secret/foo" )
2015-03-24 18:37:07 +00:00
req . ClientToken = root
2018-10-15 16:56:24 +00:00
req . SetTokenEntry ( & logical . TokenEntry { ID : root , NamespaceID : "root" , Policies : [ ] string { "root" } } )
2018-11-05 16:11:32 +00:00
resp , err = core . HandleRequest ( namespace . RootContext ( nil ) , req )
2015-03-16 23:11:55 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
2015-04-08 20:35:32 +00:00
if resp == nil || resp . Secret == nil || resp . Secret . LeaseID == "" {
2015-03-16 23:11:55 +00:00
t . Fatalf ( "bad: %#v" , resp )
}
// Attempt renew
2017-05-04 02:03:42 +00:00
req2 := logical . TestRequest ( t , logical . UpdateOperation , "leases/renew/" + resp . Secret . LeaseID )
2018-11-05 16:11:32 +00:00
resp2 , err := b . HandleRequest ( namespace . RootContext ( nil ) , req2 )
2015-04-09 00:03:46 +00:00
if err != logical . ErrInvalidRequest {
2015-03-16 23:11:55 +00:00
t . Fatalf ( "err: %v" , err )
}
2015-04-09 00:03:46 +00:00
// Should get error about non-renewability
if resp2 . Data [ "error" ] != "lease is not renewable" {
2015-03-16 23:11:55 +00:00
t . Fatalf ( "bad: %#v" , resp )
}
2016-08-08 22:32:18 +00:00
// Add a TTL to the lease
req = logical . TestRequest ( t , logical . UpdateOperation , "secret/foo" )
req . Data [ "foo" ] = "bar"
req . Data [ "ttl" ] = "180s"
req . ClientToken = root
2018-11-05 16:11:32 +00:00
resp , err = core . HandleRequest ( namespace . RootContext ( nil ) , req )
2016-08-08 22:32:18 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
if resp != nil {
t . Fatalf ( "bad: %#v" , resp )
}
// Read a key with a LeaseID
req = logical . TestRequest ( t , logical . ReadOperation , "secret/foo" )
req . ClientToken = root
2018-10-15 16:56:24 +00:00
req . SetTokenEntry ( & logical . TokenEntry { ID : root , NamespaceID : "root" , Policies : [ ] string { "root" } } )
2018-11-05 16:11:32 +00:00
resp , err = core . HandleRequest ( namespace . RootContext ( nil ) , req )
2016-08-08 22:32:18 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
if resp == nil || resp . Secret == nil || resp . Secret . LeaseID == "" {
t . Fatalf ( "bad: %#v" , resp )
}
// Attempt renew
2017-05-04 02:03:42 +00:00
req2 = logical . TestRequest ( t , logical . UpdateOperation , "leases/renew/" + resp . Secret . LeaseID )
2018-11-05 16:11:32 +00:00
resp2 , err = b . HandleRequest ( namespace . RootContext ( nil ) , req2 )
2016-08-08 22:32:18 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
if resp2 . IsError ( ) {
t . Fatalf ( "got an error" )
}
if resp2 . Data == nil {
t . Fatal ( "nil data" )
}
if resp . Secret . TTL != 180 * time . Second {
2016-08-09 11:13:29 +00:00
t . Fatalf ( "bad lease duration: %v" , resp . Secret . TTL )
2016-08-08 22:32:18 +00:00
}
// Test the other route path
2017-05-04 02:03:42 +00:00
req2 = logical . TestRequest ( t , logical . UpdateOperation , "leases/renew" )
req2 . Data [ "lease_id" ] = resp . Secret . LeaseID
2018-11-05 16:11:32 +00:00
resp2 , err = b . HandleRequest ( namespace . RootContext ( nil ) , req2 )
2017-05-04 02:03:42 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
if resp2 . IsError ( ) {
t . Fatalf ( "got an error" )
}
if resp2 . Data == nil {
t . Fatal ( "nil data" )
}
if resp . Secret . TTL != 180 * time . Second {
t . Fatalf ( "bad lease duration: %v" , resp . Secret . TTL )
}
// Test orig path
2016-08-08 22:32:18 +00:00
req2 = logical . TestRequest ( t , logical . UpdateOperation , "renew" )
req2 . Data [ "lease_id" ] = resp . Secret . LeaseID
2018-11-05 16:11:32 +00:00
resp2 , err = b . HandleRequest ( namespace . RootContext ( nil ) , req2 )
2016-08-08 22:32:18 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
if resp2 . IsError ( ) {
t . Fatalf ( "got an error" )
}
if resp2 . Data == nil {
t . Fatal ( "nil data" )
}
2018-10-15 16:56:24 +00:00
if resp . Secret . TTL != time . Second * 180 {
2016-08-09 11:13:29 +00:00
t . Fatalf ( "bad lease duration: %v" , resp . Secret . TTL )
2016-08-08 22:32:18 +00:00
}
2015-03-16 23:11:55 +00:00
}
2015-03-16 23:14:53 +00:00
func TestSystemBackend_renew_invalidID ( t * testing . T ) {
b := testSystemBackend ( t )
2017-05-04 02:03:42 +00:00
// Attempt renew
req := logical . TestRequest ( t , logical . UpdateOperation , "leases/renew/foobarbaz" )
2018-11-05 16:11:32 +00:00
resp , err := b . HandleRequest ( namespace . RootContext ( nil ) , req )
2017-05-04 02:03:42 +00:00
if err != logical . ErrInvalidRequest {
t . Fatalf ( "err: %v" , err )
}
2018-10-15 16:56:24 +00:00
if resp . Data [ "error" ] != "lease not found" {
2017-05-04 02:03:42 +00:00
t . Fatalf ( "bad: %v" , resp )
}
// Attempt renew with other method
req = logical . TestRequest ( t , logical . UpdateOperation , "leases/renew" )
req . Data [ "lease_id" ] = "foobarbaz"
2018-11-05 16:11:32 +00:00
resp , err = b . HandleRequest ( namespace . RootContext ( nil ) , req )
2017-05-04 02:03:42 +00:00
if err != logical . ErrInvalidRequest {
t . Fatalf ( "err: %v" , err )
}
2018-10-15 16:56:24 +00:00
if resp . Data [ "error" ] != "lease not found" {
2017-05-04 02:03:42 +00:00
t . Fatalf ( "bad: %v" , resp )
}
}
func TestSystemBackend_renew_invalidID_origUrl ( t * testing . T ) {
b := testSystemBackend ( t )
2015-03-16 23:14:53 +00:00
// Attempt renew
2016-01-07 15:30:47 +00:00
req := logical . TestRequest ( t , logical . UpdateOperation , "renew/foobarbaz" )
2018-11-05 16:11:32 +00:00
resp , err := b . HandleRequest ( namespace . RootContext ( nil ) , req )
2015-03-16 23:14:53 +00:00
if err != logical . ErrInvalidRequest {
t . Fatalf ( "err: %v" , err )
}
2018-10-15 16:56:24 +00:00
if resp . Data [ "error" ] != "lease not found" {
2015-03-16 23:14:53 +00:00
t . Fatalf ( "bad: %v" , resp )
}
2017-04-27 14:47:43 +00:00
// Attempt renew with other method
req = logical . TestRequest ( t , logical . UpdateOperation , "renew" )
req . Data [ "lease_id" ] = "foobarbaz"
2018-11-05 16:11:32 +00:00
resp , err = b . HandleRequest ( namespace . RootContext ( nil ) , req )
2017-04-27 14:47:43 +00:00
if err != logical . ErrInvalidRequest {
t . Fatalf ( "err: %v" , err )
}
2018-10-15 16:56:24 +00:00
if resp . Data [ "error" ] != "lease not found" {
2017-04-27 14:47:43 +00:00
t . Fatalf ( "bad: %v" , resp )
}
2015-03-16 23:14:53 +00:00
}
2015-03-16 23:26:34 +00:00
func TestSystemBackend_revoke ( t * testing . T ) {
2015-03-24 18:37:07 +00:00
core , b , root := testCoreSystemBackend ( t )
2015-03-16 23:26:34 +00:00
// Create a key with a lease
2016-01-07 15:30:47 +00:00
req := logical . TestRequest ( t , logical . UpdateOperation , "secret/foo" )
2015-03-16 23:26:34 +00:00
req . Data [ "foo" ] = "bar"
req . Data [ "lease" ] = "1h"
2015-03-24 18:37:07 +00:00
req . ClientToken = root
2018-11-05 16:11:32 +00:00
resp , err := core . HandleRequest ( namespace . RootContext ( nil ) , req )
2015-03-16 23:26:34 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
if resp != nil {
t . Fatalf ( "bad: %#v" , resp )
}
2015-04-08 20:35:32 +00:00
// Read a key with a LeaseID
2015-03-16 23:26:34 +00:00
req = logical . TestRequest ( t , logical . ReadOperation , "secret/foo" )
2015-03-24 18:37:07 +00:00
req . ClientToken = root
2018-10-15 16:56:24 +00:00
req . SetTokenEntry ( & logical . TokenEntry { ID : root , NamespaceID : "root" , Policies : [ ] string { "root" } } )
2018-11-05 16:11:32 +00:00
resp , err = core . HandleRequest ( namespace . RootContext ( nil ) , req )
2015-03-16 23:26:34 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
2015-04-08 20:35:32 +00:00
if resp == nil || resp . Secret == nil || resp . Secret . LeaseID == "" {
2015-03-16 23:26:34 +00:00
t . Fatalf ( "bad: %#v" , resp )
}
2015-03-16 23:33:48 +00:00
// Attempt revoke
2016-01-07 15:30:47 +00:00
req2 := logical . TestRequest ( t , logical . UpdateOperation , "revoke/" + resp . Secret . LeaseID )
2018-11-05 16:11:32 +00:00
resp2 , err := b . HandleRequest ( namespace . RootContext ( nil ) , req2 )
2015-03-16 23:26:34 +00:00
if err != nil {
t . Fatalf ( "err: %v %#v" , err , resp2 )
}
if resp2 != nil {
t . Fatalf ( "bad: %#v" , resp )
}
2015-03-16 23:33:48 +00:00
// Attempt renew
2016-01-07 15:30:47 +00:00
req3 := logical . TestRequest ( t , logical . UpdateOperation , "renew/" + resp . Secret . LeaseID )
2018-11-05 16:11:32 +00:00
resp3 , err := b . HandleRequest ( namespace . RootContext ( nil ) , req3 )
2015-03-16 23:33:48 +00:00
if err != logical . ErrInvalidRequest {
t . Fatalf ( "err: %v" , err )
}
2018-10-15 16:56:24 +00:00
if resp3 . Data [ "error" ] != "lease not found" {
t . Fatalf ( "bad: %v" , * resp3 )
2015-03-16 23:33:48 +00:00
}
2017-04-27 14:47:43 +00:00
// Read a key with a LeaseID
req = logical . TestRequest ( t , logical . ReadOperation , "secret/foo" )
req . ClientToken = root
2018-10-15 16:56:24 +00:00
req . SetTokenEntry ( & logical . TokenEntry { ID : root , NamespaceID : "root" , Policies : [ ] string { "root" } } )
2018-11-05 16:11:32 +00:00
resp , err = core . HandleRequest ( namespace . RootContext ( nil ) , req )
2017-04-27 14:47:43 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
if resp == nil || resp . Secret == nil || resp . Secret . LeaseID == "" {
t . Fatalf ( "bad: %#v" , resp )
}
// Test the other route path
req2 = logical . TestRequest ( t , logical . UpdateOperation , "revoke" )
req2 . Data [ "lease_id" ] = resp . Secret . LeaseID
2018-11-05 16:11:32 +00:00
resp2 , err = b . HandleRequest ( namespace . RootContext ( nil ) , req2 )
2017-04-27 14:47:43 +00:00
if err != nil {
t . Fatalf ( "err: %v %#v" , err , resp2 )
}
if resp2 != nil {
t . Fatalf ( "bad: %#v" , resp )
}
2017-05-04 02:03:42 +00:00
// Read a key with a LeaseID
req = logical . TestRequest ( t , logical . ReadOperation , "secret/foo" )
req . ClientToken = root
2018-10-15 16:56:24 +00:00
req . SetTokenEntry ( & logical . TokenEntry { ID : root , NamespaceID : "root" , Policies : [ ] string { "root" } } )
2018-11-05 16:11:32 +00:00
resp , err = core . HandleRequest ( namespace . RootContext ( nil ) , req )
2017-05-04 02:03:42 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
if resp == nil || resp . Secret == nil || resp . Secret . LeaseID == "" {
t . Fatalf ( "bad: %#v" , resp )
}
// Test the other route path
req2 = logical . TestRequest ( t , logical . UpdateOperation , "leases/revoke" )
req2 . Data [ "lease_id" ] = resp . Secret . LeaseID
2018-11-05 16:11:32 +00:00
resp2 , err = b . HandleRequest ( namespace . RootContext ( nil ) , req2 )
2017-05-04 02:03:42 +00:00
if err != nil {
t . Fatalf ( "err: %v %#v" , err , resp2 )
}
if resp2 != nil {
t . Fatalf ( "bad: %#v" , resp )
}
2015-03-16 23:26:34 +00:00
}
func TestSystemBackend_revoke_invalidID ( t * testing . T ) {
b := testSystemBackend ( t )
2017-05-04 02:03:42 +00:00
// Attempt revoke
req := logical . TestRequest ( t , logical . UpdateOperation , "leases/revoke/foobarbaz" )
2018-11-05 16:11:32 +00:00
resp , err := b . HandleRequest ( namespace . RootContext ( nil ) , req )
2017-05-04 02:03:42 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
if resp != nil {
t . Fatalf ( "bad: %v" , resp )
}
// Attempt revoke with other method
req = logical . TestRequest ( t , logical . UpdateOperation , "leases/revoke" )
req . Data [ "lease_id" ] = "foobarbaz"
2018-11-05 16:11:32 +00:00
resp , err = b . HandleRequest ( namespace . RootContext ( nil ) , req )
2017-05-04 02:03:42 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
if resp != nil {
t . Fatalf ( "bad: %v" , resp )
}
}
func TestSystemBackend_revoke_invalidID_origUrl ( t * testing . T ) {
b := testSystemBackend ( t )
2017-04-27 14:47:43 +00:00
// Attempt revoke
2016-01-07 15:30:47 +00:00
req := logical . TestRequest ( t , logical . UpdateOperation , "revoke/foobarbaz" )
2018-11-05 16:11:32 +00:00
resp , err := b . HandleRequest ( namespace . RootContext ( nil ) , req )
2015-03-16 23:26:34 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
if resp != nil {
t . Fatalf ( "bad: %v" , resp )
}
2017-04-27 14:47:43 +00:00
// Attempt revoke with other method
req = logical . TestRequest ( t , logical . UpdateOperation , "revoke" )
req . Data [ "lease_id" ] = "foobarbaz"
2018-11-05 16:11:32 +00:00
resp , err = b . HandleRequest ( namespace . RootContext ( nil ) , req )
2017-04-27 14:47:43 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
if resp != nil {
t . Fatalf ( "bad: %v" , resp )
}
2015-03-16 23:26:34 +00:00
}
2015-03-16 23:33:48 +00:00
func TestSystemBackend_revokePrefix ( t * testing . T ) {
2015-03-24 18:37:07 +00:00
core , b , root := testCoreSystemBackend ( t )
2015-03-16 23:33:48 +00:00
// Create a key with a lease
2016-01-07 15:30:47 +00:00
req := logical . TestRequest ( t , logical . UpdateOperation , "secret/foo" )
2015-03-16 23:33:48 +00:00
req . Data [ "foo" ] = "bar"
req . Data [ "lease" ] = "1h"
2015-03-24 18:37:07 +00:00
req . ClientToken = root
2018-11-05 16:11:32 +00:00
resp , err := core . HandleRequest ( namespace . RootContext ( nil ) , req )
2015-03-16 23:33:48 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
if resp != nil {
t . Fatalf ( "bad: %#v" , resp )
}
2015-04-08 20:35:32 +00:00
// Read a key with a LeaseID
2015-03-16 23:33:48 +00:00
req = logical . TestRequest ( t , logical . ReadOperation , "secret/foo" )
2015-03-24 18:37:07 +00:00
req . ClientToken = root
2018-10-15 16:56:24 +00:00
req . SetTokenEntry ( & logical . TokenEntry { ID : root , NamespaceID : "root" , Policies : [ ] string { "root" } } )
2018-11-05 16:11:32 +00:00
resp , err = core . HandleRequest ( namespace . RootContext ( nil ) , req )
2015-03-16 23:33:48 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
2015-04-08 20:35:32 +00:00
if resp == nil || resp . Secret == nil || resp . Secret . LeaseID == "" {
2015-03-16 23:33:48 +00:00
t . Fatalf ( "bad: %#v" , resp )
}
2017-05-04 02:03:42 +00:00
// Attempt revoke
req2 := logical . TestRequest ( t , logical . UpdateOperation , "leases/revoke-prefix/secret/" )
2018-11-05 16:11:32 +00:00
resp2 , err := b . HandleRequest ( namespace . RootContext ( nil ) , req2 )
2017-05-04 02:03:42 +00:00
if err != nil {
t . Fatalf ( "err: %v %#v" , err , resp2 )
}
if resp2 != nil {
t . Fatalf ( "bad: %#v" , resp )
}
// Attempt renew
req3 := logical . TestRequest ( t , logical . UpdateOperation , "leases/renew/" + resp . Secret . LeaseID )
2018-11-05 16:11:32 +00:00
resp3 , err := b . HandleRequest ( namespace . RootContext ( nil ) , req3 )
2017-05-04 02:03:42 +00:00
if err != logical . ErrInvalidRequest {
t . Fatalf ( "err: %v" , err )
}
2018-10-15 16:56:24 +00:00
if resp3 . Data [ "error" ] != "lease not found" {
t . Fatalf ( "bad: %v" , * resp3 )
2017-05-04 02:03:42 +00:00
}
}
func TestSystemBackend_revokePrefix_origUrl ( t * testing . T ) {
core , b , root := testCoreSystemBackend ( t )
// Create a key with a lease
req := logical . TestRequest ( t , logical . UpdateOperation , "secret/foo" )
req . Data [ "foo" ] = "bar"
req . Data [ "lease" ] = "1h"
req . ClientToken = root
2018-11-05 16:11:32 +00:00
resp , err := core . HandleRequest ( namespace . RootContext ( nil ) , req )
2017-05-04 02:03:42 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
if resp != nil {
t . Fatalf ( "bad: %#v" , resp )
}
// Read a key with a LeaseID
req = logical . TestRequest ( t , logical . ReadOperation , "secret/foo" )
req . ClientToken = root
2018-10-15 16:56:24 +00:00
req . SetTokenEntry ( & logical . TokenEntry { ID : root , NamespaceID : "root" , Policies : [ ] string { "root" } } )
2018-11-05 16:11:32 +00:00
resp , err = core . HandleRequest ( namespace . RootContext ( nil ) , req )
2017-05-04 02:03:42 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
if resp == nil || resp . Secret == nil || resp . Secret . LeaseID == "" {
t . Fatalf ( "bad: %#v" , resp )
}
2015-03-16 23:33:48 +00:00
// Attempt revoke
2016-01-07 15:30:47 +00:00
req2 := logical . TestRequest ( t , logical . UpdateOperation , "revoke-prefix/secret/" )
2018-11-05 16:11:32 +00:00
resp2 , err := b . HandleRequest ( namespace . RootContext ( nil ) , req2 )
2015-03-16 23:33:48 +00:00
if err != nil {
t . Fatalf ( "err: %v %#v" , err , resp2 )
}
if resp2 != nil {
t . Fatalf ( "bad: %#v" , resp )
}
// Attempt renew
2016-01-07 15:30:47 +00:00
req3 := logical . TestRequest ( t , logical . UpdateOperation , "renew/" + resp . Secret . LeaseID )
2018-11-05 16:11:32 +00:00
resp3 , err := b . HandleRequest ( namespace . RootContext ( nil ) , req3 )
2015-03-16 23:33:48 +00:00
if err != logical . ErrInvalidRequest {
t . Fatalf ( "err: %v" , err )
}
2018-10-15 16:56:24 +00:00
if resp3 . Data [ "error" ] != "lease not found" {
t . Fatalf ( "bad: %#v" , * resp3 )
2015-03-16 23:33:48 +00:00
}
}
2018-06-03 22:14:51 +00:00
func TestSystemBackend_revokePrefixAuth_newUrl ( t * testing . T ) {
core , _ , _ := TestCoreUnsealed ( t )
ts := core . tokenStore
2016-03-31 22:04:05 +00:00
bc := & logical . BackendConfig {
Logger : core . logger ,
System : logical . StaticSystemView {
DefaultLeaseTTLVal : time . Hour * 24 ,
2016-09-28 22:32:49 +00:00
MaxLeaseTTLVal : time . Hour * 24 * 32 ,
2016-03-31 22:04:05 +00:00
} ,
}
2018-04-03 00:46:59 +00:00
b := NewSystemBackend ( core , hclog . New ( & hclog . LoggerOptions { } ) )
2018-11-05 16:11:32 +00:00
err := b . Backend . Setup ( namespace . RootContext ( nil ) , bc )
2016-09-29 04:01:28 +00:00
if err != nil {
t . Fatal ( err )
}
2016-03-31 22:04:05 +00:00
exp := ts . expiration
2018-06-08 21:24:27 +00:00
te := & logical . TokenEntry {
2018-09-18 03:03:00 +00:00
ID : "foo" ,
Path : "auth/github/login/bar" ,
TTL : time . Hour ,
NamespaceID : namespace . RootNamespaceID ,
2017-05-04 02:03:42 +00:00
}
2018-06-03 22:14:51 +00:00
testMakeTokenDirectly ( t , ts , te )
2017-05-04 02:03:42 +00:00
2018-11-05 16:11:32 +00:00
te , err = ts . Lookup ( namespace . RootContext ( nil ) , "foo" )
2017-05-04 02:03:42 +00:00
if err != nil {
t . Fatal ( err )
}
if te == nil {
t . Fatal ( "token entry was nil" )
}
// Create a new token
auth := & logical . Auth {
ClientToken : te . ID ,
LeaseOptions : logical . LeaseOptions {
TTL : time . Hour ,
} ,
}
2018-11-05 16:11:32 +00:00
err = exp . RegisterAuth ( namespace . RootContext ( nil ) , te , auth )
2017-05-04 02:03:42 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
req := logical . TestRequest ( t , logical . UpdateOperation , "leases/revoke-prefix/auth/github/" )
2018-11-05 16:11:32 +00:00
resp , err := b . HandleRequest ( namespace . RootContext ( nil ) , req )
2017-05-04 02:03:42 +00:00
if err != nil {
t . Fatalf ( "err: %v %v" , err , resp )
}
if resp != nil {
t . Fatalf ( "bad: %#v" , resp )
}
2018-11-05 16:11:32 +00:00
te , err = ts . Lookup ( namespace . RootContext ( nil ) , te . ID )
2017-05-04 02:03:42 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
if te != nil {
t . Fatalf ( "bad: %v" , te )
}
}
func TestSystemBackend_revokePrefixAuth_origUrl ( t * testing . T ) {
2018-06-03 22:14:51 +00:00
core , _ , _ := TestCoreUnsealed ( t )
ts := core . tokenStore
2016-03-31 22:04:05 +00:00
bc := & logical . BackendConfig {
Logger : core . logger ,
System : logical . StaticSystemView {
DefaultLeaseTTLVal : time . Hour * 24 ,
2016-09-28 22:32:49 +00:00
MaxLeaseTTLVal : time . Hour * 24 * 32 ,
2016-03-31 22:04:05 +00:00
} ,
}
2018-04-03 00:46:59 +00:00
b := NewSystemBackend ( core , hclog . New ( & hclog . LoggerOptions { } ) )
2018-11-05 16:11:32 +00:00
err := b . Backend . Setup ( namespace . RootContext ( nil ) , bc )
2016-09-29 04:01:28 +00:00
if err != nil {
t . Fatal ( err )
}
2016-03-31 22:04:05 +00:00
exp := ts . expiration
2018-06-08 21:24:27 +00:00
te := & logical . TokenEntry {
2018-09-18 03:03:00 +00:00
ID : "foo" ,
Path : "auth/github/login/bar" ,
TTL : time . Hour ,
NamespaceID : namespace . RootNamespaceID ,
2016-03-31 22:04:05 +00:00
}
2018-06-03 22:14:51 +00:00
testMakeTokenDirectly ( t , ts , te )
2016-03-31 22:04:05 +00:00
2018-11-05 16:11:32 +00:00
te , err = ts . Lookup ( namespace . RootContext ( nil ) , "foo" )
2016-03-31 22:04:05 +00:00
if err != nil {
t . Fatal ( err )
}
if te == nil {
t . Fatal ( "token entry was nil" )
}
// Create a new token
auth := & logical . Auth {
ClientToken : te . ID ,
LeaseOptions : logical . LeaseOptions {
TTL : time . Hour ,
} ,
}
2018-11-05 16:11:32 +00:00
err = exp . RegisterAuth ( namespace . RootContext ( nil ) , te , auth )
2016-03-31 22:04:05 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
req := logical . TestRequest ( t , logical . UpdateOperation , "revoke-prefix/auth/github/" )
2018-11-05 16:11:32 +00:00
resp , err := b . HandleRequest ( namespace . RootContext ( nil ) , req )
2016-03-31 22:04:05 +00:00
if err != nil {
t . Fatalf ( "err: %v %v" , err , resp )
}
if resp != nil {
t . Fatalf ( "bad: %#v" , resp )
}
2018-11-05 16:11:32 +00:00
te , err = ts . Lookup ( namespace . RootContext ( nil ) , te . ID )
2016-03-31 22:04:05 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
if te != nil {
t . Fatalf ( "bad: %v" , te )
}
}
2015-03-20 19:48:19 +00:00
func TestSystemBackend_authTable ( t * testing . T ) {
b := testSystemBackend ( t )
req := logical . TestRequest ( t , logical . ReadOperation , "auth" )
2018-11-05 16:11:32 +00:00
resp , err := b . HandleRequest ( namespace . RootContext ( nil ) , req )
2015-03-20 19:48:19 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
exp := map [ string ] interface { } {
2016-06-20 19:55:21 +00:00
"token/" : map [ string ] interface { } {
2019-11-07 16:54:34 +00:00
"type" : "token" ,
2019-10-17 17:33:00 +00:00
"external_entropy_access" : false ,
2019-11-07 16:54:34 +00:00
"description" : "token based credentials" ,
"accessor" : resp . Data [ "token/" ] . ( map [ string ] interface { } ) [ "accessor" ] ,
"uuid" : resp . Data [ "token/" ] . ( map [ string ] interface { } ) [ "uuid" ] ,
2016-06-20 19:55:21 +00:00
"config" : map [ string ] interface { } {
2016-06-21 00:08:12 +00:00
"default_lease_ttl" : int64 ( 0 ) ,
"max_lease_ttl" : int64 ( 0 ) ,
2018-10-15 16:56:24 +00:00
"force_no_cache" : false ,
"token_type" : "default-service" ,
2016-06-20 19:55:21 +00:00
} ,
2017-11-13 16:22:22 +00:00
"local" : false ,
"seal_wrap" : false ,
2018-03-21 19:04:27 +00:00
"options" : map [ string ] string ( nil ) ,
2015-03-20 19:48:19 +00:00
} ,
}
2018-10-15 16:56:24 +00:00
if diff := deep . Equal ( resp . Data , exp ) ; diff != nil {
t . Fatal ( diff )
2015-03-20 19:48:19 +00:00
}
}
func TestSystemBackend_enableAuth ( t * testing . T ) {
2015-03-24 18:37:07 +00:00
c , b , _ := testCoreSystemBackend ( t )
2018-01-19 06:44:44 +00:00
c . credentialBackends [ "noop" ] = func ( context . Context , * logical . BackendConfig ) ( logical . Backend , error ) {
2018-11-07 01:21:24 +00:00
return & NoopBackend { BackendType : logical . TypeCredential } , nil
2015-03-20 19:48:19 +00:00
}
2016-01-07 15:30:47 +00:00
req := logical . TestRequest ( t , logical . UpdateOperation , "auth/foo" )
2015-03-20 19:48:19 +00:00
req . Data [ "type" ] = "noop"
2018-02-22 15:26:29 +00:00
req . Data [ "config" ] = map [ string ] interface { } {
"default_lease_ttl" : "35m" ,
"max_lease_ttl" : "45m" ,
}
2017-11-13 16:22:22 +00:00
req . Data [ "local" ] = true
req . Data [ "seal_wrap" ] = true
2015-03-20 19:48:19 +00:00
2018-11-05 16:11:32 +00:00
resp , err := b . HandleRequest ( namespace . RootContext ( nil ) , req )
2015-03-20 19:48:19 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
if resp != nil {
t . Fatalf ( "bad: %v" , resp )
}
2017-11-13 16:22:22 +00:00
req = logical . TestRequest ( t , logical . ReadOperation , "auth" )
2018-11-05 16:11:32 +00:00
resp , err = b . HandleRequest ( namespace . RootContext ( nil ) , req )
2017-11-13 16:22:22 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
if resp == nil {
t . Fatal ( "resp is nil" )
}
exp := map [ string ] interface { } {
"foo/" : map [ string ] interface { } {
2019-11-07 16:54:34 +00:00
"type" : "noop" ,
2019-10-17 17:33:00 +00:00
"external_entropy_access" : false ,
2019-11-07 16:54:34 +00:00
"description" : "" ,
"accessor" : resp . Data [ "foo/" ] . ( map [ string ] interface { } ) [ "accessor" ] ,
"uuid" : resp . Data [ "foo/" ] . ( map [ string ] interface { } ) [ "uuid" ] ,
2017-11-13 16:22:22 +00:00
"config" : map [ string ] interface { } {
2018-02-22 15:26:29 +00:00
"default_lease_ttl" : int64 ( 2100 ) ,
"max_lease_ttl" : int64 ( 2700 ) ,
2018-10-15 16:56:24 +00:00
"force_no_cache" : false ,
"token_type" : "default-service" ,
2017-11-13 16:22:22 +00:00
} ,
"local" : true ,
"seal_wrap" : true ,
2018-03-21 19:04:27 +00:00
"options" : map [ string ] string { } ,
2017-11-13 16:22:22 +00:00
} ,
"token/" : map [ string ] interface { } {
2019-11-07 16:54:34 +00:00
"type" : "token" ,
2019-10-17 17:33:00 +00:00
"external_entropy_access" : false ,
2019-11-07 16:54:34 +00:00
"description" : "token based credentials" ,
"accessor" : resp . Data [ "token/" ] . ( map [ string ] interface { } ) [ "accessor" ] ,
"uuid" : resp . Data [ "token/" ] . ( map [ string ] interface { } ) [ "uuid" ] ,
2017-11-13 16:22:22 +00:00
"config" : map [ string ] interface { } {
"default_lease_ttl" : int64 ( 0 ) ,
"max_lease_ttl" : int64 ( 0 ) ,
2018-10-15 16:56:24 +00:00
"force_no_cache" : false ,
"token_type" : "default-service" ,
2017-11-13 16:22:22 +00:00
} ,
"local" : false ,
"seal_wrap" : false ,
2018-03-21 19:04:27 +00:00
"options" : map [ string ] string ( nil ) ,
2017-11-13 16:22:22 +00:00
} ,
}
2018-10-15 16:56:24 +00:00
if diff := deep . Equal ( resp . Data , exp ) ; diff != nil {
t . Fatal ( diff )
2017-11-13 16:22:22 +00:00
}
2015-03-20 19:48:19 +00:00
}
func TestSystemBackend_enableAuth_invalid ( t * testing . T ) {
b := testSystemBackend ( t )
2016-01-07 15:30:47 +00:00
req := logical . TestRequest ( t , logical . UpdateOperation , "auth/foo" )
2015-03-20 19:48:19 +00:00
req . Data [ "type" ] = "nope"
2018-11-05 16:11:32 +00:00
resp , err := b . HandleRequest ( namespace . RootContext ( nil ) , req )
2015-03-20 19:48:19 +00:00
if err != logical . ErrInvalidRequest {
t . Fatalf ( "err: %v" , err )
}
2018-11-07 01:21:24 +00:00
if resp . Data [ "error" ] != ` plugin not found in the catalog: nope ` {
2015-03-20 19:48:19 +00:00
t . Fatalf ( "bad: %v" , resp )
}
}
func TestSystemBackend_disableAuth ( t * testing . T ) {
2015-03-24 18:37:07 +00:00
c , b , _ := testCoreSystemBackend ( t )
2018-01-19 06:44:44 +00:00
c . credentialBackends [ "noop" ] = func ( context . Context , * logical . BackendConfig ) ( logical . Backend , error ) {
2015-03-31 01:07:05 +00:00
return & NoopBackend { } , nil
2015-03-20 19:48:19 +00:00
}
// Register the backend
2016-01-07 15:30:47 +00:00
req := logical . TestRequest ( t , logical . UpdateOperation , "auth/foo" )
2015-03-20 19:48:19 +00:00
req . Data [ "type" ] = "noop"
2018-11-05 16:11:32 +00:00
b . HandleRequest ( namespace . RootContext ( nil ) , req )
2015-03-20 19:48:19 +00:00
// Deregister it
req = logical . TestRequest ( t , logical . DeleteOperation , "auth/foo" )
2018-11-05 16:11:32 +00:00
resp , err := b . HandleRequest ( namespace . RootContext ( nil ) , req )
2015-03-20 19:48:19 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
if resp != nil {
t . Fatalf ( "bad: %v" , resp )
}
}
2020-02-15 18:32:47 +00:00
func TestSystemBackend_tuneAuth ( t * testing . T ) {
c , b , _ := testCoreSystemBackend ( t )
c . credentialBackends [ "noop" ] = func ( context . Context , * logical . BackendConfig ) ( logical . Backend , error ) {
return & NoopBackend { BackendType : logical . TypeCredential } , nil
}
req := logical . TestRequest ( t , logical . ReadOperation , "auth/token/tune" )
resp , err := b . HandleRequest ( namespace . RootContext ( nil ) , req )
if err != nil {
t . Fatalf ( "err: %v" , err )
}
if resp == nil {
t . Fatal ( "resp is nil" )
}
exp := map [ string ] interface { } {
"description" : "token based credentials" ,
"default_lease_ttl" : int ( 2764800 ) ,
"max_lease_ttl" : int ( 2764800 ) ,
"force_no_cache" : false ,
"token_type" : "default-service" ,
}
if diff := deep . Equal ( resp . Data , exp ) ; diff != nil {
t . Fatal ( diff )
}
req = logical . TestRequest ( t , logical . UpdateOperation , "auth/token/tune" )
req . Data [ "description" ] = ""
resp , err = b . HandleRequest ( namespace . RootContext ( nil ) , req )
if err != nil {
t . Fatalf ( "err: %v" , err )
}
req = logical . TestRequest ( t , logical . ReadOperation , "auth/token/tune" )
resp , err = b . HandleRequest ( namespace . RootContext ( nil ) , req )
if err != nil {
t . Fatalf ( "err: %v" , err )
}
if resp == nil {
t . Fatal ( "resp is nil" )
}
if resp . Data [ "description" ] != "" {
t . Fatalf ( "got: %#v expect: %#v" , resp . Data [ "description" ] , "" )
}
}
2015-03-23 21:43:31 +00:00
func TestSystemBackend_policyList ( t * testing . T ) {
b := testSystemBackend ( t )
req := logical . TestRequest ( t , logical . ReadOperation , "policy" )
2018-11-05 16:11:32 +00:00
resp , err := b . HandleRequest ( namespace . RootContext ( nil ) , req )
2015-03-23 21:43:31 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
exp := map [ string ] interface { } {
2016-07-25 19:59:02 +00:00
"keys" : [ ] string { "default" , "root" } ,
"policies" : [ ] string { "default" , "root" } ,
2015-03-23 21:43:31 +00:00
}
if ! reflect . DeepEqual ( resp . Data , exp ) {
t . Fatalf ( "got: %#v expect: %#v" , resp . Data , exp )
}
}
func TestSystemBackend_policyCRUD ( t * testing . T ) {
b := testSystemBackend ( t )
// Create the policy
rules := ` path "foo/" { policy = "read" } `
2016-01-07 15:30:47 +00:00
req := logical . TestRequest ( t , logical . UpdateOperation , "policy/Foo" )
2015-03-23 21:43:31 +00:00
req . Data [ "rules" ] = rules
2018-11-05 16:11:32 +00:00
resp , err := b . HandleRequest ( namespace . RootContext ( nil ) , req )
2015-03-23 21:43:31 +00:00
if err != nil {
t . Fatalf ( "err: %v %#v" , err , resp )
}
2017-10-23 19:35:28 +00:00
if resp != nil && ( resp . IsError ( ) || len ( resp . Data ) > 0 ) {
2015-03-23 21:43:31 +00:00
t . Fatalf ( "bad: %#v" , resp )
}
// Read the policy
req = logical . TestRequest ( t , logical . ReadOperation , "policy/foo" )
2018-11-05 16:11:32 +00:00
resp , err = b . HandleRequest ( namespace . RootContext ( nil ) , req )
2015-03-23 21:43:31 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
exp := map [ string ] interface { } {
"name" : "foo" ,
"rules" : rules ,
}
if ! reflect . DeepEqual ( resp . Data , exp ) {
t . Fatalf ( "got: %#v expect: %#v" , resp . Data , exp )
}
2015-10-07 17:52:21 +00:00
// Read, and make sure that case has been normalized
req = logical . TestRequest ( t , logical . ReadOperation , "policy/Foo" )
2018-11-05 16:11:32 +00:00
resp , err = b . HandleRequest ( namespace . RootContext ( nil ) , req )
2017-07-04 17:58:28 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
2017-08-18 23:47:23 +00:00
exp = map [ string ] interface { } {
"name" : "foo" ,
"rules" : rules ,
}
if ! reflect . DeepEqual ( resp . Data , exp ) {
t . Fatalf ( "got: %#v expect: %#v" , resp . Data , exp )
2015-10-07 17:52:21 +00:00
}
2015-03-23 21:43:31 +00:00
// List the policies
req = logical . TestRequest ( t , logical . ReadOperation , "policy" )
2018-11-05 16:11:32 +00:00
resp , err = b . HandleRequest ( namespace . RootContext ( nil ) , req )
2015-03-23 21:43:31 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
exp = map [ string ] interface { } {
2016-07-25 19:59:02 +00:00
"keys" : [ ] string { "default" , "foo" , "root" } ,
"policies" : [ ] string { "default" , "foo" , "root" } ,
2015-03-23 21:43:31 +00:00
}
if ! reflect . DeepEqual ( resp . Data , exp ) {
t . Fatalf ( "got: %#v expect: %#v" , resp . Data , exp )
}
// Delete the policy
req = logical . TestRequest ( t , logical . DeleteOperation , "policy/foo" )
2018-11-05 16:11:32 +00:00
resp , err = b . HandleRequest ( namespace . RootContext ( nil ) , req )
2015-03-23 21:43:31 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
if resp != nil {
t . Fatalf ( "bad: %#v" , resp )
}
// Read the policy (deleted)
req = logical . TestRequest ( t , logical . ReadOperation , "policy/foo" )
2018-11-05 16:11:32 +00:00
resp , err = b . HandleRequest ( namespace . RootContext ( nil ) , req )
2015-03-23 21:43:31 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
if resp != nil {
t . Fatalf ( "bad: %#v" , resp )
}
// List the policies (deleted)
req = logical . TestRequest ( t , logical . ReadOperation , "policy" )
2018-11-05 16:11:32 +00:00
resp , err = b . HandleRequest ( namespace . RootContext ( nil ) , req )
2015-03-23 21:43:31 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
exp = map [ string ] interface { } {
2016-07-25 19:59:02 +00:00
"keys" : [ ] string { "default" , "root" } ,
"policies" : [ ] string { "default" , "root" } ,
2015-03-23 21:43:31 +00:00
}
if ! reflect . DeepEqual ( resp . Data , exp ) {
t . Fatalf ( "got: %#v expect: %#v" , resp . Data , exp )
}
}
2015-03-31 23:45:00 +00:00
func TestSystemBackend_enableAudit ( t * testing . T ) {
c , b , _ := testCoreSystemBackend ( t )
2018-01-19 06:44:44 +00:00
c . auditBackends [ "noop" ] = func ( ctx context . Context , config * audit . BackendConfig ) ( audit . Backend , error ) {
2015-09-18 21:36:42 +00:00
return & NoopAudit {
Config : config ,
} , nil
2015-03-31 23:45:00 +00:00
}
2016-01-07 15:30:47 +00:00
req := logical . TestRequest ( t , logical . UpdateOperation , "audit/foo" )
2015-03-31 23:45:00 +00:00
req . Data [ "type" ] = "noop"
2018-11-05 16:11:32 +00:00
resp , err := b . HandleRequest ( namespace . RootContext ( nil ) , req )
2015-03-31 23:45:00 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
if resp != nil {
t . Fatalf ( "bad: %v" , resp )
}
}
2015-11-19 01:26:03 +00:00
func TestSystemBackend_auditHash ( t * testing . T ) {
c , b , _ := testCoreSystemBackend ( t )
2018-01-19 06:44:44 +00:00
c . auditBackends [ "noop" ] = func ( ctx context . Context , config * audit . BackendConfig ) ( audit . Backend , error ) {
2015-11-19 01:26:03 +00:00
view := & logical . InmemStorage { }
2018-11-05 16:11:32 +00:00
view . Put ( namespace . RootContext ( nil ) , & logical . StorageEntry {
2015-11-19 01:26:03 +00:00
Key : "salt" ,
Value : [ ] byte ( "foo" ) ,
} )
2017-05-24 00:36:20 +00:00
config . SaltView = view
config . SaltConfig = & salt . Config {
2015-11-19 01:26:03 +00:00
HMAC : sha256 . New ,
HMACType : "hmac-sha256" ,
2017-05-24 00:36:20 +00:00
Location : salt . DefaultLocation ,
2015-11-19 01:26:03 +00:00
}
return & NoopAudit {
Config : config ,
} , nil
}
2016-01-07 15:30:47 +00:00
req := logical . TestRequest ( t , logical . UpdateOperation , "audit/foo" )
2015-11-19 01:26:03 +00:00
req . Data [ "type" ] = "noop"
2018-11-05 16:11:32 +00:00
resp , err := b . HandleRequest ( namespace . RootContext ( nil ) , req )
2015-11-19 01:26:03 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
if resp != nil {
t . Fatalf ( "bad: %v" , resp )
}
2016-01-07 15:30:47 +00:00
req = logical . TestRequest ( t , logical . UpdateOperation , "audit-hash/foo" )
2015-11-19 01:26:03 +00:00
req . Data [ "input" ] = "bar"
2018-11-05 16:11:32 +00:00
resp , err = b . HandleRequest ( namespace . RootContext ( nil ) , req )
2015-11-19 01:26:03 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
if resp == nil || resp . Data == nil {
t . Fatalf ( "response or its data was nil" )
}
hash , ok := resp . Data [ "hash" ]
if ! ok {
t . Fatalf ( "did not get hash back in response, response was %#v" , resp . Data )
}
if hash . ( string ) != "hmac-sha256:f9320baf0249169e73850cd6156ded0106e2bb6ad8cab01b7bbbebe6d1065317" {
t . Fatalf ( "bad hash back: %s" , hash . ( string ) )
}
}
2015-03-31 23:45:00 +00:00
func TestSystemBackend_enableAudit_invalid ( t * testing . T ) {
b := testSystemBackend ( t )
2016-01-07 15:30:47 +00:00
req := logical . TestRequest ( t , logical . UpdateOperation , "audit/foo" )
2015-03-31 23:45:00 +00:00
req . Data [ "type" ] = "nope"
2018-11-05 16:11:32 +00:00
resp , err := b . HandleRequest ( namespace . RootContext ( nil ) , req )
2015-03-31 23:45:00 +00:00
if err != logical . ErrInvalidRequest {
t . Fatalf ( "err: %v" , err )
}
2018-04-06 00:43:29 +00:00
if resp . Data [ "error" ] != ` unknown backend type: "nope" ` {
2015-03-31 23:45:00 +00:00
t . Fatalf ( "bad: %v" , resp )
}
}
func TestSystemBackend_auditTable ( t * testing . T ) {
c , b , _ := testCoreSystemBackend ( t )
2018-01-19 06:44:44 +00:00
c . auditBackends [ "noop" ] = func ( ctx context . Context , config * audit . BackendConfig ) ( audit . Backend , error ) {
2015-09-18 21:36:42 +00:00
return & NoopAudit {
Config : config ,
} , nil
2015-03-31 23:45:00 +00:00
}
2016-01-07 15:30:47 +00:00
req := logical . TestRequest ( t , logical . UpdateOperation , "audit/foo" )
2015-03-31 23:45:00 +00:00
req . Data [ "type" ] = "noop"
req . Data [ "description" ] = "testing"
req . Data [ "options" ] = map [ string ] interface { } {
"foo" : "bar" ,
}
2017-02-16 21:29:30 +00:00
req . Data [ "local" ] = true
2018-11-05 16:11:32 +00:00
b . HandleRequest ( namespace . RootContext ( nil ) , req )
2015-03-31 23:45:00 +00:00
req = logical . TestRequest ( t , logical . ReadOperation , "audit" )
2018-11-05 16:11:32 +00:00
resp , err := b . HandleRequest ( namespace . RootContext ( nil ) , req )
2015-03-31 23:45:00 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
exp := map [ string ] interface { } {
2015-04-03 21:27:33 +00:00
"foo/" : map [ string ] interface { } {
2016-03-14 22:40:12 +00:00
"path" : "foo/" ,
2015-03-31 23:45:00 +00:00
"type" : "noop" ,
"description" : "testing" ,
"options" : map [ string ] string {
"foo" : "bar" ,
} ,
2017-02-16 21:29:30 +00:00
"local" : true ,
2015-03-31 23:45:00 +00:00
} ,
}
if ! reflect . DeepEqual ( resp . Data , exp ) {
t . Fatalf ( "got: %#v expect: %#v" , resp . Data , exp )
}
}
func TestSystemBackend_disableAudit ( t * testing . T ) {
c , b , _ := testCoreSystemBackend ( t )
2018-01-19 06:44:44 +00:00
c . auditBackends [ "noop" ] = func ( ctx context . Context , config * audit . BackendConfig ) ( audit . Backend , error ) {
2015-09-18 21:36:42 +00:00
return & NoopAudit {
Config : config ,
} , nil
2015-03-31 23:45:00 +00:00
}
2016-01-07 15:30:47 +00:00
req := logical . TestRequest ( t , logical . UpdateOperation , "audit/foo" )
2015-03-31 23:45:00 +00:00
req . Data [ "type" ] = "noop"
req . Data [ "description" ] = "testing"
req . Data [ "options" ] = map [ string ] interface { } {
"foo" : "bar" ,
}
2018-11-05 16:11:32 +00:00
b . HandleRequest ( namespace . RootContext ( nil ) , req )
2015-03-31 23:45:00 +00:00
// Deregister it
req = logical . TestRequest ( t , logical . DeleteOperation , "audit/foo" )
2018-11-05 16:11:32 +00:00
resp , err := b . HandleRequest ( namespace . RootContext ( nil ) , req )
2015-03-31 23:45:00 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
if resp != nil {
t . Fatalf ( "bad: %v" , resp )
}
}
2018-02-09 23:43:48 +00:00
func TestSystemBackend_rawRead_Compressed ( t * testing . T ) {
b := testSystemBackendRaw ( t )
req := logical . TestRequest ( t , logical . ReadOperation , "raw/core/mounts" )
2018-11-05 16:11:32 +00:00
resp , err := b . HandleRequest ( namespace . RootContext ( nil ) , req )
2018-02-09 23:43:48 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
if ! strings . HasPrefix ( resp . Data [ "value" ] . ( string ) , "{\"type\":\"mounts\"" ) {
t . Fatalf ( "bad: %v" , resp )
}
}
2015-05-28 17:24:41 +00:00
func TestSystemBackend_rawRead_Protected ( t * testing . T ) {
2017-09-15 04:21:35 +00:00
b := testSystemBackendRaw ( t )
2015-05-28 17:24:41 +00:00
req := logical . TestRequest ( t , logical . ReadOperation , "raw/" + keyringPath )
2018-11-05 16:11:32 +00:00
_ , err := b . HandleRequest ( namespace . RootContext ( nil ) , req )
2015-05-28 17:24:41 +00:00
if err != logical . ErrInvalidRequest {
t . Fatalf ( "err: %v" , err )
}
}
func TestSystemBackend_rawWrite_Protected ( t * testing . T ) {
2017-09-15 04:21:35 +00:00
b := testSystemBackendRaw ( t )
2015-05-28 17:24:41 +00:00
2016-01-07 15:30:47 +00:00
req := logical . TestRequest ( t , logical . UpdateOperation , "raw/" + keyringPath )
2018-11-05 16:11:32 +00:00
_ , err := b . HandleRequest ( namespace . RootContext ( nil ) , req )
2015-05-28 17:24:41 +00:00
if err != logical . ErrInvalidRequest {
t . Fatalf ( "err: %v" , err )
}
}
2016-04-19 20:26:26 +00:00
func TestSystemBackend_rawReadWrite ( t * testing . T ) {
2017-10-23 19:35:28 +00:00
_ , b , _ := testCoreSystemBackendRaw ( t )
2015-04-02 00:44:43 +00:00
2016-01-07 15:30:47 +00:00
req := logical . TestRequest ( t , logical . UpdateOperation , "raw/sys/policy/test" )
2015-04-02 00:44:43 +00:00
req . Data [ "value" ] = ` path "secret/" { policy = "read" } `
2018-11-05 16:11:32 +00:00
resp , err := b . HandleRequest ( namespace . RootContext ( nil ) , req )
2015-04-02 00:44:43 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
if resp != nil {
t . Fatalf ( "bad: %v" , resp )
}
2016-04-19 20:26:26 +00:00
// Read via raw API
req = logical . TestRequest ( t , logical . ReadOperation , "raw/sys/policy/test" )
2018-11-05 16:11:32 +00:00
resp , err = b . HandleRequest ( namespace . RootContext ( nil ) , req )
2016-04-19 20:26:26 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
if ! strings . HasPrefix ( resp . Data [ "value" ] . ( string ) , "path" ) {
t . Fatalf ( "bad: %v" , resp )
}
2017-10-23 19:35:28 +00:00
// Note: since the upgrade code is gone that upgraded from 0.1, we can't
// simply parse this out directly via GetPolicy, so the test now ends here.
2015-04-02 00:44:43 +00:00
}
2015-05-28 17:24:41 +00:00
func TestSystemBackend_rawDelete_Protected ( t * testing . T ) {
2017-09-15 04:21:35 +00:00
b := testSystemBackendRaw ( t )
2015-05-28 17:24:41 +00:00
req := logical . TestRequest ( t , logical . DeleteOperation , "raw/" + keyringPath )
2018-11-05 16:11:32 +00:00
_ , err := b . HandleRequest ( namespace . RootContext ( nil ) , req )
2015-05-28 17:24:41 +00:00
if err != logical . ErrInvalidRequest {
t . Fatalf ( "err: %v" , err )
}
}
2015-04-02 00:44:43 +00:00
func TestSystemBackend_rawDelete ( t * testing . T ) {
2017-09-15 04:21:35 +00:00
c , b , _ := testCoreSystemBackendRaw ( t )
2015-04-02 00:44:43 +00:00
// set the policy!
2017-10-23 19:35:28 +00:00
p := & Policy {
2018-09-18 03:03:00 +00:00
Name : "test" ,
Type : PolicyTypeACL ,
namespace : namespace . RootNamespace ,
2017-10-23 19:35:28 +00:00
}
2018-11-05 16:11:32 +00:00
err := c . policyStore . SetPolicy ( namespace . RootContext ( nil ) , p )
2015-04-02 00:44:43 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
// Delete the policy
req := logical . TestRequest ( t , logical . DeleteOperation , "raw/sys/policy/test" )
2018-11-05 16:11:32 +00:00
resp , err := b . HandleRequest ( namespace . RootContext ( nil ) , req )
2015-04-02 00:44:43 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
if resp != nil {
t . Fatalf ( "bad: %v" , resp )
}
// Policy should be gone
2017-10-23 19:35:28 +00:00
c . policyStore . tokenPoliciesLRU . Purge ( )
2018-11-05 16:11:32 +00:00
out , err := c . policyStore . GetPolicy ( namespace . RootContext ( nil ) , "test" , PolicyTypeToken )
2015-04-02 00:44:43 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
if out != nil {
t . Fatalf ( "policy should be gone" )
}
}
2015-05-28 00:53:42 +00:00
func TestSystemBackend_keyStatus ( t * testing . T ) {
b := testSystemBackend ( t )
req := logical . TestRequest ( t , logical . ReadOperation , "key-status" )
2018-11-05 16:11:32 +00:00
resp , err := b . HandleRequest ( namespace . RootContext ( nil ) , req )
2015-05-28 00:53:42 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
exp := map [ string ] interface { } {
"term" : 1 ,
}
delete ( resp . Data , "install_time" )
2021-02-25 20:27:25 +00:00
delete ( resp . Data , "encryptions" )
if ! reflect . DeepEqual ( resp . Data , exp ) {
t . Fatalf ( "got: %#v expect: %#v" , resp . Data , exp )
}
}
func TestSystemBackend_rotateConfig ( t * testing . T ) {
b := testSystemBackend ( t )
req := logical . TestRequest ( t , logical . ReadOperation , "rotate/config" )
resp , err := b . HandleRequest ( namespace . RootContext ( nil ) , req )
if err != nil {
t . Fatalf ( "err: %v" , err )
}
exp := map [ string ] interface { } {
"max_operations" : absoluteOperationMaximum ,
"interval" : 0 ,
"enabled" : true ,
}
if ! reflect . DeepEqual ( resp . Data , exp ) {
t . Fatalf ( "got: %#v expect: %#v" , resp . Data , exp )
}
req2 := logical . TestRequest ( t , logical . UpdateOperation , "rotate/config" )
2021-05-05 19:39:04 +00:00
req2 . Data [ "max_operations" ] = int64 ( 3221225472 )
2021-02-25 20:27:25 +00:00
req2 . Data [ "interval" ] = "5432h0m0s"
req2 . Data [ "enabled" ] = false
resp , err = b . HandleRequest ( namespace . RootContext ( nil ) , req2 )
if err != nil {
t . Fatalf ( "err: %v" , err )
}
resp , err = b . HandleRequest ( namespace . RootContext ( nil ) , req )
if err != nil {
t . Fatalf ( "err: %v" , err )
}
exp = map [ string ] interface { } {
2021-05-05 19:39:04 +00:00
"max_operations" : int64 ( 3221225472 ) ,
2021-02-25 20:27:25 +00:00
"interval" : "5432h0m0s" ,
"enabled" : false ,
}
2015-05-28 00:53:42 +00:00
if ! reflect . DeepEqual ( resp . Data , exp ) {
t . Fatalf ( "got: %#v expect: %#v" , resp . Data , exp )
}
}
func TestSystemBackend_rotate ( t * testing . T ) {
b := testSystemBackend ( t )
2016-01-07 15:30:47 +00:00
req := logical . TestRequest ( t , logical . UpdateOperation , "rotate" )
2018-11-05 16:11:32 +00:00
resp , err := b . HandleRequest ( namespace . RootContext ( nil ) , req )
2015-05-28 00:53:42 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
if resp != nil {
t . Fatalf ( "bad: %v" , resp )
}
req = logical . TestRequest ( t , logical . ReadOperation , "key-status" )
2018-11-05 16:11:32 +00:00
resp , err = b . HandleRequest ( namespace . RootContext ( nil ) , req )
2015-05-28 00:53:42 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
exp := map [ string ] interface { } {
"term" : 2 ,
}
delete ( resp . Data , "install_time" )
2021-02-25 20:27:25 +00:00
delete ( resp . Data , "encryptions" )
2015-05-28 00:53:42 +00:00
if ! reflect . DeepEqual ( resp . Data , exp ) {
t . Fatalf ( "got: %#v expect: %#v" , resp . Data , exp )
}
}
2015-03-16 00:35:59 +00:00
func testSystemBackend ( t * testing . T ) logical . Backend {
2015-03-29 23:18:08 +00:00
c , _ , _ := TestCoreUnsealed ( t )
2018-03-01 16:14:56 +00:00
return c . systemBackend
2017-09-15 04:21:35 +00:00
}
2016-09-29 04:01:28 +00:00
2017-09-15 04:21:35 +00:00
func testSystemBackendRaw ( t * testing . T ) logical . Backend {
c , _ , _ := TestCoreUnsealedRaw ( t )
2018-03-01 16:14:56 +00:00
return c . systemBackend
2015-03-15 21:42:05 +00:00
}
2015-03-16 23:11:55 +00:00
2015-03-24 18:37:07 +00:00
func testCoreSystemBackend ( t * testing . T ) ( * Core , logical . Backend , string ) {
2015-03-29 23:18:08 +00:00
c , _ , root := TestCoreUnsealed ( t )
2018-03-01 16:14:56 +00:00
return c , c . systemBackend , root
2017-09-15 04:21:35 +00:00
}
func testCoreSystemBackendRaw ( t * testing . T ) ( * Core , logical . Backend , string ) {
c , _ , root := TestCoreUnsealedRaw ( t )
2018-03-01 16:14:56 +00:00
return c , c . systemBackend , root
2017-09-15 04:21:35 +00:00
}
2017-04-12 17:39:18 +00:00
func TestSystemBackend_PluginCatalog_CRUD ( t * testing . T ) {
c , b , _ := testCoreSystemBackend ( t )
// Bootstrap the pluginCatalog
sym , err := filepath . EvalSymlinks ( os . TempDir ( ) )
if err != nil {
t . Fatalf ( "error: %v" , err )
}
c . pluginCatalog . directory = sym
2018-11-07 01:21:24 +00:00
req := logical . TestRequest ( t , logical . ListOperation , "plugins/catalog/database" )
2018-11-05 16:11:32 +00:00
resp , err := b . HandleRequest ( namespace . RootContext ( nil ) , req )
2017-04-12 17:39:18 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
2018-11-07 01:21:24 +00:00
if len ( resp . Data [ "keys" ] . ( [ ] string ) ) != len ( c . builtinRegistry . Keys ( consts . PluginTypeDatabase ) ) {
t . Fatalf ( "Wrong number of plugins, got %d, expected %d" , len ( resp . Data [ "keys" ] . ( [ ] string ) ) , len ( builtinplugins . Registry . Keys ( consts . PluginTypeDatabase ) ) )
2017-04-12 17:39:18 +00:00
}
2018-11-07 01:21:24 +00:00
req = logical . TestRequest ( t , logical . ReadOperation , "plugins/catalog/database/mysql-database-plugin" )
2018-11-05 16:11:32 +00:00
resp , err = b . HandleRequest ( namespace . RootContext ( nil ) , req )
2017-04-12 17:39:18 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
2018-01-18 00:19:28 +00:00
actualRespData := resp . Data
expectedRespData := map [ string ] interface { } {
"name" : "mysql-database-plugin" ,
"command" : "" ,
"args" : [ ] string ( nil ) ,
"sha256" : "" ,
"builtin" : true ,
2017-04-12 17:39:18 +00:00
}
Backend plugin system (#2874)
* Add backend plugin changes
* Fix totp backend plugin tests
* Fix logical/plugin InvalidateKey test
* Fix plugin catalog CRUD test, fix NoopBackend
* Clean up commented code block
* Fix system backend mount test
* Set plugin_name to omitempty, fix handleMountTable config parsing
* Clean up comments, keep shim connections alive until cleanup
* Include pluginClient, disallow LookupPlugin call from within a plugin
* Add wrapper around backendPluginClient for proper cleanup
* Add logger shim tests
* Add logger, storage, and system shim tests
* Use pointer receivers for system view shim
* Use plugin name if no path is provided on mount
* Enable plugins for auth backends
* Add backend type attribute, move builtin/plugin/package
* Fix merge conflict
* Fix missing plugin name in mount config
* Add integration tests on enabling auth backend plugins
* Remove dependency cycle on mock-plugin
* Add passthrough backend plugin, use logical.BackendType to determine lease generation
* Remove vault package dependency on passthrough package
* Add basic impl test for passthrough plugin
* Incorporate feedback; set b.backend after shims creation on backendPluginServer
* Fix totp plugin test
* Add plugin backends docs
* Fix tests
* Fix builtin/plugin tests
* Remove flatten from PluginRunner fields
* Move mock plugin to logical/plugin, remove totp and passthrough plugins
* Move pluginMap into newPluginClient
* Do not create storage RPC connection on HandleRequest and HandleExistenceCheck
* Change shim logger's Fatal to no-op
* Change BackendType to uint32, match UX backend types
* Change framework.Backend Setup signature
* Add Setup func to logical.Backend interface
* Move OptionallyEnableMlock call into plugin.Serve, update docs and comments
* Remove commented var in plugin package
* RegisterLicense on logical.Backend interface (#3017)
* Add RegisterLicense to logical.Backend interface
* Update RegisterLicense to use callback func on framework.Backend
* Refactor framework.Backend.RegisterLicense
* plugin: Prevent plugin.SystemViewClient.ResponseWrapData from getting JWTs
* plugin: Revert BackendType to remove TypePassthrough and related references
* Fix typo in plugin backends docs
2017-07-20 17:28:40 +00:00
if ! reflect . DeepEqual ( actualRespData , expectedRespData ) {
t . Fatalf ( "expected did not match actual, got %#v\n expected %#v\n" , actualRespData , expectedRespData )
2017-04-12 17:39:18 +00:00
}
// Set a plugin
file , err := ioutil . TempFile ( os . TempDir ( ) , "temp" )
if err != nil {
t . Fatal ( err )
}
defer file . Close ( )
2018-01-18 00:19:28 +00:00
// Check we can only specify args in one of command or args.
2017-04-12 17:39:18 +00:00
command := fmt . Sprintf ( "%s --test" , filepath . Base ( file . Name ( ) ) )
2018-11-07 01:21:24 +00:00
req = logical . TestRequest ( t , logical . UpdateOperation , "plugins/catalog/database/test-plugin" )
2018-01-18 00:19:28 +00:00
req . Data [ "args" ] = [ ] string { "--foo" }
2017-04-12 17:39:18 +00:00
req . Data [ "sha_256" ] = hex . EncodeToString ( [ ] byte { '1' } )
req . Data [ "command" ] = command
2018-11-05 16:11:32 +00:00
resp , err = b . HandleRequest ( namespace . RootContext ( nil ) , req )
2017-04-12 17:39:18 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
2018-03-20 18:54:10 +00:00
if resp . Error ( ) . Error ( ) != "must not specify args in command and args field" {
2018-01-18 00:19:28 +00:00
t . Fatalf ( "err: %v" , resp . Error ( ) )
}
delete ( req . Data , "args" )
2018-11-05 16:11:32 +00:00
resp , err = b . HandleRequest ( namespace . RootContext ( nil ) , req )
2018-01-18 00:19:28 +00:00
if err != nil || resp . Error ( ) != nil {
t . Fatalf ( "err: %v %v" , err , resp . Error ( ) )
}
2017-04-12 17:39:18 +00:00
2018-11-07 01:21:24 +00:00
req = logical . TestRequest ( t , logical . ReadOperation , "plugins/catalog/database/test-plugin" )
2018-11-05 16:11:32 +00:00
resp , err = b . HandleRequest ( namespace . RootContext ( nil ) , req )
2017-04-12 17:39:18 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
2018-01-18 00:19:28 +00:00
actual := resp . Data
expected := map [ string ] interface { } {
"name" : "test-plugin" ,
"command" : filepath . Base ( file . Name ( ) ) ,
"args" : [ ] string { "--test" } ,
"sha256" : "31" ,
"builtin" : false ,
2017-04-12 17:39:18 +00:00
}
Backend plugin system (#2874)
* Add backend plugin changes
* Fix totp backend plugin tests
* Fix logical/plugin InvalidateKey test
* Fix plugin catalog CRUD test, fix NoopBackend
* Clean up commented code block
* Fix system backend mount test
* Set plugin_name to omitempty, fix handleMountTable config parsing
* Clean up comments, keep shim connections alive until cleanup
* Include pluginClient, disallow LookupPlugin call from within a plugin
* Add wrapper around backendPluginClient for proper cleanup
* Add logger shim tests
* Add logger, storage, and system shim tests
* Use pointer receivers for system view shim
* Use plugin name if no path is provided on mount
* Enable plugins for auth backends
* Add backend type attribute, move builtin/plugin/package
* Fix merge conflict
* Fix missing plugin name in mount config
* Add integration tests on enabling auth backend plugins
* Remove dependency cycle on mock-plugin
* Add passthrough backend plugin, use logical.BackendType to determine lease generation
* Remove vault package dependency on passthrough package
* Add basic impl test for passthrough plugin
* Incorporate feedback; set b.backend after shims creation on backendPluginServer
* Fix totp plugin test
* Add plugin backends docs
* Fix tests
* Fix builtin/plugin tests
* Remove flatten from PluginRunner fields
* Move mock plugin to logical/plugin, remove totp and passthrough plugins
* Move pluginMap into newPluginClient
* Do not create storage RPC connection on HandleRequest and HandleExistenceCheck
* Change shim logger's Fatal to no-op
* Change BackendType to uint32, match UX backend types
* Change framework.Backend Setup signature
* Add Setup func to logical.Backend interface
* Move OptionallyEnableMlock call into plugin.Serve, update docs and comments
* Remove commented var in plugin package
* RegisterLicense on logical.Backend interface (#3017)
* Add RegisterLicense to logical.Backend interface
* Update RegisterLicense to use callback func on framework.Backend
* Refactor framework.Backend.RegisterLicense
* plugin: Prevent plugin.SystemViewClient.ResponseWrapData from getting JWTs
* plugin: Revert BackendType to remove TypePassthrough and related references
* Fix typo in plugin backends docs
2017-07-20 17:28:40 +00:00
if ! reflect . DeepEqual ( actual , expected ) {
t . Fatalf ( "expected did not match actual, got %#v\n expected %#v\n" , actual , expected )
2017-04-12 17:39:18 +00:00
}
// Delete plugin
2018-11-07 01:21:24 +00:00
req = logical . TestRequest ( t , logical . DeleteOperation , "plugins/catalog/database/test-plugin" )
2018-11-05 16:11:32 +00:00
resp , err = b . HandleRequest ( namespace . RootContext ( nil ) , req )
2017-04-12 17:39:18 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
2018-11-07 01:21:24 +00:00
req = logical . TestRequest ( t , logical . ReadOperation , "plugins/catalog/database/test-plugin" )
2018-11-05 16:11:32 +00:00
resp , err = b . HandleRequest ( namespace . RootContext ( nil ) , req )
2017-04-25 04:24:19 +00:00
if resp != nil || err != nil {
t . Fatalf ( "expected nil response, plugin not deleted correctly got resp: %v, err: %v" , resp , err )
2017-04-12 17:39:18 +00:00
}
}
2017-10-20 14:59:17 +00:00
func TestSystemBackend_ToolsHash ( t * testing . T ) {
b := testSystemBackend ( t )
req := logical . TestRequest ( t , logical . UpdateOperation , "tools/hash" )
req . Data = map [ string ] interface { } {
"input" : "dGhlIHF1aWNrIGJyb3duIGZveA==" ,
}
2018-11-05 16:11:32 +00:00
_ , err := b . HandleRequest ( namespace . RootContext ( nil ) , req )
2017-10-20 14:59:17 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
doRequest := func ( req * logical . Request , errExpected bool , expected string ) {
t . Helper ( )
2018-11-05 16:11:32 +00:00
resp , err := b . HandleRequest ( namespace . RootContext ( nil ) , req )
2017-10-20 14:59:17 +00:00
if err != nil && ! errExpected {
t . Fatal ( err )
}
if resp == nil {
t . Fatal ( "expected non-nil response" )
}
if errExpected {
if ! resp . IsError ( ) {
t . Fatalf ( "bad: got error response: %#v" , * resp )
}
return
}
if resp . IsError ( ) {
t . Fatalf ( "bad: got error response: %#v" , * resp )
}
sum , ok := resp . Data [ "sum" ]
if ! ok {
t . Fatal ( "no sum key found in returned data" )
}
if sum . ( string ) != expected {
t . Fatal ( "mismatched hashes" )
}
}
// Test defaults -- sha2-256
doRequest ( req , false , "9ecb36561341d18eb65484e833efea61edc74b84cf5e6ae1b81c63533e25fc8f" )
// Test algorithm selection in the path
req . Path = "tools/hash/sha2-224"
doRequest ( req , false , "ea074a96cabc5a61f8298a2c470f019074642631a49e1c5e2f560865" )
// Reset and test algorithm selection in the data
req . Path = "tools/hash"
req . Data [ "algorithm" ] = "sha2-224"
doRequest ( req , false , "ea074a96cabc5a61f8298a2c470f019074642631a49e1c5e2f560865" )
req . Data [ "algorithm" ] = "sha2-384"
doRequest ( req , false , "15af9ec8be783f25c583626e9491dbf129dd6dd620466fdf05b3a1d0bb8381d30f4d3ec29f923ff1e09a0f6b337365a6" )
req . Data [ "algorithm" ] = "sha2-512"
doRequest ( req , false , "d9d380f29b97ad6a1d92e987d83fa5a02653301e1006dd2bcd51afa59a9147e9caedaf89521abc0f0b682adcd47fb512b8343c834a32f326fe9bef00542ce887" )
// Test returning as base64
req . Data [ "format" ] = "base64"
doRequest ( req , false , "2dOA8puXrWodkumH2D+loCZTMB4QBt0rzVGvpZqRR+nK7a+JUhq8DwtoKtzUf7USuDQ8g0oy8yb+m+8AVCzohw==" )
// Test bad input/format/algorithm
req . Data [ "format" ] = "base92"
doRequest ( req , true , "" )
req . Data [ "format" ] = "hex"
req . Data [ "algorithm" ] = "foobar"
doRequest ( req , true , "" )
req . Data [ "algorithm" ] = "sha2-256"
req . Data [ "input" ] = "foobar"
doRequest ( req , true , "" )
}
func TestSystemBackend_ToolsRandom ( t * testing . T ) {
b := testSystemBackend ( t )
req := logical . TestRequest ( t , logical . UpdateOperation , "tools/random" )
2018-11-05 16:11:32 +00:00
_ , err := b . HandleRequest ( namespace . RootContext ( nil ) , req )
2017-10-20 14:59:17 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
doRequest := func ( req * logical . Request , errExpected bool , format string , numBytes int ) {
t . Helper ( )
getResponse := func ( ) [ ] byte {
2018-11-05 16:11:32 +00:00
resp , err := b . HandleRequest ( namespace . RootContext ( nil ) , req )
2017-10-20 14:59:17 +00:00
if err != nil && ! errExpected {
t . Fatal ( err )
}
if resp == nil {
t . Fatal ( "expected non-nil response" )
}
if errExpected {
if ! resp . IsError ( ) {
t . Fatalf ( "bad: got error response: %#v" , * resp )
}
return nil
}
if resp . IsError ( ) {
t . Fatalf ( "bad: got error response: %#v" , * resp )
}
if _ , ok := resp . Data [ "random_bytes" ] ; ! ok {
t . Fatal ( "no random_bytes found in response" )
}
outputStr := resp . Data [ "random_bytes" ] . ( string )
var outputBytes [ ] byte
switch format {
case "base64" :
outputBytes , err = base64 . StdEncoding . DecodeString ( outputStr )
case "hex" :
outputBytes , err = hex . DecodeString ( outputStr )
default :
t . Fatal ( "unknown format" )
}
if err != nil {
t . Fatal ( err )
}
return outputBytes
}
rand1 := getResponse ( )
// Expected error
if rand1 == nil {
return
}
rand2 := getResponse ( )
if len ( rand1 ) != numBytes || len ( rand2 ) != numBytes {
2018-03-20 18:54:10 +00:00
t . Fatal ( "length of output random bytes not what is expected" )
2017-10-20 14:59:17 +00:00
}
if reflect . DeepEqual ( rand1 , rand2 ) {
t . Fatal ( "found identical ouputs" )
}
}
// Test defaults
doRequest ( req , false , "base64" , 32 )
// Test size selection in the path
req . Path = "tools/random/24"
req . Data [ "format" ] = "hex"
doRequest ( req , false , "hex" , 24 )
// Test bad input/format
req . Path = "tools/random"
req . Data [ "format" ] = "base92"
doRequest ( req , true , "" , 0 )
req . Data [ "format" ] = "hex"
req . Data [ "bytes" ] = - 1
doRequest ( req , true , "" , 0 )
2019-07-25 01:22:23 +00:00
req . Data [ "format" ] = "hex"
req . Data [ "bytes" ] = maxBytes + 1
doRequest ( req , true , "" , 0 )
2017-10-20 14:59:17 +00:00
}
2018-03-20 03:16:33 +00:00
func TestSystemBackend_InternalUIMounts ( t * testing . T ) {
2018-04-23 22:00:02 +00:00
_ , b , rootToken := testCoreSystemBackend ( t )
2018-03-20 03:16:33 +00:00
// Ensure no entries are in the endpoint as a starting point
req := logical . TestRequest ( t , logical . ReadOperation , "internal/ui/mounts" )
2018-11-05 16:11:32 +00:00
resp , err := b . HandleRequest ( namespace . RootContext ( nil ) , req )
2018-03-20 03:16:33 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
exp := map [ string ] interface { } {
"secret" : map [ string ] interface { } { } ,
"auth" : map [ string ] interface { } { } ,
}
if ! reflect . DeepEqual ( resp . Data , exp ) {
t . Fatalf ( "got: %#v expect: %#v" , resp . Data , exp )
}
2018-04-23 22:00:02 +00:00
req = logical . TestRequest ( t , logical . ReadOperation , "internal/ui/mounts" )
req . ClientToken = rootToken
2018-11-05 16:11:32 +00:00
resp , err = b . HandleRequest ( namespace . RootContext ( nil ) , req )
2018-04-23 22:00:02 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
exp = map [ string ] interface { } {
"secret" : map [ string ] interface { } {
"secret/" : map [ string ] interface { } {
2019-11-07 16:54:34 +00:00
"type" : "kv" ,
2019-10-17 17:33:00 +00:00
"external_entropy_access" : false ,
2019-11-07 16:54:34 +00:00
"description" : "key/value secret storage" ,
"accessor" : resp . Data [ "secret" ] . ( map [ string ] interface { } ) [ "secret/" ] . ( map [ string ] interface { } ) [ "accessor" ] ,
"uuid" : resp . Data [ "secret" ] . ( map [ string ] interface { } ) [ "secret/" ] . ( map [ string ] interface { } ) [ "uuid" ] ,
2018-04-23 22:00:02 +00:00
"config" : map [ string ] interface { } {
"default_lease_ttl" : resp . Data [ "secret" ] . ( map [ string ] interface { } ) [ "secret/" ] . ( map [ string ] interface { } ) [ "config" ] . ( map [ string ] interface { } ) [ "default_lease_ttl" ] . ( int64 ) ,
"max_lease_ttl" : resp . Data [ "secret" ] . ( map [ string ] interface { } ) [ "secret/" ] . ( map [ string ] interface { } ) [ "config" ] . ( map [ string ] interface { } ) [ "max_lease_ttl" ] . ( int64 ) ,
"force_no_cache" : false ,
} ,
"local" : false ,
"seal_wrap" : false ,
"options" : map [ string ] string {
"version" : "1" ,
} ,
} ,
"sys/" : map [ string ] interface { } {
2019-11-07 16:54:34 +00:00
"type" : "system" ,
2019-10-17 17:33:00 +00:00
"external_entropy_access" : false ,
2019-11-07 16:54:34 +00:00
"description" : "system endpoints used for control, policy and debugging" ,
"accessor" : resp . Data [ "secret" ] . ( map [ string ] interface { } ) [ "sys/" ] . ( map [ string ] interface { } ) [ "accessor" ] ,
"uuid" : resp . Data [ "secret" ] . ( map [ string ] interface { } ) [ "sys/" ] . ( map [ string ] interface { } ) [ "uuid" ] ,
2018-04-23 22:00:02 +00:00
"config" : map [ string ] interface { } {
2019-02-15 18:45:55 +00:00
"default_lease_ttl" : resp . Data [ "secret" ] . ( map [ string ] interface { } ) [ "sys/" ] . ( map [ string ] interface { } ) [ "config" ] . ( map [ string ] interface { } ) [ "default_lease_ttl" ] . ( int64 ) ,
"max_lease_ttl" : resp . Data [ "secret" ] . ( map [ string ] interface { } ) [ "sys/" ] . ( map [ string ] interface { } ) [ "config" ] . ( map [ string ] interface { } ) [ "max_lease_ttl" ] . ( int64 ) ,
"force_no_cache" : false ,
"passthrough_request_headers" : [ ] string { "Accept" } ,
2018-04-23 22:00:02 +00:00
} ,
"local" : false ,
"seal_wrap" : false ,
"options" : map [ string ] string ( nil ) ,
} ,
"cubbyhole/" : map [ string ] interface { } {
2019-11-07 16:54:34 +00:00
"description" : "per-token private secret storage" ,
"type" : "cubbyhole" ,
2019-10-17 17:33:00 +00:00
"external_entropy_access" : false ,
2019-11-07 16:54:34 +00:00
"accessor" : resp . Data [ "secret" ] . ( map [ string ] interface { } ) [ "cubbyhole/" ] . ( map [ string ] interface { } ) [ "accessor" ] ,
"uuid" : resp . Data [ "secret" ] . ( map [ string ] interface { } ) [ "cubbyhole/" ] . ( map [ string ] interface { } ) [ "uuid" ] ,
2018-04-23 22:00:02 +00:00
"config" : map [ string ] interface { } {
"default_lease_ttl" : resp . Data [ "secret" ] . ( map [ string ] interface { } ) [ "cubbyhole/" ] . ( map [ string ] interface { } ) [ "config" ] . ( map [ string ] interface { } ) [ "default_lease_ttl" ] . ( int64 ) ,
"max_lease_ttl" : resp . Data [ "secret" ] . ( map [ string ] interface { } ) [ "cubbyhole/" ] . ( map [ string ] interface { } ) [ "config" ] . ( map [ string ] interface { } ) [ "max_lease_ttl" ] . ( int64 ) ,
"force_no_cache" : false ,
} ,
"local" : true ,
"seal_wrap" : false ,
"options" : map [ string ] string ( nil ) ,
} ,
"identity/" : map [ string ] interface { } {
2019-11-07 16:54:34 +00:00
"description" : "identity store" ,
"type" : "identity" ,
2019-10-17 17:33:00 +00:00
"external_entropy_access" : false ,
2019-11-07 16:54:34 +00:00
"accessor" : resp . Data [ "secret" ] . ( map [ string ] interface { } ) [ "identity/" ] . ( map [ string ] interface { } ) [ "accessor" ] ,
"uuid" : resp . Data [ "secret" ] . ( map [ string ] interface { } ) [ "identity/" ] . ( map [ string ] interface { } ) [ "uuid" ] ,
2018-04-23 22:00:02 +00:00
"config" : map [ string ] interface { } {
"default_lease_ttl" : resp . Data [ "secret" ] . ( map [ string ] interface { } ) [ "identity/" ] . ( map [ string ] interface { } ) [ "config" ] . ( map [ string ] interface { } ) [ "default_lease_ttl" ] . ( int64 ) ,
"max_lease_ttl" : resp . Data [ "secret" ] . ( map [ string ] interface { } ) [ "identity/" ] . ( map [ string ] interface { } ) [ "config" ] . ( map [ string ] interface { } ) [ "max_lease_ttl" ] . ( int64 ) ,
"force_no_cache" : false ,
} ,
"local" : false ,
"seal_wrap" : false ,
"options" : map [ string ] string ( nil ) ,
} ,
} ,
"auth" : map [ string ] interface { } {
"token/" : map [ string ] interface { } {
"options" : map [ string ] string ( nil ) ,
"config" : map [ string ] interface { } {
"default_lease_ttl" : int64 ( 0 ) ,
"max_lease_ttl" : int64 ( 0 ) ,
"force_no_cache" : false ,
2018-10-15 16:56:24 +00:00
"token_type" : "default-service" ,
2018-04-23 22:00:02 +00:00
} ,
2019-11-07 16:54:34 +00:00
"type" : "token" ,
2019-10-17 17:33:00 +00:00
"external_entropy_access" : false ,
2019-11-07 16:54:34 +00:00
"description" : "token based credentials" ,
"accessor" : resp . Data [ "auth" ] . ( map [ string ] interface { } ) [ "token/" ] . ( map [ string ] interface { } ) [ "accessor" ] ,
"uuid" : resp . Data [ "auth" ] . ( map [ string ] interface { } ) [ "token/" ] . ( map [ string ] interface { } ) [ "uuid" ] ,
"local" : false ,
"seal_wrap" : false ,
2018-04-23 22:00:02 +00:00
} ,
} ,
}
2018-10-15 16:56:24 +00:00
if diff := deep . Equal ( resp . Data , exp ) ; diff != nil {
t . Fatal ( diff )
2018-04-23 22:00:02 +00:00
}
2018-03-20 03:16:33 +00:00
// Mount-tune an auth mount
req = logical . TestRequest ( t , logical . UpdateOperation , "auth/token/tune" )
req . Data [ "listing_visibility" ] = "unauth"
2018-11-05 16:11:32 +00:00
resp , err = b . HandleRequest ( namespace . RootContext ( nil ) , req )
2018-09-18 03:03:00 +00:00
if resp . IsError ( ) || err != nil {
t . Fatalf ( "resp.Error: %v, err:%v" , resp . Error ( ) , err )
}
2018-03-20 03:16:33 +00:00
// Mount-tune a secret mount
req = logical . TestRequest ( t , logical . UpdateOperation , "mounts/secret/tune" )
req . Data [ "listing_visibility" ] = "unauth"
2018-11-05 16:11:32 +00:00
resp , err = b . HandleRequest ( namespace . RootContext ( nil ) , req )
2018-09-18 03:03:00 +00:00
if resp . IsError ( ) || err != nil {
t . Fatalf ( "resp.Error: %v, err:%v" , resp . Error ( ) , err )
}
2018-03-20 03:16:33 +00:00
req = logical . TestRequest ( t , logical . ReadOperation , "internal/ui/mounts" )
2018-11-05 16:11:32 +00:00
resp , err = b . HandleRequest ( namespace . RootContext ( nil ) , req )
2018-03-20 03:16:33 +00:00
if err != nil {
t . Fatalf ( "err: %v" , err )
}
exp = map [ string ] interface { } {
"secret" : map [ string ] interface { } {
"secret/" : map [ string ] interface { } {
"type" : "kv" ,
"description" : "key/value secret storage" ,
2018-04-23 22:00:02 +00:00
"options" : map [ string ] string { "version" : "1" } ,
2018-03-20 03:16:33 +00:00
} ,
} ,
"auth" : map [ string ] interface { } {
"token/" : map [ string ] interface { } {
"type" : "token" ,
"description" : "token based credentials" ,
2018-04-23 22:00:02 +00:00
"options" : map [ string ] string ( nil ) ,
2018-03-20 03:16:33 +00:00
} ,
} ,
}
if ! reflect . DeepEqual ( resp . Data , exp ) {
t . Fatalf ( "got: %#v expect: %#v" , resp . Data , exp )
}
}
2018-04-23 22:00:02 +00:00
func TestSystemBackend_InternalUIMount ( t * testing . T ) {
core , b , rootToken := testCoreSystemBackend ( t )
req := logical . TestRequest ( t , logical . UpdateOperation , "policy/secret" )
req . ClientToken = rootToken
req . Data = map [ string ] interface { } {
"rules" : ` path "secret/foo/*" {
capabilities = [ "create" , "read" , "update" , "delete" , "list" ]
} ` ,
}
2018-11-05 16:11:32 +00:00
resp , err := b . HandleRequest ( namespace . RootContext ( nil ) , req )
2018-04-23 22:00:02 +00:00
if err != nil || ( resp != nil && resp . IsError ( ) ) {
t . Fatalf ( "Bad %#v %#v" , err , resp )
}
req = logical . TestRequest ( t , logical . UpdateOperation , "mounts/kv" )
req . ClientToken = rootToken
req . Data = map [ string ] interface { } {
"type" : "kv" ,
}
2018-11-05 16:11:32 +00:00
resp , err = b . HandleRequest ( namespace . RootContext ( nil ) , req )
2018-04-23 22:00:02 +00:00
if err != nil || ( resp != nil && resp . IsError ( ) ) {
t . Fatalf ( "Bad %#v %#v" , err , resp )
}
2018-04-23 22:16:10 +00:00
req = logical . TestRequest ( t , logical . ReadOperation , "internal/ui/mounts/kv/bar" )
2018-04-23 22:00:02 +00:00
req . ClientToken = rootToken
2018-11-05 16:11:32 +00:00
resp , err = b . HandleRequest ( namespace . RootContext ( nil ) , req )
2018-04-23 22:00:02 +00:00
if err != nil || ( resp != nil && resp . IsError ( ) ) {
t . Fatalf ( "Bad %#v %#v" , err , resp )
}
if resp . Data [ "type" ] != "kv" {
t . Fatalf ( "Bad Response: %#v" , resp )
}
2018-10-15 16:56:24 +00:00
testMakeServiceTokenViaBackend ( t , core . tokenStore , rootToken , "tokenid" , "" , [ ] string { "secret" } )
2018-04-23 22:00:02 +00:00
2018-04-23 22:16:10 +00:00
req = logical . TestRequest ( t , logical . ReadOperation , "internal/ui/mounts/kv" )
2018-04-23 22:00:02 +00:00
req . ClientToken = "tokenid"
2018-11-05 16:11:32 +00:00
resp , err = b . HandleRequest ( namespace . RootContext ( nil ) , req )
2018-04-23 22:00:02 +00:00
if err != logical . ErrPermissionDenied {
t . Fatal ( "expected permission denied error" )
}
2018-04-23 22:16:10 +00:00
req = logical . TestRequest ( t , logical . ReadOperation , "internal/ui/mounts/secret" )
2018-04-23 22:00:02 +00:00
req . ClientToken = "tokenid"
2018-11-05 16:11:32 +00:00
resp , err = b . HandleRequest ( namespace . RootContext ( nil ) , req )
2018-04-23 22:00:02 +00:00
if err != nil || ( resp != nil && resp . IsError ( ) ) {
t . Fatalf ( "Bad %#v %#v" , err , resp )
}
if resp . Data [ "type" ] != "kv" {
t . Fatalf ( "Bad Response: %#v" , resp )
}
2018-04-23 22:16:10 +00:00
req = logical . TestRequest ( t , logical . ReadOperation , "internal/ui/mounts/sys" )
2018-04-23 22:00:02 +00:00
req . ClientToken = "tokenid"
2018-11-05 16:11:32 +00:00
resp , err = b . HandleRequest ( namespace . RootContext ( nil ) , req )
2018-04-23 22:00:02 +00:00
if err != nil || ( resp != nil && resp . IsError ( ) ) {
t . Fatalf ( "Bad %#v %#v" , err , resp )
}
if resp . Data [ "type" ] != "system" {
t . Fatalf ( "Bad Response: %#v" , resp )
}
2018-04-23 22:16:10 +00:00
req = logical . TestRequest ( t , logical . ReadOperation , "internal/ui/mounts/non-existent" )
2018-04-23 22:00:02 +00:00
req . ClientToken = "tokenid"
2018-11-05 16:11:32 +00:00
resp , err = b . HandleRequest ( namespace . RootContext ( nil ) , req )
2018-04-23 22:00:02 +00:00
if err != logical . ErrPermissionDenied {
t . Fatal ( "expected permission denied error" )
}
}
2018-11-05 20:24:39 +00:00
func TestSystemBackend_OpenAPI ( t * testing . T ) {
_ , b , rootToken := testCoreSystemBackend ( t )
var oapi map [ string ] interface { }
// Ensure no paths are reported if there is no token
req := logical . TestRequest ( t , logical . ReadOperation , "internal/specs/openapi" )
resp , err := b . HandleRequest ( namespace . RootContext ( nil ) , req )
if err != nil {
t . Fatalf ( "err: %v" , err )
}
body := resp . Data [ "http_raw_body" ] . ( [ ] byte )
err = jsonutil . DecodeJSON ( body , & oapi )
if err != nil {
t . Fatalf ( "err: %v" , err )
}
exp := map [ string ] interface { } {
"openapi" : framework . OASVersion ,
"info" : map [ string ] interface { } {
"title" : "HashiCorp Vault API" ,
"description" : "HTTP API that gives you full access to Vault. All API routes are prefixed with `/v1/`." ,
"version" : version . GetVersion ( ) . Version ,
"license" : map [ string ] interface { } {
"name" : "Mozilla Public License 2.0" ,
"url" : "https://www.mozilla.org/en-US/MPL/2.0" ,
} ,
} ,
"paths" : map [ string ] interface { } { } ,
}
if diff := deep . Equal ( oapi , exp ) ; diff != nil {
t . Fatal ( diff )
}
// Check that default paths are present with a root token
req = logical . TestRequest ( t , logical . ReadOperation , "internal/specs/openapi" )
req . ClientToken = rootToken
resp , err = b . HandleRequest ( namespace . RootContext ( nil ) , req )
if err != nil {
t . Fatalf ( "err: %v" , err )
}
body = resp . Data [ "http_raw_body" ] . ( [ ] byte )
err = jsonutil . DecodeJSON ( body , & oapi )
if err != nil {
t . Fatalf ( "err: %v" , err )
}
doc , err := framework . NewOASDocumentFromMap ( oapi )
if err != nil {
t . Fatal ( err )
}
pathSamples := [ ] struct {
path string
tag string
} {
{ "/auth/token/lookup" , "auth" } ,
2018-11-06 18:09:06 +00:00
{ "/cubbyhole/{path}" , "secrets" } ,
2018-11-05 20:24:39 +00:00
{ "/identity/group/id" , "identity" } ,
2018-11-06 18:09:06 +00:00
{ "/secret/.*" , "secrets" } , // TODO update after kv repo update
2018-11-05 20:24:39 +00:00
{ "/sys/policy" , "system" } ,
}
for _ , path := range pathSamples {
if doc . Paths [ path . path ] == nil {
t . Fatalf ( "didn't find expected path '%s'." , path )
}
tag := doc . Paths [ path . path ] . Get . Tags [ 0 ]
if tag != path . tag {
t . Fatalf ( "path: %s; expected tag: %s, actual: %s" , path . path , tag , path . tag )
}
}
// Simple sanity check of response size (which is much larger than most
// Vault responses), mainly to catch mass omission of expected path data.
minLen := 70000
if len ( body ) < minLen {
t . Fatalf ( "response size too small; expected: min %d, actual: %d" , minLen , len ( body ) )
}
// Test path-help response
req = logical . TestRequest ( t , logical . HelpOperation , "rotate" )
req . ClientToken = rootToken
resp , err = b . HandleRequest ( namespace . RootContext ( nil ) , req )
if err != nil {
t . Fatalf ( "err: %v" , err )
}
doc = resp . Data [ "openapi" ] . ( * framework . OASDocument )
if len ( doc . Paths ) != 1 {
t . Fatalf ( "expected 1 path, actual: %d" , len ( doc . Paths ) )
}
if doc . Paths [ "/rotate" ] == nil {
t . Fatalf ( "expected to find path '/rotate'" )
}
}
2019-04-10 21:46:17 +00:00
func TestSystemBackend_PathWildcardPreflight ( t * testing . T ) {
core , b , _ := testCoreSystemBackend ( t )
ctx := namespace . RootContext ( nil )
// Add another mount
me := & MountEntry {
Table : mountTableType ,
2020-06-29 22:36:22 +00:00
Path : sanitizePath ( "kv-v1" ) ,
2019-04-10 21:46:17 +00:00
Type : "kv" ,
Options : map [ string ] string { "version" : "1" } ,
}
if err := core . mount ( ctx , me ) ; err != nil {
t . Fatal ( err )
}
// Create the policy, designed to fail
rules := ` path "foo" { capabilities = ["read"] } `
req := logical . TestRequest ( t , logical . UpdateOperation , "policy/foo" )
req . Data [ "rules" ] = rules
resp , err := b . HandleRequest ( ctx , req )
if err != nil {
t . Fatalf ( "err: %v %#v" , err , resp )
}
if resp != nil && ( resp . IsError ( ) || len ( resp . Data ) > 0 ) {
t . Fatalf ( "bad: %#v" , resp )
}
if err := core . identityStore . upsertEntity ( ctx , & identity . Entity {
2019-05-07 19:29:51 +00:00
ID : "abcd" ,
Name : "abcd" ,
BucketKey : "abcd" ,
2019-04-10 21:46:17 +00:00
} , nil , false ) ; err != nil {
t . Fatal ( err )
}
te := & logical . TokenEntry {
TTL : 300 * time . Second ,
EntityID : "abcd" ,
Policies : [ ] string { "default" , "foo" } ,
NamespaceID : namespace . RootNamespaceID ,
}
if err := core . tokenStore . create ( ctx , te ) ; err != nil {
t . Fatal ( err )
}
t . Logf ( "token id: %s" , te . ID )
if err := core . expiration . RegisterAuth ( ctx , te , & logical . Auth {
LeaseOptions : logical . LeaseOptions {
TTL : te . TTL ,
} ,
ClientToken : te . ID ,
Accessor : te . Accessor ,
Orphan : true ,
} ) ; err != nil {
t . Fatal ( err )
}
// Check the mount access func
req = logical . TestRequest ( t , logical . ReadOperation , "internal/ui/mounts/kv-v1/baz" )
req . ClientToken = te . ID
resp , err = b . HandleRequest ( ctx , req )
if err == nil || ! strings . Contains ( err . Error ( ) , "permission denied" ) {
t . Fatalf ( "expected 403, got err: %v" , err )
}
// Modify policy to pass
rules = ` path "kv-v1/+" { capabilities = ["read"] } `
req = logical . TestRequest ( t , logical . UpdateOperation , "policy/foo" )
req . Data [ "rules" ] = rules
resp , err = b . HandleRequest ( ctx , req )
if err != nil {
t . Fatalf ( "err: %v %#v" , err , resp )
}
if resp != nil && ( resp . IsError ( ) || len ( resp . Data ) > 0 ) {
t . Fatalf ( "bad: %#v" , resp )
}
// Check the mount access func again
req = logical . TestRequest ( t , logical . ReadOperation , "internal/ui/mounts/kv-v1/baz" )
req . ClientToken = te . ID
resp , err = b . HandleRequest ( ctx , req )
if err != nil {
t . Fatalf ( "err: %v" , err )
}
}
2020-05-27 18:28:00 +00:00
func TestHandlePoliciesPasswordSet ( t * testing . T ) {
type testCase struct {
inputData * framework . FieldData
storage * logical . InmemStorage
expectedResp * logical . Response
expectErr bool
expectedStore map [ string ] * logical . StorageEntry
}
tests := map [ string ] testCase {
"missing policy name" : {
inputData : passwordPoliciesFieldData ( map [ string ] interface { } {
"policy" : ` length = 20
rule "charset" {
charset = "abcdefghij"
} ` ,
} ) ,
storage : new ( logical . InmemStorage ) ,
expectedResp : nil ,
expectErr : true ,
expectedStore : map [ string ] * logical . StorageEntry { } ,
} ,
"missing policy" : {
inputData : passwordPoliciesFieldData ( map [ string ] interface { } {
"name" : "testpolicy" ,
} ) ,
storage : new ( logical . InmemStorage ) ,
expectedResp : nil ,
expectErr : true ,
expectedStore : map [ string ] * logical . StorageEntry { } ,
} ,
"garbage policy" : {
inputData : passwordPoliciesFieldData ( map [ string ] interface { } {
"name" : "testpolicy" ,
"policy" : "hasdukfhiuashdfoiasjdf" ,
} ) ,
storage : new ( logical . InmemStorage ) ,
expectedResp : nil ,
expectErr : true ,
expectedStore : map [ string ] * logical . StorageEntry { } ,
} ,
"storage failure" : {
inputData : passwordPoliciesFieldData ( map [ string ] interface { } {
"name" : "testpolicy" ,
"policy" : "length = 20\n" +
"rule \"charset\" {\n" +
" charset=\"abcdefghij\"\n" +
"}" ,
} ) ,
storage : new ( logical . InmemStorage ) . FailPut ( true ) ,
expectedResp : nil ,
expectErr : true ,
expectedStore : map [ string ] * logical . StorageEntry { } ,
} ,
"impossible policy" : {
inputData : passwordPoliciesFieldData ( map [ string ] interface { } {
"name" : "testpolicy" ,
"policy" : "length = 20\n" +
"rule \"charset\" {\n" +
" charset=\"a\"\n" +
" min-chars = 30\n" +
"}" ,
} ) ,
storage : new ( logical . InmemStorage ) ,
expectedResp : nil ,
expectErr : true ,
expectedStore : map [ string ] * logical . StorageEntry { } ,
} ,
"not base64 encoded" : {
inputData : passwordPoliciesFieldData ( map [ string ] interface { } {
"name" : "testpolicy" ,
"policy" : "length = 20\n" +
"rule \"charset\" {\n" +
" charset=\"abcdefghij\"\n" +
"}" ,
} ) ,
storage : new ( logical . InmemStorage ) ,
expectedResp : & logical . Response {
Data : map [ string ] interface { } {
logical . HTTPContentType : "application/json" ,
logical . HTTPStatusCode : http . StatusNoContent ,
} ,
} ,
expectErr : false ,
expectedStore : makeStorageMap ( storageEntry ( t , "testpolicy" , "length = 20\n" +
"rule \"charset\" {\n" +
" charset=\"abcdefghij\"\n" +
"}" ) ) ,
} ,
"base64 encoded" : {
inputData : passwordPoliciesFieldData ( map [ string ] interface { } {
"name" : "testpolicy" ,
"policy" : base64Encode (
"length = 20\n" +
"rule \"charset\" {\n" +
" charset=\"abcdefghij\"\n" +
"}" ) ,
} ) ,
storage : new ( logical . InmemStorage ) ,
expectedResp : & logical . Response {
Data : map [ string ] interface { } {
logical . HTTPContentType : "application/json" ,
logical . HTTPStatusCode : http . StatusNoContent ,
} ,
} ,
expectErr : false ,
expectedStore : makeStorageMap ( storageEntry ( t , "testpolicy" ,
"length = 20\n" +
"rule \"charset\" {\n" +
" charset=\"abcdefghij\"\n" +
"}" ) ) ,
} ,
}
for name , test := range tests {
t . Run ( name , func ( t * testing . T ) {
ctx , cancel := context . WithTimeout ( context . Background ( ) , 100 * time . Millisecond )
defer cancel ( )
req := & logical . Request {
Storage : test . storage ,
}
b := & SystemBackend { }
actualResp , err := b . handlePoliciesPasswordSet ( ctx , req , test . inputData )
if test . expectErr && err == nil {
t . Fatalf ( "err expected, got nil" )
}
if ! test . expectErr && err != nil {
t . Fatalf ( "no error expected, got: %s" , err )
}
if ! reflect . DeepEqual ( actualResp , test . expectedResp ) {
t . Fatalf ( "Actual response: %#v\nExpected response: %#v" , actualResp , test . expectedResp )
}
actualStore := LogicalToMap ( t , ctx , test . storage )
if ! reflect . DeepEqual ( actualStore , test . expectedStore ) {
t . Fatalf ( "Actual: %#v\nActual: %#v" , dereferenceMap ( actualStore ) , dereferenceMap ( test . expectedStore ) )
}
} )
}
}
func TestHandlePoliciesPasswordGet ( t * testing . T ) {
type testCase struct {
inputData * framework . FieldData
storage * logical . InmemStorage
expectedResp * logical . Response
expectErr bool
expectedStore map [ string ] * logical . StorageEntry
}
tests := map [ string ] testCase {
"missing policy name" : {
inputData : passwordPoliciesFieldData ( map [ string ] interface { } { } ) ,
storage : new ( logical . InmemStorage ) ,
expectedResp : nil ,
expectErr : true ,
expectedStore : map [ string ] * logical . StorageEntry { } ,
} ,
"storage error" : {
inputData : passwordPoliciesFieldData ( map [ string ] interface { } {
"name" : "testpolicy" ,
} ) ,
storage : new ( logical . InmemStorage ) . FailGet ( true ) ,
expectedResp : nil ,
expectErr : true ,
expectedStore : map [ string ] * logical . StorageEntry { } ,
} ,
"missing value" : {
inputData : passwordPoliciesFieldData ( map [ string ] interface { } {
"name" : "testpolicy" ,
} ) ,
storage : new ( logical . InmemStorage ) ,
expectedResp : nil ,
expectErr : true ,
expectedStore : map [ string ] * logical . StorageEntry { } ,
} ,
"good value" : {
inputData : passwordPoliciesFieldData ( map [ string ] interface { } {
"name" : "testpolicy" ,
} ) ,
storage : makeStorage ( t , storageEntry ( t , "testpolicy" ,
"length = 20\n" +
"rule \"charset\" {\n" +
" charset=\"abcdefghij\"\n" +
"}" ) ) ,
expectedResp : & logical . Response {
Data : map [ string ] interface { } {
"policy" : "length = 20\n" +
"rule \"charset\" {\n" +
" charset=\"abcdefghij\"\n" +
"}" ,
} ,
} ,
expectErr : false ,
expectedStore : makeStorageMap ( storageEntry ( t , "testpolicy" ,
"length = 20\n" +
"rule \"charset\" {\n" +
" charset=\"abcdefghij\"\n" +
"}" ) ) ,
} ,
}
for name , test := range tests {
t . Run ( name , func ( t * testing . T ) {
ctx , cancel := context . WithTimeout ( context . Background ( ) , 10 * time . Millisecond )
defer cancel ( )
req := & logical . Request {
Storage : test . storage ,
}
b := & SystemBackend { }
actualResp , err := b . handlePoliciesPasswordGet ( ctx , req , test . inputData )
if test . expectErr && err == nil {
t . Fatalf ( "err expected, got nil" )
}
if ! test . expectErr && err != nil {
t . Fatalf ( "no error expected, got: %s" , err )
}
if ! reflect . DeepEqual ( actualResp , test . expectedResp ) {
t . Fatalf ( "Actual response: %#v\nExpected response: %#v" , actualResp , test . expectedResp )
}
actualStore := LogicalToMap ( t , ctx , test . storage )
if ! reflect . DeepEqual ( actualStore , test . expectedStore ) {
t . Fatalf ( "Actual: %#v\nActual: %#v" , dereferenceMap ( actualStore ) , dereferenceMap ( test . expectedStore ) )
}
} )
}
}
func TestHandlePoliciesPasswordDelete ( t * testing . T ) {
type testCase struct {
inputData * framework . FieldData
storage logical . Storage
expectedResp * logical . Response
expectErr bool
expectedStore map [ string ] * logical . StorageEntry
}
tests := map [ string ] testCase {
"missing policy name" : {
inputData : passwordPoliciesFieldData ( map [ string ] interface { } { } ) ,
storage : new ( logical . InmemStorage ) ,
expectedResp : nil ,
expectErr : true ,
expectedStore : map [ string ] * logical . StorageEntry { } ,
} ,
"storage failure" : {
inputData : passwordPoliciesFieldData ( map [ string ] interface { } {
"name" : "testpolicy" ,
} ) ,
storage : new ( logical . InmemStorage ) . FailDelete ( true ) ,
expectedResp : nil ,
expectErr : true ,
expectedStore : map [ string ] * logical . StorageEntry { } ,
} ,
"successful delete" : {
inputData : passwordPoliciesFieldData ( map [ string ] interface { } {
"name" : "testpolicy" ,
} ) ,
storage : makeStorage ( t ,
& logical . StorageEntry {
Key : getPasswordPolicyKey ( "testpolicy" ) ,
Value : toJson ( t ,
passwordPolicyConfig {
HCLPolicy : "length = 18\n" +
"rule \"charset\" {\n" +
" charset=\"ABCDEFGHIJ\"\n" +
"}" ,
} ) ,
} ,
& logical . StorageEntry {
Key : getPasswordPolicyKey ( "unrelated_policy" ) ,
Value : toJson ( t ,
passwordPolicyConfig {
HCLPolicy : "length = 20\n" +
"rule \"charset\" {\n" +
" charset=\"abcdefghij\"\n" +
"}" ,
} ) ,
} ,
) ,
expectedResp : nil ,
expectErr : false ,
expectedStore : makeStorageMap ( storageEntry ( t , "unrelated_policy" ,
"length = 20\n" +
"rule \"charset\" {\n" +
" charset=\"abcdefghij\"\n" +
"}" ) ) ,
} ,
}
for name , test := range tests {
t . Run ( name , func ( t * testing . T ) {
ctx , cancel := context . WithTimeout ( context . Background ( ) , 10 * time . Millisecond )
defer cancel ( )
req := & logical . Request {
Storage : test . storage ,
}
b := & SystemBackend { }
actualResp , err := b . handlePoliciesPasswordDelete ( ctx , req , test . inputData )
if test . expectErr && err == nil {
t . Fatalf ( "err expected, got nil" )
}
if ! test . expectErr && err != nil {
t . Fatalf ( "no error expected, got: %s" , err )
}
if ! reflect . DeepEqual ( actualResp , test . expectedResp ) {
t . Fatalf ( "Actual response: %#v\nExpected response: %#v" , actualResp , test . expectedResp )
}
actualStore := LogicalToMap ( t , ctx , test . storage )
if ! reflect . DeepEqual ( actualStore , test . expectedStore ) {
t . Fatalf ( "Actual: %#v\nExpected: %#v" , dereferenceMap ( actualStore ) , dereferenceMap ( test . expectedStore ) )
}
} )
}
}
func TestHandlePoliciesPasswordGenerate ( t * testing . T ) {
t . Run ( "errors" , func ( t * testing . T ) {
type testCase struct {
timeout time . Duration
inputData * framework . FieldData
storage * logical . InmemStorage
expectedResp * logical . Response
expectErr bool
}
tests := map [ string ] testCase {
"missing policy name" : {
inputData : passwordPoliciesFieldData ( map [ string ] interface { } { } ) ,
storage : new ( logical . InmemStorage ) ,
expectedResp : nil ,
expectErr : true ,
} ,
"storage failure" : {
inputData : passwordPoliciesFieldData ( map [ string ] interface { } {
"name" : "testpolicy" ,
} ) ,
storage : new ( logical . InmemStorage ) . FailGet ( true ) ,
expectedResp : nil ,
expectErr : true ,
} ,
"policy does not exist" : {
inputData : passwordPoliciesFieldData ( map [ string ] interface { } {
"name" : "testpolicy" ,
} ) ,
storage : new ( logical . InmemStorage ) ,
expectedResp : nil ,
expectErr : true ,
} ,
"policy improperly saved" : {
inputData : passwordPoliciesFieldData ( map [ string ] interface { } {
"name" : "testpolicy" ,
} ) ,
storage : makeStorage ( t , storageEntry ( t , "testpolicy" , "badpolicy" ) ) ,
expectedResp : nil ,
expectErr : true ,
} ,
"failed to generate" : {
timeout : 0 * time . Second , // Timeout immediately
inputData : passwordPoliciesFieldData ( map [ string ] interface { } {
"name" : "testpolicy" ,
} ) ,
storage : makeStorage ( t , storageEntry ( t , "testpolicy" ,
"length = 20\n" +
"rule \"charset\" {\n" +
" charset=\"abcdefghij\"\n" +
"}" ) ) ,
expectedResp : nil ,
expectErr : true ,
} ,
}
for name , test := range tests {
t . Run ( name , func ( t * testing . T ) {
ctx , cancel := context . WithTimeout ( context . Background ( ) , test . timeout )
defer cancel ( )
req := & logical . Request {
Storage : test . storage ,
}
b := & SystemBackend { }
actualResp , err := b . handlePoliciesPasswordGenerate ( ctx , req , test . inputData )
if test . expectErr && err == nil {
t . Fatalf ( "err expected, got nil" )
}
if ! test . expectErr && err != nil {
t . Fatalf ( "no error expected, got: %s" , err )
}
if ! reflect . DeepEqual ( actualResp , test . expectedResp ) {
t . Fatalf ( "Actual response: %#v\nExpected response: %#v" , actualResp , test . expectedResp )
}
} )
}
} )
t . Run ( "success" , func ( t * testing . T ) {
2020-06-11 22:08:20 +00:00
ctx , cancel := context . WithTimeout ( context . Background ( ) , 5 * time . Second )
2020-05-27 18:28:00 +00:00
defer cancel ( )
policyEntry := storageEntry ( t , "testpolicy" ,
"length = 20\n" +
"rule \"charset\" {\n" +
" charset=\"abcdefghij\"\n" +
"}" )
storage := makeStorage ( t , policyEntry )
inputData := passwordPoliciesFieldData ( map [ string ] interface { } {
"name" : "testpolicy" ,
} )
expectedResp := & logical . Response {
Data : map [ string ] interface { } {
// Doesn't include the password as that's pulled out and compared separately
} ,
}
// Password assertions
expectedPassLen := 20
rules := [ ] random . Rule {
random . CharsetRule {
Charset : [ ] rune ( "abcdefghij" ) ,
MinChars : expectedPassLen ,
} ,
}
// Run the test a bunch of times to help ensure we don't have flaky behavior
for i := 0 ; i < 1000 ; i ++ {
req := & logical . Request {
Storage : storage ,
}
b := & SystemBackend { }
actualResp , err := b . handlePoliciesPasswordGenerate ( ctx , req , inputData )
if err != nil {
t . Fatalf ( "no error expected, got: %s" , err )
}
assert ( t , actualResp != nil , "response is nil" )
assert ( t , actualResp . Data != nil , "expected data, got nil" )
assertHasKey ( t , actualResp . Data , "password" , "password key not found in data" )
assertIsString ( t , actualResp . Data [ "password" ] , "password key should have a string value" )
password := actualResp . Data [ "password" ] . ( string )
// Delete the password so the rest of the response can be compared
delete ( actualResp . Data , "password" )
assert ( t , reflect . DeepEqual ( actualResp , expectedResp ) , "Actual response: %#v\nExpected response: %#v" , actualResp , expectedResp )
// Check to make sure the password is correctly formatted
passwordLength := len ( [ ] rune ( password ) )
if passwordLength != expectedPassLen {
t . Fatalf ( "password is %d characters but should be %d" , passwordLength , expectedPassLen )
}
for _ , rule := range rules {
if ! rule . Pass ( [ ] rune ( password ) ) {
t . Fatalf ( "password %s does not have the correct characters" , password )
}
}
}
} )
}
func assert ( t * testing . T , pass bool , f string , vals ... interface { } ) {
t . Helper ( )
if ! pass {
t . Fatalf ( f , vals ... )
}
}
func assertHasKey ( t * testing . T , m map [ string ] interface { } , key string , f string , vals ... interface { } ) {
t . Helper ( )
_ , exists := m [ key ]
if ! exists {
t . Fatalf ( f , vals ... )
}
}
func assertIsString ( t * testing . T , val interface { } , f string , vals ... interface { } ) {
t . Helper ( )
_ , ok := val . ( string )
if ! ok {
t . Fatalf ( f , vals ... )
}
}
func passwordPoliciesFieldData ( raw map [ string ] interface { } ) * framework . FieldData {
return & framework . FieldData {
Raw : raw ,
Schema : map [ string ] * framework . FieldSchema {
2021-04-08 16:43:39 +00:00
"name" : {
2020-05-27 18:28:00 +00:00
Type : framework . TypeString ,
Description : "The name of the password policy." ,
} ,
2021-04-08 16:43:39 +00:00
"policy" : {
2020-05-27 18:28:00 +00:00
Type : framework . TypeString ,
Description : "The password policy" ,
} ,
} ,
}
}
func base64Encode ( data string ) string {
return base64 . StdEncoding . EncodeToString ( [ ] byte ( data ) )
}
func toJson ( t * testing . T , val interface { } ) [ ] byte {
t . Helper ( )
b , err := jsonutil . EncodeJSON ( val )
if err != nil {
t . Fatalf ( "Unable to marshal to JSON: %s" , err )
}
return b
}
func storageEntry ( t * testing . T , key string , policy string ) * logical . StorageEntry {
return & logical . StorageEntry {
Key : getPasswordPolicyKey ( key ) ,
Value : toJson ( t , passwordPolicyConfig {
HCLPolicy : policy ,
} ) ,
}
}
func makeStorageMap ( entries ... * logical . StorageEntry ) map [ string ] * logical . StorageEntry {
m := map [ string ] * logical . StorageEntry { }
for _ , entry := range entries {
m [ entry . Key ] = entry
}
return m
}
func dereferenceMap ( store map [ string ] * logical . StorageEntry ) map [ string ] interface { } {
m := map [ string ] interface { } { }
for k , v := range store {
m [ k ] = map [ string ] string {
"Key" : v . Key ,
"Value" : string ( v . Value ) ,
}
}
return m
}
type walkFunc func ( * logical . StorageEntry ) error
// WalkLogicalStorage applies the provided walkFunc against each entry in the logical storage.
// This operates as a breadth first search.
// TODO: Figure out a place for this to live permanently. This is generic and should be in a helper package somewhere.
// At the time of writing, none of these locations work due to import cycles:
// - vault/helper/testhelpers
// - vault/helper/testhelpers/logical
// - vault/helper/testhelpers/teststorage
func WalkLogicalStorage ( ctx context . Context , store logical . Storage , walker walkFunc ) ( err error ) {
if store == nil {
return fmt . Errorf ( "no storage provided" )
}
if walker == nil {
return fmt . Errorf ( "no walk function provided" )
}
keys , err := store . List ( ctx , "" )
if err != nil {
return fmt . Errorf ( "unable to list root keys: %w" , err )
}
// Non-recursive breadth-first search through all keys
for i := 0 ; i < len ( keys ) ; i ++ {
key := keys [ i ]
entry , err := store . Get ( ctx , key )
if err != nil {
return fmt . Errorf ( "unable to retrieve key at [%s]: %w" , key , err )
}
if entry != nil {
err = walker ( entry )
if err != nil {
return err
}
}
if strings . HasSuffix ( key , "/" ) {
// Directory
subkeys , err := store . List ( ctx , key )
if err != nil {
return fmt . Errorf ( "unable to list keys at [%s]: %w" , key , err )
}
// Append the sub-keys to the keys slice so it searches into the sub-directory
for _ , subkey := range subkeys {
// Avoids infinite loop if the subkey is empty which then repeats indefinitely
if subkey == "" {
continue
}
subkey = fmt . Sprintf ( "%s%s" , key , subkey )
keys = append ( keys , subkey )
}
}
}
return nil
}
// LogicalToMap retrieves all entries in the store and returns them as a map of key -> StorageEntry
func LogicalToMap ( t * testing . T , ctx context . Context , store logical . Storage ) ( data map [ string ] * logical . StorageEntry ) {
data = map [ string ] * logical . StorageEntry { }
f := func ( entry * logical . StorageEntry ) error {
data [ entry . Key ] = entry
return nil
}
err := WalkLogicalStorage ( ctx , store , f )
if err != nil {
t . Fatalf ( "Unable to walk the storage: %s" , err )
}
return data
}
// Ensure the WalkLogicalStorage function works
func TestWalkLogicalStorage ( t * testing . T ) {
type testCase struct {
entries [ ] * logical . StorageEntry
}
tests := map [ string ] testCase {
"no entries" : {
entries : [ ] * logical . StorageEntry { } ,
} ,
"one entry" : {
entries : [ ] * logical . StorageEntry {
{
Key : "root" ,
} ,
} ,
} ,
"many entries" : {
entries : [ ] * logical . StorageEntry {
// Alphabetical, breadth-first
{ Key : "bar" } ,
{ Key : "foo" } ,
{ Key : "bar/sub-bar1" } ,
{ Key : "bar/sub-bar2" } ,
{ Key : "foo/sub-foo1" } ,
{ Key : "foo/sub-foo2" } ,
{ Key : "foo/sub-foo3" } ,
{ Key : "bar/sub-bar1/sub-sub-bar1" } ,
{ Key : "bar/sub-bar1/sub-sub-bar2" } ,
{ Key : "bar/sub-bar2/sub-sub-bar1" } ,
{ Key : "foo/sub-foo1/sub-sub-foo1" } ,
{ Key : "foo/sub-foo2/sub-sub-foo1" } ,
{ Key : "foo/sub-foo3/sub-sub-foo1" } ,
{ Key : "foo/sub-foo3/sub-sub-foo2" } ,
} ,
} ,
"sub key without root key" : {
entries : [ ] * logical . StorageEntry {
{ Key : "foo/bar/baz" } ,
} ,
} ,
"key with trailing slash" : {
entries : [ ] * logical . StorageEntry {
{ Key : "foo/" } ,
} ,
} ,
"double slash" : {
entries : [ ] * logical . StorageEntry {
{ Key : "foo//" } ,
{ Key : "foo//bar" } ,
} ,
} ,
}
for name , test := range tests {
t . Run ( name , func ( t * testing . T ) {
ctx , cancel := context . WithTimeout ( context . Background ( ) , 10 * time . Second )
defer cancel ( )
store := makeStorage ( t , test . entries ... )
actualEntries := [ ] * logical . StorageEntry { }
f := func ( entry * logical . StorageEntry ) error {
actualEntries = append ( actualEntries , entry )
return nil
}
err := WalkLogicalStorage ( ctx , store , f )
if err != nil {
t . Fatalf ( "Failed to walk storage: %s" , err )
}
if ! reflect . DeepEqual ( actualEntries , test . entries ) {
t . Fatalf ( "Actual: %#v\nExpected: %#v" , actualEntries , test . entries )
}
} )
}
}
func makeStorage ( t * testing . T , entries ... * logical . StorageEntry ) * logical . InmemStorage {
t . Helper ( )
ctx := context . Background ( )
store := new ( logical . InmemStorage )
for _ , entry := range entries {
err := store . Put ( ctx , entry )
if err != nil {
t . Fatalf ( "Unable to load test storage: %s" , err )
}
}
return store
}