gitlab.com/SkynetLabs/skyd@v1.6.9/cmd/skyc/skykeycmd_test.go (about)

     1  package main
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  	"testing"
     7  
     8  	"gitlab.com/SkynetLabs/skyd/node/api/client"
     9  	"gitlab.com/SkynetLabs/skyd/skykey"
    10  )
    11  
    12  const testSkykeyString string = "skykey:Aa71WcCoKFwVGAVotJh3USAslb8dotVJp2VZRRSAG2QhYRbuTbQhjDolIJ1nOlQ-rWYK29_1xee5?name=test_key1"
    13  
    14  // TestSkykeyCommands tests the basic functionality of the siac skykey commands
    15  // interface. More detailed testing of the skykey manager is done in the skykey
    16  // package.
    17  func TestSkykeyCommands(t *testing.T) {
    18  	if testing.Short() {
    19  		t.SkipNow()
    20  	}
    21  
    22  	groupDir := skycTestDir(t.Name())
    23  
    24  	// Define subtests
    25  	subTests := []subTest{
    26  		{name: "TestDuplicateSkykeyAdd", test: testDuplicateSkykeyAdd},
    27  		{name: "TestChangeKeyEntropyKeepName", test: testChangeKeyEntropyKeepName},
    28  		{name: "TestAddKeyTwice", test: testAddKeyTwice},
    29  		{name: "TestDelete", test: testDeleteKey},
    30  		{name: "TestInvalidSkykeyType", test: testInvalidSkykeyType},
    31  		{name: "TestSkykeyGet", test: testSkykeyGet},
    32  		{name: "TestSkykeyGetUsingNameAndID", test: testSkykeyGetUsingNameAndID},
    33  		{name: "TestSkykeyGetUsingNoNameAndNoID", test: testSkykeyGetUsingNoNameAndNoID},
    34  		{name: "TestSkykeyListKeys", test: testSkykeyListKeys},
    35  		{name: "TestSkykeyListKeysDoesntShowPrivateKeys", test: testSkykeyListKeysDoesntShowPrivateKeys},
    36  		{name: "TestSkykeyListKeysAdditionalKeys", test: testSkykeyListKeysAdditionalKeys},
    37  		{name: "TestSkykeyListKeysAdditionalKeysDoesntShowPrivateKeys", test: testSkykeyListKeysAdditionalKeysDoesntShowPrivateKeys},
    38  	}
    39  
    40  	// Run tests
    41  	if err := runSubTests(t, groupDir, subTests); err != nil {
    42  		t.Fatal(err)
    43  	}
    44  }
    45  
    46  // testDuplicateSkykeyAdd tests that adding with duplicate Skykey will return
    47  // duplicate name error.
    48  func testDuplicateSkykeyAdd(t *testing.T, c client.Client) {
    49  	err := skykeyAdd(c, testSkykeyString)
    50  	if err != nil {
    51  		t.Fatal(err)
    52  	}
    53  
    54  	err = skykeyAdd(c, testSkykeyString)
    55  	if !strings.Contains(err.Error(), skykey.ErrSkykeyWithIDAlreadyExists.Error()) {
    56  		t.Fatal("Expected duplicate name error but got", err)
    57  	}
    58  }
    59  
    60  // testChangeKeyEntropyKeepName tests that adding with changed entropy but the
    61  // same Skykey will return duplicate name error.
    62  func testChangeKeyEntropyKeepName(t *testing.T, c client.Client) {
    63  	// Change the key entropy, but keep the same name.
    64  	var sk skykey.Skykey
    65  	err := sk.FromString(testSkykeyString)
    66  	if err != nil {
    67  		t.Fatal(err)
    68  	}
    69  	sk.Entropy[0] ^= 1 // flip the first byte.
    70  
    71  	skString, err := sk.ToString()
    72  	if err != nil {
    73  		t.Fatal(err)
    74  	}
    75  
    76  	// This should return a duplicate name error.
    77  	err = skykeyAdd(c, skString)
    78  	if !strings.Contains(err.Error(), skykey.ErrSkykeyWithNameAlreadyExists.Error()) {
    79  		t.Fatal("Expected duplicate name error but got", err)
    80  	}
    81  }
    82  
    83  // testAddKeyTwice tests that creating a Skykey with the same key name twice
    84  // returns duplicate name error.
    85  func testAddKeyTwice(t *testing.T, c client.Client) {
    86  	// Check that adding same key twice returns an error.
    87  	keyName := "createkey1"
    88  	_, err := skykeyCreate(c, keyName, skykey.TypePublicID.ToString())
    89  	if err != nil {
    90  		t.Fatal(err)
    91  	}
    92  	_, err = skykeyCreate(c, keyName, skykey.TypePublicID.ToString())
    93  	if !strings.Contains(err.Error(), skykey.ErrSkykeyWithNameAlreadyExists.Error()) {
    94  		t.Fatal("Expected error when creating key with same name")
    95  	}
    96  }
    97  
    98  // testDeleteKey tests that deleting a Skykey by name or id actually deletes
    99  // the key
   100  func testDeleteKey(t *testing.T, c client.Client) {
   101  	// Create a key.
   102  	keyName := "keyToDeleteByName"
   103  	_, err := skykeyCreate(c, keyName, skykey.TypePublicID.ToString())
   104  	if err != nil {
   105  		t.Fatal(err)
   106  	}
   107  
   108  	// Get the Key
   109  	sk, err := c.SkykeyGetByName(keyName)
   110  	if err != nil {
   111  		t.Fatal(err)
   112  	}
   113  	if sk.Name != keyName {
   114  		t.Fatalf("Expected Skykey name %v but got %v", keyName, sk.Name)
   115  	}
   116  
   117  	// Delete key by name
   118  	err = c.SkykeyDeleteByNamePost(keyName)
   119  	if err != nil {
   120  		t.Fatal(err)
   121  	}
   122  
   123  	// Try and get the key again
   124  	_, err = c.SkykeyGetByName(keyName)
   125  	if err == nil || !strings.Contains(err.Error(), skykey.ErrNoSkykeysWithThatName.Error()) {
   126  		t.Fatalf("Expected Error to contain %v and got %v", skykey.ErrNoSkykeysWithThatName, err)
   127  	}
   128  
   129  	// Create key again
   130  	_, err = skykeyCreate(c, keyName, skykey.TypePublicID.ToString())
   131  	if err != nil {
   132  		t.Fatal(err)
   133  	}
   134  
   135  	// Get ID
   136  	sk, err = c.SkykeyGetByName(keyName)
   137  	if err != nil {
   138  		t.Fatal(err)
   139  	}
   140  
   141  	// Delete key by ID
   142  	err = c.SkykeyDeleteByIDPost(sk.ID())
   143  	if err != nil {
   144  		t.Fatal(err)
   145  	}
   146  
   147  	// Try and get the key again
   148  	_, err = c.SkykeyGetByName(keyName)
   149  	if err == nil || !strings.Contains(err.Error(), skykey.ErrNoSkykeysWithThatName.Error()) {
   150  		t.Fatalf("Expected Error to contain %v and got %v", skykey.ErrNoSkykeysWithThatName, err)
   151  	}
   152  }
   153  
   154  // testInvalidSkykeyType tests that invalid cipher types are caught.
   155  func testInvalidSkykeyType(t *testing.T, c client.Client) {
   156  	// Verify invalid type returns error
   157  	_, err := skykeyCreate(c, "createkey2", skykey.TypeInvalid.ToString())
   158  	if !strings.Contains(err.Error(), skykey.ErrInvalidSkykeyType.Error()) {
   159  		t.Fatal("Expected error when creating key with invalid skykeytpe", err)
   160  	}
   161  
   162  	// Submitting a blank skykey type should succeed and default to private
   163  	keyName := "blankType"
   164  	_, err = skykeyCreate(c, keyName, "")
   165  	if err != nil {
   166  		t.Fatal(err)
   167  	}
   168  	sk, err := c.SkykeyGetByName(keyName)
   169  	if err != nil {
   170  		t.Fatal(err)
   171  	}
   172  	if sk.Type != skykey.TypePrivateID {
   173  		t.Fatal("Skykey type expected to be private")
   174  	}
   175  	// Delete Key to not impact future sub tests
   176  	err = c.SkykeyDeleteByNamePost(keyName)
   177  	if err != nil {
   178  		t.Fatal(err)
   179  	}
   180  	// Verify a random type gives an error
   181  	_, err = skykeyCreate(c, "", "not a type")
   182  	if !strings.Contains(err.Error(), skykey.ErrInvalidSkykeyType.Error()) {
   183  		t.Fatal("Expected error when creating key with invalid skykeytpe", err)
   184  	}
   185  }
   186  
   187  // testSkykeyGet tests skykeyGet with known key should not return any errors.
   188  func testSkykeyGet(t *testing.T, c client.Client) {
   189  	keyName := "createkey testSkykeyGet"
   190  	newSkykey, err := skykeyCreate(c, keyName, skykey.TypePublicID.ToString())
   191  	if err != nil {
   192  		t.Fatal(err)
   193  	}
   194  
   195  	// Test skykeyGet
   196  	// known key should have no errors.
   197  	getKeyStr, err := skykeyGet(c, keyName, "")
   198  	if err != nil {
   199  		t.Fatal(err)
   200  	}
   201  	if getKeyStr != newSkykey {
   202  		t.Fatal("Expected keys to match")
   203  	}
   204  }
   205  
   206  // testSkykeyGetUsingNameAndID tests using both name and id params should return an
   207  // error.
   208  func testSkykeyGetUsingNameAndID(t *testing.T, c client.Client) {
   209  	_, err := skykeyGet(c, "name", "id")
   210  	if err == nil {
   211  		t.Fatal("Expected error when using both name and id")
   212  	}
   213  }
   214  
   215  // testSkykeyGetUsingNoNameAndNoID test using neither name or id param should return an
   216  // error.
   217  func testSkykeyGetUsingNoNameAndNoID(t *testing.T, c client.Client) {
   218  	_, err := skykeyGet(c, "", "")
   219  	if err == nil {
   220  		t.Fatal("Expected error when using neither name or id params")
   221  	}
   222  }
   223  
   224  // testSkykeyListKeys tests that skykeyListKeys shows key names, ids and keys
   225  func testSkykeyListKeys(t *testing.T, c client.Client) {
   226  	nKeys := 3
   227  	nExtraLines := 3
   228  	keyStrings := make([]string, nKeys)
   229  	keyNames := make([]string, nKeys)
   230  	keyIDs := make([]string, nKeys)
   231  
   232  	initSkykeyData(t, c, keyStrings, keyNames, keyIDs)
   233  
   234  	keyListString, err := skykeyListKeys(c, true)
   235  	if err != nil {
   236  		t.Fatal(err)
   237  	}
   238  	for i := 0; i < nKeys; i++ {
   239  		if !strings.Contains(keyListString, keyNames[i]) {
   240  			t.Log(keyListString)
   241  			t.Fatal("Missing key name!", i)
   242  		}
   243  		if !strings.Contains(keyListString, keyIDs[i]) {
   244  			t.Log(keyListString)
   245  			t.Fatal("Missing id!", i)
   246  		}
   247  		if !strings.Contains(keyListString, keyStrings[i]) {
   248  			t.Log(keyListString)
   249  			t.Fatal("Missing key!", i)
   250  		}
   251  	}
   252  	keyList := strings.Split(keyListString, "\n")
   253  	if len(keyList) != nKeys+nExtraLines {
   254  		t.Log(keyListString)
   255  		t.Fatalf("Unexpected number of lines/keys %d, Expected %d", len(keyList), nKeys+nExtraLines)
   256  	}
   257  }
   258  
   259  // testKskykeyListKeysDoesntShowPrivateKeys tests that skykeyListKeys shows key names, ids and
   260  // doesn't show private keys
   261  func testSkykeyListKeysDoesntShowPrivateKeys(t *testing.T, c client.Client) {
   262  	nKeys := 3
   263  	nExtraLines := 3
   264  	keyStrings := make([]string, nKeys)
   265  	keyNames := make([]string, nKeys)
   266  	keyIDs := make([]string, nKeys)
   267  
   268  	initSkykeyData(t, c, keyStrings, keyNames, keyIDs)
   269  
   270  	keyListString, err := skykeyListKeys(c, false)
   271  	if err != nil {
   272  		t.Fatal(err)
   273  	}
   274  	for i := 0; i < nKeys; i++ {
   275  		if !strings.Contains(keyListString, keyNames[i]) {
   276  			t.Log(keyListString)
   277  			t.Fatal("Missing key name!", i)
   278  		}
   279  		if !strings.Contains(keyListString, keyIDs[i]) {
   280  			t.Log(keyListString)
   281  			t.Fatal("Missing id!", i)
   282  		}
   283  		if strings.Contains(keyListString, keyStrings[i]) {
   284  			t.Log(keyListString)
   285  			t.Fatal("Found key!", i)
   286  		}
   287  	}
   288  	keyList := strings.Split(keyListString, "\n")
   289  	if len(keyList) != nKeys+nExtraLines {
   290  		t.Fatal("Unexpected number of lines/keys", len(keyList))
   291  	}
   292  }
   293  
   294  // testSkykeyListKeysAdditionalKeys tests that after creating additional keys,
   295  // skykeyListKeys shows all key names, ids and keys
   296  func testSkykeyListKeysAdditionalKeys(t *testing.T, c client.Client) {
   297  	nExtraKeys := 10
   298  	nKeys := 3 + nExtraKeys
   299  	keyStrings := make([]string, nKeys)
   300  	keyNames := make([]string, nKeys)
   301  	keyIDs := make([]string, nKeys)
   302  
   303  	initSkykeyData(t, c, keyStrings, keyNames, keyIDs)
   304  
   305  	// Count the number of public/private keys we create.
   306  	expectedNumPublic := nKeys - nExtraKeys // initial keys are public
   307  	expectedNumPrivate := 0
   308  
   309  	// Add extra keys
   310  	for i := 0; i < nExtraKeys; i++ {
   311  		skykeyType := skykey.TypePrivateID
   312  		if i%2 == 0 {
   313  			skykeyType = skykey.TypePublicID
   314  			expectedNumPublic += 1
   315  		} else {
   316  			expectedNumPrivate += 1
   317  		}
   318  
   319  		nextName := fmt.Sprintf("extrakey-%d", i)
   320  		keyNames = append(keyNames, nextName)
   321  		nextSkStr, err := skykeyCreate(c, nextName, skykeyType.ToString())
   322  		if err != nil {
   323  			t.Fatal(err)
   324  		}
   325  		var nextSkykey skykey.Skykey
   326  		err = nextSkykey.FromString(nextSkStr)
   327  		if err != nil {
   328  			t.Fatal(err)
   329  		}
   330  		keyIDs = append(keyIDs, nextSkykey.ID().ToString())
   331  		keyStrings = append(keyStrings, nextSkStr)
   332  	}
   333  
   334  	// Check that all the key names and key data is there.
   335  	keyListString, err := skykeyListKeys(c, true)
   336  	if err != nil {
   337  		t.Fatal(err)
   338  	}
   339  	for i := 0; i < nKeys; i++ {
   340  		if !strings.Contains(keyListString, keyNames[i]) {
   341  			t.Log(keyListString)
   342  			t.Fatal("Missing key name!", i)
   343  		}
   344  		if !strings.Contains(keyListString, keyIDs[i]) {
   345  			t.Log(keyListString)
   346  			t.Fatal("Missing id!", i)
   347  		}
   348  		if !strings.Contains(keyListString, keyStrings[i]) {
   349  			t.Log(keyListString)
   350  			t.Fatal("Missing key!", i)
   351  		}
   352  	}
   353  
   354  	// Check that the expected number of public/private keys were created.
   355  	numPublic := strings.Count(keyListString, skykey.TypePublicID.ToString())
   356  	numPrivate := strings.Count(keyListString, skykey.TypePrivateID.ToString())
   357  	if numPublic != expectedNumPublic {
   358  		t.Log(keyListString)
   359  		t.Fatalf("Expected %d %s keys got %d instead", numPublic, skykey.TypePublicID.ToString(), expectedNumPublic)
   360  	}
   361  	if numPrivate != expectedNumPrivate {
   362  		t.Log(keyListString)
   363  		t.Fatalf("Expected %d %s keys got %d instead", numPrivate, skykey.TypePrivateID.ToString(), expectedNumPrivate)
   364  	}
   365  }
   366  
   367  // testSkykeyListKeysAdditionalKeysDoesntShowPrivateKeys tests that after creating additional keys,
   368  // skykeyListKeys shows all key names, ids and doesn't show private keys
   369  func testSkykeyListKeysAdditionalKeysDoesntShowPrivateKeys(t *testing.T, c client.Client) {
   370  	nExtraKeys := 10
   371  	nPrevKeys := 3
   372  	nKeys := nPrevKeys + nExtraKeys
   373  	nExtraLines := 3
   374  	keyStrings := make([]string, nPrevKeys)
   375  	keyNames := make([]string, nPrevKeys)
   376  	keyIDs := make([]string, nPrevKeys)
   377  
   378  	initSkykeyData(t, c, keyStrings, keyNames, keyIDs)
   379  
   380  	// Get extra keys
   381  	for i := 0; i < nExtraKeys; i++ {
   382  		nextName := fmt.Sprintf("extrakey-%d", i)
   383  		keyNames = append(keyNames, nextName)
   384  		nextSkStr, err := skykeyGet(c, nextName, "")
   385  		if err != nil {
   386  			t.Fatal(err)
   387  		}
   388  		var nextSkykey skykey.Skykey
   389  		err = nextSkykey.FromString(nextSkStr)
   390  		if err != nil {
   391  			t.Fatal(err)
   392  		}
   393  		keyIDs = append(keyIDs, nextSkykey.ID().ToString())
   394  		keyStrings = append(keyStrings, nextSkStr)
   395  	}
   396  
   397  	// Make sure key data isn't shown but otherwise the same checks pass.
   398  	keyListString, err := skykeyListKeys(c, false)
   399  	if err != nil {
   400  		t.Fatal(err)
   401  	}
   402  	for i := 0; i < nKeys; i++ {
   403  		if !strings.Contains(keyListString, keyNames[i]) {
   404  			t.Log(keyListString)
   405  			t.Fatal("Missing key name!", i)
   406  		}
   407  		if !strings.Contains(keyListString, keyIDs[i]) {
   408  			t.Log(keyListString)
   409  			t.Fatal("Missing id!", i)
   410  		}
   411  		if strings.Contains(keyListString, keyStrings[i]) {
   412  			t.Log(keyListString)
   413  			t.Fatal("Found key!", i)
   414  		}
   415  	}
   416  	keyList := strings.Split(keyListString, "\n")
   417  	if len(keyList) != nKeys+nExtraLines {
   418  		t.Fatal("Unexpected number of lines/keys", len(keyList))
   419  	}
   420  }
   421  
   422  // initSkykeyData initializes keyStrings, keyNames, keyIDS slices with existing Skykey data
   423  func initSkykeyData(t *testing.T, c client.Client, keyStrings, keyNames, keyIDs []string) {
   424  	keyName1 := "createkey1"
   425  	keyName2 := "createkey testSkykeyGet"
   426  
   427  	getKeyStr1, err := skykeyGet(c, keyName1, "")
   428  	if err != nil {
   429  		t.Fatal(err)
   430  	}
   431  
   432  	getKeyStr2, err := skykeyGet(c, keyName2, "")
   433  	if err != nil {
   434  		t.Fatal(err)
   435  	}
   436  
   437  	keyNames[0] = "key1"
   438  	keyNames[1] = keyName1
   439  	keyNames[2] = keyName2
   440  	keyStrings[0] = testSkykeyString
   441  	keyStrings[1] = getKeyStr1
   442  	keyStrings[2] = getKeyStr2
   443  
   444  	var sk skykey.Skykey
   445  	err = sk.FromString(testSkykeyString)
   446  	if err != nil {
   447  		t.Fatal(err)
   448  	}
   449  	keyIDs[0] = sk.ID().ToString()
   450  
   451  	err = sk.FromString(getKeyStr1)
   452  	if err != nil {
   453  		t.Fatal(err)
   454  	}
   455  	keyIDs[1] = sk.ID().ToString()
   456  
   457  	err = sk.FromString(getKeyStr2)
   458  	if err != nil {
   459  		t.Fatal(err)
   460  	}
   461  	keyIDs[2] = sk.ID().ToString()
   462  }