2015-03-15 23:39:49 +00:00
package framework
2015-03-14 04:15:20 +00:00
import (
2018-01-08 20:26:13 +00:00
"context"
2018-11-05 20:24:39 +00:00
"net/http"
2015-03-14 04:15:20 +00:00
"reflect"
2018-11-05 20:24:39 +00:00
"strings"
2015-03-18 00:15:23 +00:00
"sync/atomic"
2015-03-14 04:15:20 +00:00
"testing"
2015-03-18 00:58:05 +00:00
"time"
2015-03-14 06:58:20 +00:00
2022-04-12 21:11:33 +00:00
"github.com/hashicorp/go-secure-stdlib/strutil"
2020-01-07 22:04:08 +00:00
"github.com/hashicorp/vault/sdk/helper/consts"
2019-04-12 21:54:35 +00:00
"github.com/hashicorp/vault/sdk/logical"
2022-04-13 14:11:53 +00:00
"github.com/stretchr/testify/require"
2015-03-14 04:15:20 +00:00
)
2015-03-14 06:22:48 +00:00
func BenchmarkBackendRoute ( b * testing . B ) {
patterns := [ ] string {
"foo" ,
"bar/(?P<name>.+?)" ,
"baz/(?P<name>what)" ,
` aws/policy/(?P<policy>\w) ` ,
` aws/(?P<policy>\w) ` ,
}
backend := & Backend { Paths : make ( [ ] * Path , 0 , len ( patterns ) ) }
for _ , p := range patterns {
backend . Paths = append ( backend . Paths , & Path { Pattern : p } )
}
2015-03-14 06:25:17 +00:00
// Warm any caches
backend . Route ( "aws/policy/foo" )
// Reset the timer since we did a lot above
2015-03-14 06:22:48 +00:00
b . ResetTimer ( )
2015-03-14 06:25:17 +00:00
// Run through and route. We do a sanity check of the return value
2015-03-14 06:22:48 +00:00
for i := 0 ; i < b . N ; i ++ {
2015-03-14 06:25:17 +00:00
if p := backend . Route ( "aws/policy/foo" ) ; p == nil {
2015-03-14 06:22:48 +00:00
b . Fatal ( "p should not be nil" )
}
}
}
2015-03-14 06:58:20 +00:00
func TestBackend_impl ( t * testing . T ) {
2015-03-15 21:57:19 +00:00
var _ logical . Backend = new ( Backend )
2015-03-14 06:58:20 +00:00
}
2022-04-11 13:57:12 +00:00
func TestBackendHandleRequestFieldWarnings ( t * testing . T ) {
handler := func ( ctx context . Context , req * logical . Request , data * FieldData ) ( * logical . Response , error ) {
return & logical . Response {
Data : map [ string ] interface { } {
"an_int" : data . Get ( "an_int" ) ,
"a_string" : data . Get ( "a_string" ) ,
"name" : data . Get ( "name" ) ,
} ,
} , nil
}
backend := & Backend {
Paths : [ ] * Path {
{
Pattern : "foo/bar/(?P<name>.+)" ,
Fields : map [ string ] * FieldSchema {
"an_int" : { Type : TypeInt } ,
"a_string" : { Type : TypeString } ,
"name" : { Type : TypeString } ,
} ,
Operations : map [ logical . Operation ] OperationHandler {
logical . UpdateOperation : & PathOperation { Callback : handler } ,
} ,
} ,
} ,
}
ctx := context . Background ( )
resp , err := backend . HandleRequest ( ctx , & logical . Request {
Operation : logical . UpdateOperation ,
Path : "foo/bar/baz" ,
Data : map [ string ] interface { } {
"an_int" : 10 ,
"a_string" : "accepted" ,
"unrecognized1" : "unrecognized" ,
"unrecognized2" : 20.2 ,
"name" : "noop" ,
} ,
} )
require . NoError ( t , err )
require . NotNil ( t , resp )
t . Log ( resp . Warnings )
require . Len ( t , resp . Warnings , 2 )
require . True ( t , strutil . StrListContains ( resp . Warnings , "Endpoint ignored these unrecognized parameters: [unrecognized1 unrecognized2]" ) )
require . True ( t , strutil . StrListContains ( resp . Warnings , "Endpoint replaced the value of these parameters with the values captured from the endpoint's path: [name]" ) )
}
2015-03-14 06:58:20 +00:00
func TestBackendHandleRequest ( t * testing . T ) {
2018-01-08 20:26:13 +00:00
callback := func ( ctx context . Context , req * logical . Request , data * FieldData ) ( * logical . Response , error ) {
2015-03-15 21:57:19 +00:00
return & logical . Response {
2015-03-14 06:58:20 +00:00
Data : map [ string ] interface { } {
2015-03-19 22:11:42 +00:00
"value" : data . Get ( "value" ) ,
2015-03-14 06:58:20 +00:00
} ,
} , nil
}
2018-11-05 20:24:39 +00:00
handler := func ( ctx context . Context , req * logical . Request , data * FieldData ) ( * logical . Response , error ) {
return & logical . Response {
Data : map [ string ] interface { } {
"amount" : data . Get ( "amount" ) ,
} ,
} , nil
}
2015-03-14 06:58:20 +00:00
b := & Backend {
Paths : [ ] * Path {
2018-11-05 20:24:39 +00:00
{
2015-03-14 06:58:20 +00:00
Pattern : "foo/bar" ,
Fields : map [ string ] * FieldSchema {
2021-04-08 16:43:39 +00:00
"value" : { Type : TypeInt } ,
2015-03-14 06:58:20 +00:00
} ,
2015-03-15 21:57:19 +00:00
Callbacks : map [ logical . Operation ] OperationFunc {
logical . ReadOperation : callback ,
2015-03-14 07:19:25 +00:00
} ,
2015-03-14 06:58:20 +00:00
} ,
2018-11-05 20:24:39 +00:00
{
Pattern : "foo/baz/handler" ,
Fields : map [ string ] * FieldSchema {
2021-04-08 16:43:39 +00:00
"amount" : { Type : TypeInt } ,
2018-11-05 20:24:39 +00:00
} ,
Operations : map [ logical . Operation ] OperationHandler {
logical . ReadOperation : & PathOperation { Callback : handler } ,
} ,
} ,
{
Pattern : "foo/both/handler" ,
Fields : map [ string ] * FieldSchema {
2021-04-08 16:43:39 +00:00
"amount" : { Type : TypeInt } ,
2018-11-05 20:24:39 +00:00
} ,
Callbacks : map [ logical . Operation ] OperationFunc {
logical . ReadOperation : callback ,
} ,
Operations : map [ logical . Operation ] OperationHandler {
logical . ReadOperation : & PathOperation { Callback : handler } ,
} ,
} ,
2015-03-14 06:58:20 +00:00
} ,
2020-01-07 22:04:08 +00:00
system : & logical . StaticSystemView { } ,
2015-03-14 06:58:20 +00:00
}
2018-11-05 20:24:39 +00:00
for _ , path := range [ ] string { "foo/bar" , "foo/baz/handler" , "foo/both/handler" } {
key := "value"
if strings . Contains ( path , "handler" ) {
key = "amount"
}
resp , err := b . HandleRequest ( context . Background ( ) , & logical . Request {
Operation : logical . ReadOperation ,
Path : path ,
Data : map [ string ] interface { } { key : "42" } ,
} )
if err != nil {
t . Fatalf ( "err: %s" , err )
}
if resp . Data [ key ] != 42 {
t . Fatalf ( "bad: %#v" , resp )
}
2015-03-14 06:58:20 +00:00
}
}
2020-01-07 22:04:08 +00:00
func TestBackendHandleRequest_Forwarding ( t * testing . T ) {
tests := map [ string ] struct {
fwdStandby bool
fwdSecondary bool
isLocal bool
isStandby bool
isSecondary bool
expectFwd bool
2020-01-08 13:59:44 +00:00
nilSysView bool
2020-01-07 22:04:08 +00:00
} {
"no forward" : {
expectFwd : false ,
} ,
"no forward, local restricted" : {
isSecondary : true ,
fwdSecondary : true ,
isLocal : true ,
expectFwd : false ,
} ,
"no forward, forwarding not requested" : {
isSecondary : true ,
isStandby : true ,
expectFwd : false ,
} ,
"forward, secondary" : {
fwdSecondary : true ,
isSecondary : true ,
expectFwd : true ,
} ,
"forward, standby" : {
fwdStandby : true ,
isStandby : true ,
expectFwd : true ,
} ,
"no forward, only secondary" : {
fwdSecondary : true ,
isStandby : true ,
expectFwd : false ,
} ,
"no forward, only standby" : {
fwdStandby : true ,
isSecondary : true ,
expectFwd : false ,
} ,
2020-01-08 13:59:44 +00:00
"nil system view" : {
nilSysView : true ,
expectFwd : false ,
} ,
2020-01-07 22:04:08 +00:00
}
for name , test := range tests {
t . Run ( name , func ( t * testing . T ) {
var replState consts . ReplicationState
if test . isStandby {
replState . AddState ( consts . ReplicationPerformanceStandby )
}
if test . isSecondary {
replState . AddState ( consts . ReplicationPerformanceSecondary )
}
b := & Backend {
Paths : [ ] * Path {
{
Pattern : "foo" ,
Operations : map [ logical . Operation ] OperationHandler {
logical . ReadOperation : & PathOperation {
Callback : func ( ctx context . Context , req * logical . Request , data * FieldData ) ( * logical . Response , error ) {
return nil , nil
} ,
ForwardPerformanceSecondary : test . fwdSecondary ,
ForwardPerformanceStandby : test . fwdStandby ,
} ,
} ,
} ,
} ,
system : & logical . StaticSystemView {
LocalMountVal : test . isLocal ,
ReplicationStateVal : replState ,
} ,
}
2020-01-08 13:59:44 +00:00
if test . nilSysView {
b . system = nil
}
2020-01-07 22:04:08 +00:00
_ , err := b . HandleRequest ( context . Background ( ) , & logical . Request {
Operation : logical . ReadOperation ,
Path : "foo" ,
} )
if ! test . expectFwd && err != nil {
t . Fatalf ( "unexpected err: %v" , err )
}
if test . expectFwd && err != logical . ErrReadOnly {
t . Fatalf ( "expected ErrReadOnly, got: %v" , err )
}
} )
}
}
2015-08-11 16:34:14 +00:00
func TestBackendHandleRequest_badwrite ( t * testing . T ) {
2018-01-08 20:26:13 +00:00
callback := func ( ctx context . Context , req * logical . Request , data * FieldData ) ( * logical . Response , error ) {
2015-08-11 16:34:14 +00:00
return & logical . Response {
Data : map [ string ] interface { } {
"value" : data . Get ( "value" ) . ( bool ) ,
} ,
} , nil
}
b := & Backend {
Paths : [ ] * Path {
2021-04-08 16:43:39 +00:00
{
2015-08-11 16:34:14 +00:00
Pattern : "foo/bar" ,
Fields : map [ string ] * FieldSchema {
2021-04-08 16:43:39 +00:00
"value" : { Type : TypeBool } ,
2015-08-11 16:34:14 +00:00
} ,
Callbacks : map [ logical . Operation ] OperationFunc {
2016-01-07 15:30:47 +00:00
logical . UpdateOperation : callback ,
2015-08-11 16:34:14 +00:00
} ,
} ,
} ,
}
2021-07-12 17:39:28 +00:00
resp , err := b . HandleRequest ( context . Background ( ) , & logical . Request {
2016-01-07 15:30:47 +00:00
Operation : logical . UpdateOperation ,
2015-08-11 16:34:14 +00:00
Path : "foo/bar" ,
Data : map [ string ] interface { } { "value" : "3false3" } ,
} )
2021-07-12 17:39:28 +00:00
if err != nil {
t . Fatalf ( "err: %s" , err )
}
2015-08-11 16:34:14 +00:00
2021-07-12 17:39:28 +00:00
if ! strings . Contains ( resp . Data [ "error" ] . ( string ) , "Field validation failed" ) {
t . Fatalf ( "bad: %#v" , resp )
2015-08-11 16:34:14 +00:00
}
}
2015-03-14 06:58:20 +00:00
func TestBackendHandleRequest_404 ( t * testing . T ) {
2018-01-08 20:26:13 +00:00
callback := func ( ctx context . Context , req * logical . Request , data * FieldData ) ( * logical . Response , error ) {
2015-03-15 21:57:19 +00:00
return & logical . Response {
2015-03-14 06:58:20 +00:00
Data : map [ string ] interface { } {
2015-03-19 22:11:42 +00:00
"value" : data . Get ( "value" ) ,
2015-03-14 06:58:20 +00:00
} ,
} , nil
}
b := & Backend {
Paths : [ ] * Path {
2021-04-08 16:43:39 +00:00
{
2015-03-14 06:58:20 +00:00
Pattern : ` foo/bar ` ,
Fields : map [ string ] * FieldSchema {
2021-04-08 16:43:39 +00:00
"value" : { Type : TypeInt } ,
2015-03-14 06:58:20 +00:00
} ,
2015-03-15 21:57:19 +00:00
Callbacks : map [ logical . Operation ] OperationFunc {
logical . ReadOperation : callback ,
2015-03-14 07:19:25 +00:00
} ,
2015-03-14 06:58:20 +00:00
} ,
} ,
}
2018-01-08 20:26:13 +00:00
_ , err := b . HandleRequest ( context . Background ( ) , & logical . Request {
2015-03-15 21:57:19 +00:00
Operation : logical . ReadOperation ,
2015-03-14 07:19:25 +00:00
Path : "foo/baz" ,
Data : map [ string ] interface { } { "value" : "84" } ,
2015-03-14 06:58:20 +00:00
} )
2015-03-15 21:57:19 +00:00
if err != logical . ErrUnsupportedPath {
2015-03-14 06:58:20 +00:00
t . Fatalf ( "err: %s" , err )
}
}
2015-03-14 17:12:50 +00:00
func TestBackendHandleRequest_help ( t * testing . T ) {
b := & Backend {
Paths : [ ] * Path {
2021-04-08 16:43:39 +00:00
{
2015-03-14 17:12:50 +00:00
Pattern : "foo/bar" ,
Fields : map [ string ] * FieldSchema {
2021-04-08 16:43:39 +00:00
"value" : { Type : TypeInt } ,
2015-03-14 17:12:50 +00:00
} ,
HelpSynopsis : "foo" ,
HelpDescription : "bar" ,
} ,
} ,
}
2018-01-08 20:26:13 +00:00
resp , err := b . HandleRequest ( context . Background ( ) , & logical . Request {
2015-03-15 21:57:19 +00:00
Operation : logical . HelpOperation ,
2015-03-14 17:12:50 +00:00
Path : "foo/bar" ,
Data : map [ string ] interface { } { "value" : "42" } ,
} )
if err != nil {
t . Fatalf ( "err: %s" , err )
}
if resp . Data [ "help" ] == nil {
t . Fatalf ( "bad: %#v" , resp )
}
}
2015-04-04 03:36:47 +00:00
func TestBackendHandleRequest_helpRoot ( t * testing . T ) {
b := & Backend {
Help : "42" ,
}
2018-01-08 20:26:13 +00:00
resp , err := b . HandleRequest ( context . Background ( ) , & logical . Request {
2015-04-04 03:36:47 +00:00
Operation : logical . HelpOperation ,
Path : "" ,
} )
if err != nil {
t . Fatalf ( "err: %s" , err )
}
if resp . Data [ "help" ] == nil {
t . Fatalf ( "bad: %#v" , resp )
}
}
2015-04-11 21:46:09 +00:00
func TestBackendHandleRequest_renewAuth ( t * testing . T ) {
b := & Backend { }
2018-01-08 20:26:13 +00:00
resp , err := b . HandleRequest ( context . Background ( ) , logical . RenewAuthRequest ( "/foo" , & logical . Auth { } , nil ) )
2015-04-11 21:46:09 +00:00
if err != nil {
t . Fatalf ( "err: %s" , err )
}
if ! resp . IsError ( ) {
t . Fatalf ( "bad: %#v" , resp )
}
}
func TestBackendHandleRequest_renewAuthCallback ( t * testing . T ) {
2018-06-09 19:35:22 +00:00
called := new ( uint32 )
2018-01-08 20:26:13 +00:00
callback := func ( context . Context , * logical . Request , * FieldData ) ( * logical . Response , error ) {
2018-06-09 19:35:22 +00:00
atomic . AddUint32 ( called , 1 )
2015-04-11 21:46:09 +00:00
return nil , nil
}
b := & Backend {
AuthRenew : callback ,
}
2018-01-08 20:26:13 +00:00
_ , err := b . HandleRequest ( context . Background ( ) , logical . RenewAuthRequest ( "/foo" , & logical . Auth { } , nil ) )
2015-04-11 21:46:09 +00:00
if err != nil {
t . Fatalf ( "err: %s" , err )
}
2018-06-09 19:35:22 +00:00
if v := atomic . LoadUint32 ( called ) ; v != 1 {
2015-04-11 21:46:09 +00:00
t . Fatalf ( "bad: %#v" , v )
}
}
2021-04-08 16:43:39 +00:00
2015-03-19 19:20:25 +00:00
func TestBackendHandleRequest_renew ( t * testing . T ) {
2018-06-09 19:35:22 +00:00
called := new ( uint32 )
2018-01-08 20:26:13 +00:00
callback := func ( context . Context , * logical . Request , * FieldData ) ( * logical . Response , error ) {
2018-06-09 19:35:22 +00:00
atomic . AddUint32 ( called , 1 )
2015-03-19 19:20:25 +00:00
return nil , nil
}
2015-03-19 22:11:42 +00:00
secret := & Secret {
Type : "foo" ,
Renew : callback ,
}
2015-03-19 19:20:25 +00:00
b := & Backend {
2015-03-19 22:11:42 +00:00
Secrets : [ ] * Secret { secret } ,
2015-03-19 19:20:25 +00:00
}
2018-01-08 20:26:13 +00:00
_ , err := b . HandleRequest ( context . Background ( ) , logical . RenewRequest ( "/foo" , secret . Response ( nil , nil ) . Secret , nil ) )
2015-03-19 19:20:25 +00:00
if err != nil {
t . Fatalf ( "err: %s" , err )
}
2018-06-09 19:35:22 +00:00
if v := atomic . LoadUint32 ( called ) ; v != 1 {
2015-03-19 19:20:25 +00:00
t . Fatalf ( "bad: %#v" , v )
}
}
2015-03-19 18:41:41 +00:00
func TestBackendHandleRequest_revoke ( t * testing . T ) {
2018-06-09 19:35:22 +00:00
called := new ( uint32 )
2018-01-08 20:26:13 +00:00
callback := func ( context . Context , * logical . Request , * FieldData ) ( * logical . Response , error ) {
2018-06-09 19:35:22 +00:00
atomic . AddUint32 ( called , 1 )
2015-03-19 18:41:41 +00:00
return nil , nil
}
2015-03-19 22:11:42 +00:00
secret := & Secret {
Type : "foo" ,
Revoke : callback ,
}
2015-03-19 18:41:41 +00:00
b := & Backend {
2015-03-19 22:11:42 +00:00
Secrets : [ ] * Secret { secret } ,
2015-03-19 18:41:41 +00:00
}
2018-01-08 20:26:13 +00:00
_ , err := b . HandleRequest ( context . Background ( ) , logical . RevokeRequest ( "/foo" , secret . Response ( nil , nil ) . Secret , nil ) )
2015-03-19 18:41:41 +00:00
if err != nil {
t . Fatalf ( "err: %s" , err )
}
2018-06-09 19:35:22 +00:00
if v := atomic . LoadUint32 ( called ) ; v != 1 {
2015-03-19 18:41:41 +00:00
t . Fatalf ( "bad: %#v" , v )
}
}
2015-03-18 00:15:23 +00:00
func TestBackendHandleRequest_rollback ( t * testing . T ) {
2018-06-09 19:35:22 +00:00
called := new ( uint32 )
2018-01-19 06:44:44 +00:00
callback := func ( _ context . Context , req * logical . Request , kind string , data interface { } ) error {
2015-03-18 00:15:23 +00:00
if data == "foo" {
2018-06-09 19:35:22 +00:00
atomic . AddUint32 ( called , 1 )
2015-03-18 00:15:23 +00:00
}
2015-03-21 10:08:13 +00:00
return nil
2015-03-18 00:15:23 +00:00
}
b := & Backend {
2016-05-14 23:35:36 +00:00
WALRollback : callback ,
WALRollbackMinAge : 1 * time . Millisecond ,
2015-03-18 00:15:23 +00:00
}
storage := new ( logical . InmemStorage )
2018-01-19 06:44:44 +00:00
if _ , err := PutWAL ( context . Background ( ) , storage , "kind" , "foo" ) ; err != nil {
2015-03-18 00:15:23 +00:00
t . Fatalf ( "err: %s" , err )
}
2015-03-18 00:58:05 +00:00
time . Sleep ( 10 * time . Millisecond )
2018-01-08 20:26:13 +00:00
_ , err := b . HandleRequest ( context . Background ( ) , & logical . Request {
2015-03-18 00:15:23 +00:00
Operation : logical . RollbackOperation ,
Path : "" ,
Storage : storage ,
} )
if err != nil {
t . Fatalf ( "err: %s" , err )
}
2018-06-09 19:35:22 +00:00
if v := atomic . LoadUint32 ( called ) ; v != 1 {
2015-03-18 00:15:23 +00:00
t . Fatalf ( "bad: %#v" , v )
}
}
2015-03-18 01:42:35 +00:00
func TestBackendHandleRequest_rollbackMinAge ( t * testing . T ) {
2018-06-09 19:35:22 +00:00
called := new ( uint32 )
2018-01-19 06:44:44 +00:00
callback := func ( _ context . Context , req * logical . Request , kind string , data interface { } ) error {
2015-03-18 01:42:35 +00:00
if data == "foo" {
2018-06-09 19:35:22 +00:00
atomic . AddUint32 ( called , 1 )
2015-03-18 01:42:35 +00:00
}
2015-03-21 10:08:13 +00:00
return nil
2015-03-18 01:42:35 +00:00
}
b := & Backend {
2016-05-14 23:35:36 +00:00
WALRollback : callback ,
WALRollbackMinAge : 5 * time . Second ,
2015-03-18 01:42:35 +00:00
}
storage := new ( logical . InmemStorage )
2018-01-19 06:44:44 +00:00
if _ , err := PutWAL ( context . Background ( ) , storage , "kind" , "foo" ) ; err != nil {
2015-03-18 01:42:35 +00:00
t . Fatalf ( "err: %s" , err )
}
2018-01-08 20:26:13 +00:00
_ , err := b . HandleRequest ( context . Background ( ) , & logical . Request {
2015-03-18 01:42:35 +00:00
Operation : logical . RollbackOperation ,
Path : "" ,
Storage : storage ,
} )
if err != nil {
t . Fatalf ( "err: %s" , err )
}
2018-06-09 19:35:22 +00:00
if v := atomic . LoadUint32 ( called ) ; v != 0 {
2015-03-18 01:42:35 +00:00
t . Fatalf ( "bad: %#v" , v )
}
}
2015-03-14 07:19:25 +00:00
func TestBackendHandleRequest_unsupportedOperation ( t * testing . T ) {
2018-01-08 20:26:13 +00:00
callback := func ( ctx context . Context , req * logical . Request , data * FieldData ) ( * logical . Response , error ) {
2015-03-15 21:57:19 +00:00
return & logical . Response {
2015-03-14 07:19:25 +00:00
Data : map [ string ] interface { } {
2015-03-19 22:11:42 +00:00
"value" : data . Get ( "value" ) ,
2015-03-14 07:19:25 +00:00
} ,
} , nil
}
b := & Backend {
Paths : [ ] * Path {
2021-04-08 16:43:39 +00:00
{
2015-03-14 07:19:25 +00:00
Pattern : ` foo/bar ` ,
Fields : map [ string ] * FieldSchema {
2021-04-08 16:43:39 +00:00
"value" : { Type : TypeInt } ,
2015-03-14 07:19:25 +00:00
} ,
2015-03-15 21:57:19 +00:00
Callbacks : map [ logical . Operation ] OperationFunc {
logical . ReadOperation : callback ,
2015-03-14 07:19:25 +00:00
} ,
} ,
} ,
}
2018-01-08 20:26:13 +00:00
_ , err := b . HandleRequest ( context . Background ( ) , & logical . Request {
2016-01-07 15:30:47 +00:00
Operation : logical . UpdateOperation ,
2015-03-14 07:19:25 +00:00
Path : "foo/bar" ,
Data : map [ string ] interface { } { "value" : "84" } ,
} )
2015-03-15 21:57:19 +00:00
if err != logical . ErrUnsupportedOperation {
2015-03-14 07:19:25 +00:00
t . Fatalf ( "err: %s" , err )
}
}
2015-03-14 06:58:20 +00:00
func TestBackendHandleRequest_urlPriority ( t * testing . T ) {
2018-01-08 20:26:13 +00:00
callback := func ( ctx context . Context , req * logical . Request , data * FieldData ) ( * logical . Response , error ) {
2015-03-15 21:57:19 +00:00
return & logical . Response {
2015-03-14 06:58:20 +00:00
Data : map [ string ] interface { } {
2015-03-19 22:11:42 +00:00
"value" : data . Get ( "value" ) ,
2015-03-14 06:58:20 +00:00
} ,
} , nil
}
b := & Backend {
Paths : [ ] * Path {
2021-04-08 16:43:39 +00:00
{
2015-03-14 06:58:20 +00:00
Pattern : ` foo/(?P<value>\d+) ` ,
Fields : map [ string ] * FieldSchema {
2021-04-08 16:43:39 +00:00
"value" : { Type : TypeInt } ,
2015-03-14 06:58:20 +00:00
} ,
2015-03-15 21:57:19 +00:00
Callbacks : map [ logical . Operation ] OperationFunc {
logical . ReadOperation : callback ,
2015-03-14 07:19:25 +00:00
} ,
2015-03-14 06:58:20 +00:00
} ,
} ,
}
2018-01-08 20:26:13 +00:00
resp , err := b . HandleRequest ( context . Background ( ) , & logical . Request {
2015-03-15 21:57:19 +00:00
Operation : logical . ReadOperation ,
2015-03-14 07:19:25 +00:00
Path : "foo/42" ,
Data : map [ string ] interface { } { "value" : "84" } ,
2015-03-14 06:58:20 +00:00
} )
if err != nil {
t . Fatalf ( "err: %s" , err )
}
if resp . Data [ "value" ] != 42 {
t . Fatalf ( "bad: %#v" , resp )
}
}
2015-03-14 06:17:25 +00:00
func TestBackendRoute ( t * testing . T ) {
cases := map [ string ] struct {
Patterns [ ] string
Path string
Match string
} {
"no match" : {
[ ] string { "foo" } ,
"bar" ,
"" ,
} ,
"exact" : {
[ ] string { "foo" } ,
"foo" ,
2015-04-02 00:53:02 +00:00
"^foo$" ,
2015-03-14 06:17:25 +00:00
} ,
"regexp" : {
[ ] string { "fo+" } ,
"foo" ,
2015-04-02 00:53:02 +00:00
"^fo+$" ,
} ,
"anchor-start" : {
[ ] string { "bar" } ,
"foobar" ,
"" ,
} ,
"anchor-end" : {
[ ] string { "bar" } ,
"barfoo" ,
"" ,
} ,
"anchor-ambiguous" : {
[ ] string { "mounts" , "sys/mounts" } ,
"sys/mounts" ,
"^sys/mounts$" ,
2015-03-14 06:17:25 +00:00
} ,
}
for n , tc := range cases {
paths := make ( [ ] * Path , len ( tc . Patterns ) )
for i , pattern := range tc . Patterns {
paths [ i ] = & Path { Pattern : pattern }
}
b := & Backend { Paths : paths }
result := b . Route ( tc . Path )
match := ""
if result != nil {
match = result . Pattern
}
if match != tc . Match {
t . Fatalf ( "bad: %s\n\nExpected: %s\nGot: %s" ,
n , tc . Match , match )
}
}
}
2015-03-19 13:59:01 +00:00
func TestBackendSecret ( t * testing . T ) {
cases := map [ string ] struct {
Secrets [ ] * Secret
Search string
Match bool
} {
"no match" : {
2021-04-08 16:43:39 +00:00
[ ] * Secret { { Type : "foo" } } ,
2015-03-19 13:59:01 +00:00
"bar" ,
false ,
} ,
"match" : {
2021-04-08 16:43:39 +00:00
[ ] * Secret { { Type : "foo" } } ,
2015-03-19 13:59:01 +00:00
"foo" ,
true ,
} ,
}
for n , tc := range cases {
b := & Backend { Secrets : tc . Secrets }
result := b . Secret ( tc . Search )
if tc . Match != ( result != nil ) {
t . Fatalf ( "bad: %s\n\nExpected match: %v" , n , tc . Match )
}
if result != nil && result . Type != tc . Search {
t . Fatalf ( "bad: %s\n\nExpected matching type: %#v" , n , result )
}
}
}
2015-03-14 04:15:20 +00:00
func TestFieldSchemaDefaultOrZero ( t * testing . T ) {
cases := map [ string ] struct {
Schema * FieldSchema
Value interface { }
} {
"default set" : {
& FieldSchema { Type : TypeString , Default : "foo" } ,
"foo" ,
} ,
"default not set" : {
& FieldSchema { Type : TypeString } ,
"" ,
} ,
2015-06-17 22:56:26 +00:00
"default duration set" : {
& FieldSchema { Type : TypeDurationSecond , Default : 60 } ,
60 ,
} ,
2017-02-17 22:25:53 +00:00
"default duration int64" : {
& FieldSchema { Type : TypeDurationSecond , Default : int64 ( 60 ) } ,
60 ,
} ,
"default duration string" : {
& FieldSchema { Type : TypeDurationSecond , Default : "60s" } ,
60 ,
} ,
2019-06-26 17:15:36 +00:00
"illegal default duration string" : {
& FieldSchema { Type : TypeDurationSecond , Default : "h1" } ,
0 ,
} ,
2019-06-20 16:28:15 +00:00
"default duration time.Duration" : {
& FieldSchema { Type : TypeDurationSecond , Default : 60 * time . Second } ,
60 ,
} ,
2015-06-17 22:56:26 +00:00
"default duration not set" : {
& FieldSchema { Type : TypeDurationSecond } ,
0 ,
} ,
2018-08-13 18:02:44 +00:00
2019-06-26 17:15:36 +00:00
"default signed positive duration set" : {
& FieldSchema { Type : TypeSignedDurationSecond , Default : 60 } ,
60 ,
} ,
"default signed positive duration int64" : {
& FieldSchema { Type : TypeSignedDurationSecond , Default : int64 ( 60 ) } ,
60 ,
} ,
"default signed positive duration string" : {
& FieldSchema { Type : TypeSignedDurationSecond , Default : "60s" } ,
60 ,
} ,
"illegal default signed duration string" : {
& FieldSchema { Type : TypeDurationSecond , Default : "-h1" } ,
0 ,
} ,
"default signed positive duration time.Duration" : {
& FieldSchema { Type : TypeSignedDurationSecond , Default : 60 * time . Second } ,
60 ,
} ,
"default signed negative duration set" : {
& FieldSchema { Type : TypeSignedDurationSecond , Default : - 60 } ,
- 60 ,
} ,
"default signed negative duration int64" : {
& FieldSchema { Type : TypeSignedDurationSecond , Default : int64 ( - 60 ) } ,
- 60 ,
} ,
"default signed negative duration string" : {
& FieldSchema { Type : TypeSignedDurationSecond , Default : "-60s" } ,
- 60 ,
} ,
"default signed negative duration time.Duration" : {
& FieldSchema { Type : TypeSignedDurationSecond , Default : - 60 * time . Second } ,
- 60 ,
} ,
"default signed negative duration not set" : {
& FieldSchema { Type : TypeSignedDurationSecond } ,
0 ,
} ,
2018-08-13 18:02:44 +00:00
"default header not set" : {
& FieldSchema { Type : TypeHeader } ,
http . Header { } ,
} ,
2015-03-14 04:15:20 +00:00
}
for name , tc := range cases {
actual := tc . Schema . DefaultOrZero ( )
if ! reflect . DeepEqual ( actual , tc . Value ) {
2019-06-26 17:15:36 +00:00
t . Errorf ( "bad: %s\n\nExpected: %#v\nGot: %#v" ,
2015-03-14 04:15:20 +00:00
name , tc . Value , actual )
}
}
}
2019-07-05 23:55:40 +00:00
func TestInitializeBackend ( t * testing . T ) {
var inited bool
backend := & Backend { InitializeFunc : func ( context . Context , * logical . InitializationRequest ) error {
inited = true
return nil
} }
backend . Initialize ( nil , & logical . InitializationRequest { Storage : nil } )
if ! inited {
t . Fatal ( "backend should be open" )
}
}