github.com/hashicorp/vault/sdk@v0.13.0/physical/testing.go (about)

     1  // Copyright (c) HashiCorp, Inc.
     2  // SPDX-License-Identifier: MPL-2.0
     3  
     4  package physical
     5  
     6  import (
     7  	"context"
     8  	"reflect"
     9  	"sort"
    10  	"testing"
    11  	"time"
    12  
    13  	"github.com/stretchr/testify/require"
    14  )
    15  
    16  func ExerciseBackend(t testing.TB, b Backend) {
    17  	t.Helper()
    18  	ctx := context.Background()
    19  
    20  	// Should be empty
    21  	keys, err := b.List(ctx, "")
    22  	if err != nil {
    23  		t.Fatalf("initial list failed: %v", err)
    24  	}
    25  	if len(keys) != 0 {
    26  		t.Errorf("initial not empty: %v", keys)
    27  	}
    28  
    29  	// Delete should work if it does not exist
    30  	err = b.Delete(ctx, "foo")
    31  	if err != nil {
    32  		t.Fatalf("idempotent delete: %v", err)
    33  	}
    34  
    35  	// Get should not fail, but be nil
    36  	out, err := b.Get(ctx, "foo")
    37  	if err != nil {
    38  		t.Fatalf("initial get failed: %v", err)
    39  	}
    40  	if out != nil {
    41  		t.Errorf("initial get was not nil: %v", out)
    42  	}
    43  
    44  	// Make an entry
    45  	e := &Entry{Key: "foo", Value: []byte("test")}
    46  	err = b.Put(ctx, e)
    47  	if err != nil {
    48  		t.Fatalf("put failed: %v", err)
    49  	}
    50  
    51  	// Get should work
    52  	out, err = b.Get(ctx, "foo")
    53  	if err != nil {
    54  		t.Fatalf("get failed: %v", err)
    55  	}
    56  	if !reflect.DeepEqual(out, e) {
    57  		t.Errorf("bad: %v expected: %v", out, e)
    58  	}
    59  
    60  	// List should not be empty
    61  	keys, err = b.List(ctx, "")
    62  	if err != nil {
    63  		t.Fatalf("list failed: %v", err)
    64  	}
    65  	if len(keys) != 1 || keys[0] != "foo" {
    66  		t.Errorf("keys[0] did not equal foo: %v", keys)
    67  	}
    68  
    69  	// Delete should work
    70  	err = b.Delete(ctx, "foo")
    71  	if err != nil {
    72  		t.Fatalf("delete: %v", err)
    73  	}
    74  
    75  	// Should be empty
    76  	keys, err = b.List(ctx, "")
    77  	if err != nil {
    78  		t.Fatalf("list after delete: %v", err)
    79  	}
    80  	if len(keys) != 0 {
    81  		t.Errorf("list after delete not empty: %v", keys)
    82  	}
    83  
    84  	// Get should fail
    85  	out, err = b.Get(ctx, "foo")
    86  	if err != nil {
    87  		t.Fatalf("get after delete: %v", err)
    88  	}
    89  	if out != nil {
    90  		t.Errorf("get after delete not nil: %v", out)
    91  	}
    92  
    93  	// Multiple Puts should work; GH-189
    94  	e = &Entry{Key: "foo", Value: []byte("test")}
    95  	err = b.Put(ctx, e)
    96  	if err != nil {
    97  		t.Fatalf("multi put 1 failed: %v", err)
    98  	}
    99  	e = &Entry{Key: "foo", Value: []byte("test")}
   100  	err = b.Put(ctx, e)
   101  	if err != nil {
   102  		t.Fatalf("multi put 2 failed: %v", err)
   103  	}
   104  
   105  	// Make a nested entry
   106  	e = &Entry{Key: "foo/bar", Value: []byte("baz")}
   107  	err = b.Put(ctx, e)
   108  	if err != nil {
   109  		t.Fatalf("nested put failed: %v", err)
   110  	}
   111  
   112  	// Get should work
   113  	out, err = b.Get(ctx, "foo/bar")
   114  	if err != nil {
   115  		t.Fatalf("get failed: %v", err)
   116  	}
   117  	if !reflect.DeepEqual(out, e) {
   118  		t.Errorf("bad: %v expected: %v", out, e)
   119  	}
   120  
   121  	keys, err = b.List(ctx, "")
   122  	if err != nil {
   123  		t.Fatalf("list multi failed: %v", err)
   124  	}
   125  	sort.Strings(keys)
   126  	if len(keys) != 2 || keys[0] != "foo" || keys[1] != "foo/" {
   127  		t.Errorf("expected 2 keys [foo, foo/]: %v", keys)
   128  	}
   129  
   130  	// Delete with children should work
   131  	err = b.Delete(ctx, "foo")
   132  	if err != nil {
   133  		t.Fatalf("delete after multi: %v", err)
   134  	}
   135  
   136  	// Get should return the child
   137  	out, err = b.Get(ctx, "foo/bar")
   138  	if err != nil {
   139  		t.Fatalf("get after multi delete: %v", err)
   140  	}
   141  	if out == nil {
   142  		t.Errorf("get after multi delete not nil: %v", out)
   143  	}
   144  
   145  	// Removal of nested secret should not leave artifacts
   146  	e = &Entry{Key: "foo/nested1/nested2/nested3", Value: []byte("baz")}
   147  	err = b.Put(ctx, e)
   148  	if err != nil {
   149  		t.Fatalf("deep nest: %v", err)
   150  	}
   151  
   152  	err = b.Delete(ctx, "foo/nested1/nested2/nested3")
   153  	if err != nil {
   154  		t.Fatalf("failed to remove deep nest: %v", err)
   155  	}
   156  
   157  	keys, err = b.List(ctx, "foo/")
   158  	if err != nil {
   159  		t.Fatalf("err: %v", err)
   160  	}
   161  	if len(keys) != 1 || keys[0] != "bar" {
   162  		t.Errorf("should be exactly 1 key == bar: %v", keys)
   163  	}
   164  
   165  	// Make a second nested entry to test prefix removal
   166  	e = &Entry{Key: "foo/zip", Value: []byte("zap")}
   167  	err = b.Put(ctx, e)
   168  	if err != nil {
   169  		t.Fatalf("failed to create second nested: %v", err)
   170  	}
   171  
   172  	// Delete should not remove the prefix
   173  	err = b.Delete(ctx, "foo/bar")
   174  	if err != nil {
   175  		t.Fatalf("failed to delete nested prefix: %v", err)
   176  	}
   177  
   178  	keys, err = b.List(ctx, "")
   179  	if err != nil {
   180  		t.Fatalf("list nested prefix: %v", err)
   181  	}
   182  	if len(keys) != 1 || keys[0] != "foo/" {
   183  		t.Errorf("should be exactly 1 key == foo/: %v", keys)
   184  	}
   185  
   186  	// Delete should remove the prefix
   187  	err = b.Delete(ctx, "foo/zip")
   188  	if err != nil {
   189  		t.Fatalf("failed to delete second prefix: %v", err)
   190  	}
   191  
   192  	keys, err = b.List(ctx, "")
   193  	if err != nil {
   194  		t.Fatalf("listing after second delete failed: %v", err)
   195  	}
   196  	if len(keys) != 0 {
   197  		t.Errorf("should be empty at end: %v", keys)
   198  	}
   199  
   200  	// When the root path is empty, adding and removing deep nested values should not break listing
   201  	e = &Entry{Key: "foo/nested1/nested2/value1", Value: []byte("baz")}
   202  	err = b.Put(ctx, e)
   203  	if err != nil {
   204  		t.Fatalf("deep nest: %v", err)
   205  	}
   206  
   207  	e = &Entry{Key: "foo/nested1/nested2/value2", Value: []byte("baz")}
   208  	err = b.Put(ctx, e)
   209  	if err != nil {
   210  		t.Fatalf("deep nest: %v", err)
   211  	}
   212  
   213  	err = b.Delete(ctx, "foo/nested1/nested2/value2")
   214  	if err != nil {
   215  		t.Fatalf("failed to remove deep nest: %v", err)
   216  	}
   217  
   218  	keys, err = b.List(ctx, "")
   219  	if err != nil {
   220  		t.Fatalf("listing of root failed after deletion: %v", err)
   221  	}
   222  	if len(keys) == 0 {
   223  		t.Errorf("root is returning empty after deleting a single nested value, expected nested1/: %v", keys)
   224  		keys, err = b.List(ctx, "foo/nested1")
   225  		if err != nil {
   226  			t.Fatalf("listing of expected nested path 'foo/nested1' failed: %v", err)
   227  		}
   228  		// prove that the root should not be empty and that foo/nested1 exists
   229  		if len(keys) != 0 {
   230  			t.Logf("  keys can still be listed from nested1/ so it's not empty, expected nested2/: %v", keys)
   231  		}
   232  	}
   233  
   234  	// cleanup left over listing bug test value
   235  	err = b.Delete(ctx, "foo/nested1/nested2/value1")
   236  	if err != nil {
   237  		t.Fatalf("failed to remove deep nest: %v", err)
   238  	}
   239  
   240  	keys, err = b.List(ctx, "")
   241  	if err != nil {
   242  		t.Fatalf("listing of root failed after delete of deep nest: %v", err)
   243  	}
   244  	if len(keys) != 0 {
   245  		t.Errorf("should be empty at end: %v", keys)
   246  	}
   247  }
   248  
   249  func ExerciseBackend_ListPrefix(t testing.TB, b Backend) {
   250  	t.Helper()
   251  	ctx := context.Background()
   252  
   253  	e1 := &Entry{Key: "foo", Value: []byte("test")}
   254  	e2 := &Entry{Key: "foo/bar", Value: []byte("test")}
   255  	e3 := &Entry{Key: "foo/bar/baz", Value: []byte("test")}
   256  
   257  	defer func() {
   258  		_ = b.Delete(ctx, "foo")
   259  		_ = b.Delete(ctx, "foo/bar")
   260  		_ = b.Delete(ctx, "foo/bar/baz")
   261  	}()
   262  
   263  	err := b.Put(ctx, e1)
   264  	if err != nil {
   265  		t.Fatalf("failed to put entry 1: %v", err)
   266  	}
   267  	err = b.Put(ctx, e2)
   268  	if err != nil {
   269  		t.Fatalf("failed to put entry 2: %v", err)
   270  	}
   271  	err = b.Put(ctx, e3)
   272  	if err != nil {
   273  		t.Fatalf("failed to put entry 3: %v", err)
   274  	}
   275  
   276  	// Scan the root
   277  	keys, err := b.List(ctx, "")
   278  	if err != nil {
   279  		t.Fatalf("list root: %v", err)
   280  	}
   281  	sort.Strings(keys)
   282  	if len(keys) != 2 || keys[0] != "foo" || keys[1] != "foo/" {
   283  		t.Errorf("root expected [foo foo/]: %v", keys)
   284  	}
   285  
   286  	// Scan foo/
   287  	keys, err = b.List(ctx, "foo/")
   288  	if err != nil {
   289  		t.Fatalf("list level 1: %v", err)
   290  	}
   291  	sort.Strings(keys)
   292  	if len(keys) != 2 || keys[0] != "bar" || keys[1] != "bar/" {
   293  		t.Errorf("level 1 expected [bar bar/]: %v", keys)
   294  	}
   295  
   296  	// Scan foo/bar/
   297  	keys, err = b.List(ctx, "foo/bar/")
   298  	if err != nil {
   299  		t.Fatalf("list level 2: %v", err)
   300  	}
   301  	sort.Strings(keys)
   302  	if len(keys) != 1 || keys[0] != "baz" {
   303  		t.Errorf("level 1 expected [baz]: %v", keys)
   304  	}
   305  }
   306  
   307  func ExerciseHABackend(t testing.TB, b HABackend, b2 HABackend) {
   308  	t.Helper()
   309  
   310  	// Get the lock
   311  	lock, err := b.LockWith("foo", "bar")
   312  	if err != nil {
   313  		t.Fatalf("initial lock: %v", err)
   314  	}
   315  
   316  	// Attempt to lock
   317  	leaderCh, err := lock.Lock(nil)
   318  	if err != nil {
   319  		t.Fatalf("lock attempt 1: %v", err)
   320  	}
   321  	if leaderCh == nil {
   322  		t.Fatalf("missing leaderCh")
   323  	}
   324  
   325  	// Check the value
   326  	held, val, err := lock.Value()
   327  	if err != nil {
   328  		t.Fatalf("err: %v", err)
   329  	}
   330  	if !held {
   331  		t.Errorf("should be held")
   332  	}
   333  	if val != "bar" {
   334  		t.Errorf("expected value bar: %v", err)
   335  	}
   336  
   337  	// Check if it's fencing that we can register the lock
   338  	if fba, ok := b.(FencingHABackend); ok {
   339  		require.NoError(t, fba.RegisterActiveNodeLock(lock))
   340  	}
   341  
   342  	// Second acquisition should fail
   343  	lock2, err := b2.LockWith("foo", "baz")
   344  	if err != nil {
   345  		t.Fatalf("lock 2: %v", err)
   346  	}
   347  
   348  	// Checking the lock from b2 should discover that the lock is held since held
   349  	// implies only that there is _some_ leader not that b2 is leader (this was
   350  	// not clear before so we make it explicit with this assertion).
   351  	held2, val2, err := lock2.Value()
   352  	require.NoError(t, err)
   353  	require.Equal(t, "bar", val2)
   354  	require.True(t, held2)
   355  
   356  	// Cancel attempt in 50 msec
   357  	stopCh := make(chan struct{})
   358  	time.AfterFunc(50*time.Millisecond, func() {
   359  		close(stopCh)
   360  	})
   361  
   362  	// Attempt to lock
   363  	leaderCh2, err := lock2.Lock(stopCh)
   364  	if err != nil {
   365  		t.Fatalf("stop lock 2: %v", err)
   366  	}
   367  	if leaderCh2 != nil {
   368  		t.Errorf("should not have gotten leaderCh: %v", leaderCh2)
   369  	}
   370  
   371  	// Release the first lock
   372  	lock.Unlock()
   373  
   374  	// Attempt to lock should work
   375  	leaderCh2, err = lock2.Lock(nil)
   376  	if err != nil {
   377  		t.Fatalf("lock 2 lock: %v", err)
   378  	}
   379  	if leaderCh2 == nil {
   380  		t.Errorf("should get leaderCh")
   381  	}
   382  
   383  	// Check if it's fencing that we can register the lock
   384  	if fba2, ok := b2.(FencingHABackend); ok {
   385  		require.NoError(t, fba2.RegisterActiveNodeLock(lock))
   386  	}
   387  
   388  	// Check the value
   389  	held, val, err = lock2.Value()
   390  	if err != nil {
   391  		t.Fatalf("value: %v", err)
   392  	}
   393  	if !held {
   394  		t.Errorf("should still be held")
   395  	}
   396  	if val != "baz" {
   397  		t.Errorf("expected: baz, got: %v", val)
   398  	}
   399  
   400  	// Cleanup
   401  	lock2.Unlock()
   402  }
   403  
   404  func ExerciseTransactionalBackend(t testing.TB, b Backend) {
   405  	t.Helper()
   406  	ctx := context.Background()
   407  
   408  	tb, ok := b.(Transactional)
   409  	if !ok {
   410  		t.Fatal("Not a transactional backend")
   411  	}
   412  
   413  	txns := SetupTestingTransactions(t, b)
   414  
   415  	if err := tb.Transaction(ctx, txns); err != nil {
   416  		t.Fatal(err)
   417  	}
   418  
   419  	keys, err := b.List(ctx, "")
   420  	if err != nil {
   421  		t.Fatal(err)
   422  	}
   423  
   424  	expected := []string{"foo", "zip"}
   425  
   426  	sort.Strings(keys)
   427  	sort.Strings(expected)
   428  	if !reflect.DeepEqual(keys, expected) {
   429  		t.Fatalf("mismatch: expected\n%#v\ngot\n%#v\n", expected, keys)
   430  	}
   431  
   432  	entry, err := b.Get(ctx, "foo")
   433  	if err != nil {
   434  		t.Fatal(err)
   435  	}
   436  	if entry == nil {
   437  		t.Fatal("got nil entry")
   438  	}
   439  	if entry.Value == nil {
   440  		t.Fatal("got nil value")
   441  	}
   442  	if string(entry.Value) != "bar3" {
   443  		t.Fatal("updates did not apply correctly")
   444  	}
   445  
   446  	entry, err = b.Get(ctx, "zip")
   447  	if err != nil {
   448  		t.Fatal(err)
   449  	}
   450  	if entry == nil {
   451  		t.Fatal("got nil entry")
   452  	}
   453  	if entry.Value == nil {
   454  		t.Fatal("got nil value")
   455  	}
   456  	if string(entry.Value) != "zap3" {
   457  		t.Fatal("updates did not apply correctly")
   458  	}
   459  }
   460  
   461  func SetupTestingTransactions(t testing.TB, b Backend) []*TxnEntry {
   462  	t.Helper()
   463  	ctx := context.Background()
   464  
   465  	// Add a few keys so that we test rollback with deletion
   466  	if err := b.Put(ctx, &Entry{
   467  		Key:   "foo",
   468  		Value: []byte("bar"),
   469  	}); err != nil {
   470  		t.Fatal(err)
   471  	}
   472  	if err := b.Put(ctx, &Entry{
   473  		Key:   "zip",
   474  		Value: []byte("zap"),
   475  	}); err != nil {
   476  		t.Fatal(err)
   477  	}
   478  	if err := b.Put(ctx, &Entry{
   479  		Key: "deleteme",
   480  	}); err != nil {
   481  		t.Fatal(err)
   482  	}
   483  	if err := b.Put(ctx, &Entry{
   484  		Key: "deleteme2",
   485  	}); err != nil {
   486  		t.Fatal(err)
   487  	}
   488  
   489  	txns := []*TxnEntry{
   490  		{
   491  			Operation: PutOperation,
   492  			Entry: &Entry{
   493  				Key:   "foo",
   494  				Value: []byte("bar2"),
   495  			},
   496  		},
   497  		{
   498  			Operation: DeleteOperation,
   499  			Entry: &Entry{
   500  				Key: "deleteme",
   501  			},
   502  		},
   503  		{
   504  			Operation: PutOperation,
   505  			Entry: &Entry{
   506  				Key:   "foo",
   507  				Value: []byte("bar3"),
   508  			},
   509  		},
   510  		{
   511  			Operation: DeleteOperation,
   512  			Entry: &Entry{
   513  				Key: "deleteme2",
   514  			},
   515  		},
   516  		{
   517  			Operation: PutOperation,
   518  			Entry: &Entry{
   519  				Key:   "zip",
   520  				Value: []byte("zap3"),
   521  			},
   522  		},
   523  	}
   524  
   525  	return txns
   526  }
   527  
   528  // Several tests across packages have to test logic with a few variations of
   529  // transactional backends. Make some suitable for testing limits support that
   530  // can be re-used.
   531  
   532  type TestTransactionalNonLimitBackend struct{}
   533  
   534  var _ Transactional = (*TestTransactionalNonLimitBackend)(nil)
   535  
   536  func (b *TestTransactionalNonLimitBackend) Put(ctx context.Context, entry *Entry) error {
   537  	return nil
   538  }
   539  
   540  func (b *TestTransactionalNonLimitBackend) Get(ctx context.Context, key string) (*Entry, error) {
   541  	return nil, nil
   542  }
   543  
   544  func (b *TestTransactionalNonLimitBackend) Delete(ctx context.Context, key string) error {
   545  	return nil
   546  }
   547  
   548  func (b *TestTransactionalNonLimitBackend) List(ctx context.Context, prefix string) ([]string, error) {
   549  	return nil, nil
   550  }
   551  
   552  func (b *TestTransactionalNonLimitBackend) Transaction(ctx context.Context, txns []*TxnEntry) error {
   553  	return nil
   554  }
   555  
   556  type TestTransactionalLimitBackend struct {
   557  	TestTransactionalNonLimitBackend
   558  
   559  	MaxEntries, MaxSize int
   560  }
   561  
   562  var _ TransactionalLimits = (*TestTransactionalLimitBackend)(nil)
   563  
   564  func (b *TestTransactionalLimitBackend) TransactionLimits() (int, int) {
   565  	return b.MaxEntries, b.MaxSize
   566  }