code.vegaprotocol.io/vega@v0.79.0/wallet/api/admin_untaint_key_test.go (about)

     1  // Copyright (C) 2023 Gobalsky Labs Limited
     2  //
     3  // This program is free software: you can redistribute it and/or modify
     4  // it under the terms of the GNU Affero General Public License as
     5  // published by the Free Software Foundation, either version 3 of the
     6  // License, or (at your option) any later version.
     7  //
     8  // This program is distributed in the hope that it will be useful,
     9  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    10  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    11  // GNU Affero General Public License for more details.
    12  //
    13  // You should have received a copy of the GNU Affero General Public License
    14  // along with this program.  If not, see <http://www.gnu.org/licenses/>.
    15  
    16  package api_test
    17  
    18  import (
    19  	"context"
    20  	"fmt"
    21  	"testing"
    22  
    23  	"code.vegaprotocol.io/vega/libs/jsonrpc"
    24  	vgrand "code.vegaprotocol.io/vega/libs/rand"
    25  	"code.vegaprotocol.io/vega/wallet/api"
    26  	"code.vegaprotocol.io/vega/wallet/api/mocks"
    27  
    28  	"github.com/golang/mock/gomock"
    29  	"github.com/stretchr/testify/assert"
    30  	"github.com/stretchr/testify/require"
    31  )
    32  
    33  func TestAdminUntaintKey(t *testing.T) {
    34  	t.Run("Documentation matches the code", testAdminUntaintKeySchemaCorrect)
    35  	t.Run("Untainting a key with invalid params fails", testUntaintingKeyWithInvalidParamsFails)
    36  	t.Run("Untainting a key with valid params succeeds", testUntaintingKeyWithValidParamsSucceeds)
    37  	t.Run("Untainting a key on unknown wallet fails", testUntaintingKeyOnUnknownWalletFails)
    38  	t.Run("Untainting a key on unknown key fails", testUntaintingKeyOnUnknownKeyFails)
    39  	t.Run("Getting internal error during wallet verification doesn't remove the taint", testGettingInternalErrorDuringWalletVerificationDoesNotUntaintKey)
    40  	t.Run("Getting internal error during wallet retrieval doesn't remove the taint", testGettingInternalErrorDuringWalletRetrievalDoesNotUntaintKey)
    41  	t.Run("Getting internal error during wallet saving doesn't remove the taint", testGettingInternalErrorDuringWalletSavingDoesNotUntaintKey)
    42  }
    43  
    44  func testAdminUntaintKeySchemaCorrect(t *testing.T) {
    45  	assertEqualSchema(t, "admin.untaint_key", api.AdminUntaintKeyParams{}, nil)
    46  }
    47  
    48  func testUntaintingKeyWithInvalidParamsFails(t *testing.T) {
    49  	tcs := []struct {
    50  		name          string
    51  		params        interface{}
    52  		expectedError error
    53  	}{
    54  		{
    55  			name:          "with nil params",
    56  			params:        nil,
    57  			expectedError: api.ErrParamsRequired,
    58  		}, {
    59  			name:          "with wrong type of params",
    60  			params:        "test",
    61  			expectedError: api.ErrParamsDoNotMatch,
    62  		}, {
    63  			name: "with empty name",
    64  			params: api.AdminUntaintKeyParams{
    65  				Wallet:    "",
    66  				PublicKey: "b5fd9d3c4ad553cb3196303b6e6df7f484cf7f5331a572a45031239fd71ad8a0",
    67  			},
    68  			expectedError: api.ErrWalletIsRequired,
    69  		}, {
    70  			name: "with empty public key",
    71  			params: api.AdminUntaintKeyParams{
    72  				PublicKey: "",
    73  				Wallet:    vgrand.RandomStr(5),
    74  			},
    75  			expectedError: api.ErrPublicKeyIsRequired,
    76  		},
    77  	}
    78  
    79  	for _, tc := range tcs {
    80  		t.Run(tc.name, func(tt *testing.T) {
    81  			// given
    82  			ctx := context.Background()
    83  
    84  			// setup
    85  			handler := newUntaintKeyHandler(tt)
    86  
    87  			// when
    88  			errorDetails := handler.handle(t, ctx, tc.params)
    89  
    90  			// the
    91  			assertInvalidParams(tt, errorDetails, tc.expectedError)
    92  		})
    93  	}
    94  }
    95  
    96  func testUntaintingKeyWithValidParamsSucceeds(t *testing.T) {
    97  	// given
    98  	ctx := context.Background()
    99  	expectedWallet, kp := walletWithKey(t)
   100  	if err := expectedWallet.TaintKey(kp.PublicKey()); err != nil {
   101  		t.Fatalf("could not taint the key for test: %v", err)
   102  	}
   103  
   104  	// setup
   105  	handler := newUntaintKeyHandler(t)
   106  	// -- expected calls
   107  	handler.walletStore.EXPECT().WalletExists(ctx, expectedWallet.Name()).Times(1).Return(true, nil)
   108  	handler.walletStore.EXPECT().IsWalletAlreadyUnlocked(ctx, expectedWallet.Name()).Times(1).Return(true, nil)
   109  	handler.walletStore.EXPECT().GetWallet(ctx, expectedWallet.Name()).Times(1).Return(expectedWallet, nil)
   110  	handler.walletStore.EXPECT().UpdateWallet(ctx, expectedWallet).Times(1).Return(nil)
   111  
   112  	// when
   113  	errorDetails := handler.handle(t, ctx, api.AdminUntaintKeyParams{
   114  		Wallet:    expectedWallet.Name(),
   115  		PublicKey: kp.PublicKey(),
   116  	})
   117  
   118  	// then
   119  	require.Nil(t, errorDetails)
   120  	require.False(t, expectedWallet.ListKeyPairs()[0].IsTainted())
   121  }
   122  
   123  func testUntaintingKeyOnUnknownWalletFails(t *testing.T) {
   124  	// given
   125  	ctx := context.Background()
   126  	name := vgrand.RandomStr(5)
   127  
   128  	// setup
   129  	handler := newUntaintKeyHandler(t)
   130  	// -- expected calls
   131  	handler.walletStore.EXPECT().WalletExists(ctx, name).Times(1).Return(false, nil)
   132  
   133  	// when
   134  	errorDetails := handler.handle(t, ctx, api.AdminUntaintKeyParams{
   135  		Wallet:    name,
   136  		PublicKey: vgrand.RandomStr(5),
   137  	})
   138  
   139  	// then
   140  	require.NotNil(t, errorDetails)
   141  	assertInvalidParams(t, errorDetails, api.ErrWalletDoesNotExist)
   142  }
   143  
   144  func testUntaintingKeyOnUnknownKeyFails(t *testing.T) {
   145  	// given
   146  	ctx := context.Background()
   147  	expectedWallet, _ := walletWithKey(t)
   148  
   149  	// setup
   150  	handler := newUntaintKeyHandler(t)
   151  	// -- expected calls
   152  	handler.walletStore.EXPECT().WalletExists(ctx, expectedWallet.Name()).Times(1).Return(true, nil)
   153  	handler.walletStore.EXPECT().IsWalletAlreadyUnlocked(ctx, expectedWallet.Name()).Times(1).Return(true, nil)
   154  	handler.walletStore.EXPECT().GetWallet(ctx, expectedWallet.Name()).Times(1).Return(expectedWallet, nil)
   155  
   156  	// when
   157  	errorDetails := handler.handle(t, ctx, api.AdminUntaintKeyParams{
   158  		Wallet:    expectedWallet.Name(),
   159  		PublicKey: vgrand.RandomStr(5),
   160  	})
   161  
   162  	// then
   163  	require.NotNil(t, errorDetails)
   164  	assertInvalidParams(t, errorDetails, api.ErrPublicKeyDoesNotExist)
   165  }
   166  
   167  func testGettingInternalErrorDuringWalletVerificationDoesNotUntaintKey(t *testing.T) {
   168  	// given
   169  	ctx := context.Background()
   170  	expectedWallet, kp := walletWithKey(t)
   171  
   172  	// setup
   173  	handler := newUntaintKeyHandler(t)
   174  	// -- expected calls
   175  	handler.walletStore.EXPECT().WalletExists(ctx, expectedWallet.Name()).Times(1).Return(false, assert.AnError)
   176  
   177  	// when
   178  	errorDetails := handler.handle(t, ctx, api.AdminUntaintKeyParams{
   179  		Wallet:    expectedWallet.Name(),
   180  		PublicKey: kp.PublicKey(),
   181  	})
   182  
   183  	// then
   184  	require.NotNil(t, errorDetails)
   185  	assertInternalError(t, errorDetails, fmt.Errorf("could not verify the wallet exists: %w", assert.AnError))
   186  }
   187  
   188  func testGettingInternalErrorDuringWalletRetrievalDoesNotUntaintKey(t *testing.T) {
   189  	// given
   190  	ctx := context.Background()
   191  	expectedWallet, kp := walletWithKey(t)
   192  
   193  	// setup
   194  	handler := newUntaintKeyHandler(t)
   195  	// -- expected calls
   196  	handler.walletStore.EXPECT().WalletExists(ctx, expectedWallet.Name()).Times(1).Return(true, nil)
   197  	handler.walletStore.EXPECT().IsWalletAlreadyUnlocked(ctx, expectedWallet.Name()).Times(1).Return(true, nil)
   198  	handler.walletStore.EXPECT().GetWallet(ctx, expectedWallet.Name()).Times(1).Return(nil, assert.AnError)
   199  
   200  	// when
   201  	errorDetails := handler.handle(t, ctx, api.AdminUntaintKeyParams{
   202  		Wallet:    expectedWallet.Name(),
   203  		PublicKey: kp.PublicKey(),
   204  	})
   205  
   206  	// then
   207  	require.NotNil(t, errorDetails)
   208  	assertInternalError(t, errorDetails, fmt.Errorf("could not retrieve the wallet: %w", assert.AnError))
   209  }
   210  
   211  func testGettingInternalErrorDuringWalletSavingDoesNotUntaintKey(t *testing.T) {
   212  	// given
   213  	ctx := context.Background()
   214  	expectedWallet, kp := walletWithKey(t)
   215  	if err := expectedWallet.TaintKey(kp.PublicKey()); err != nil {
   216  		t.Fatalf("could not taint the key for test: %v", err)
   217  	}
   218  
   219  	// setup
   220  	handler := newUntaintKeyHandler(t)
   221  	// -- expected calls
   222  	handler.walletStore.EXPECT().WalletExists(ctx, expectedWallet.Name()).Times(1).Return(true, nil)
   223  	handler.walletStore.EXPECT().IsWalletAlreadyUnlocked(ctx, expectedWallet.Name()).Times(1).Return(true, nil)
   224  	handler.walletStore.EXPECT().GetWallet(ctx, expectedWallet.Name()).Times(1).Return(expectedWallet, nil)
   225  	handler.walletStore.EXPECT().UpdateWallet(ctx, gomock.Any()).Times(1).Return(assert.AnError)
   226  
   227  	// when
   228  	errorDetails := handler.handle(t, ctx, api.AdminUntaintKeyParams{
   229  		Wallet:    expectedWallet.Name(),
   230  		PublicKey: kp.PublicKey(),
   231  	})
   232  
   233  	// then
   234  	require.NotNil(t, errorDetails)
   235  	assertInternalError(t, errorDetails, fmt.Errorf("could not save the wallet: %w", assert.AnError))
   236  }
   237  
   238  type untaintKeyHandler struct {
   239  	*api.AdminUntaintKey
   240  	ctrl        *gomock.Controller
   241  	walletStore *mocks.MockWalletStore
   242  }
   243  
   244  func (h *untaintKeyHandler) handle(t *testing.T, ctx context.Context, params jsonrpc.Params) *jsonrpc.ErrorDetails {
   245  	t.Helper()
   246  
   247  	result, err := h.Handle(ctx, params)
   248  	assert.Nil(t, result)
   249  	return err
   250  }
   251  
   252  func newUntaintKeyHandler(t *testing.T) *untaintKeyHandler {
   253  	t.Helper()
   254  
   255  	ctrl := gomock.NewController(t)
   256  	walletStore := mocks.NewMockWalletStore(ctrl)
   257  
   258  	return &untaintKeyHandler{
   259  		AdminUntaintKey: api.NewAdminUntaintKey(walletStore),
   260  		ctrl:            ctrl,
   261  		walletStore:     walletStore,
   262  	}
   263  }