github.com/kbehouse/nsc@v0.0.6/cmd/keys_test.go (about)

     1  /*
     2   * Copyright 2018-2019 The NATS Authors
     3   * Licensed under the Apache License, Version 2.0 (the "License");
     4   * you may not use this file except in compliance with the License.
     5   * You may obtain a copy of the License at
     6   *
     7   * http://www.apache.org/licenses/LICENSE-2.0
     8   *
     9   * Unless required by applicable law or agreed to in writing, software
    10   * distributed under the License is distributed on an "AS IS" BASIS,
    11   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12   * See the License for the specific language governing permissions and
    13   * limitations under the License.
    14   */
    15  
    16  package cmd
    17  
    18  import (
    19  	"fmt"
    20  	"io/ioutil"
    21  	"os"
    22  	"path/filepath"
    23  	"testing"
    24  
    25  	"github.com/kbehouse/nsc/cmd/store"
    26  	"github.com/nats-io/nkeys"
    27  	"github.com/stretchr/testify/require"
    28  )
    29  
    30  func storeOldCreds(ts *TestStore, operator string, account string, user string, data []byte) error {
    31  	ks := filepath.Join(ts.Dir, "keys")
    32  	target := filepath.Join(ks, operator, "accounts", account, "users", fmt.Sprintf("%s.creds", user))
    33  	return ioutil.WriteFile(target, []byte(user), 0700)
    34  
    35  }
    36  
    37  func storeOldKey(ts *TestStore, operator string, account string, user string, seed []byte) error {
    38  	// old key layout was:
    39  	// <op>/<op>.nk
    40  	// <op>/accounts/<actname>/<actname>.nk
    41  	// <op>/accounts/<actname>/users/<un>.creds
    42  	// <op>/accounts/<actname>/users/<un>.nk
    43  	// new key layout is:
    44  	// keys/<op>/<first letter pk>/<second and third letters pk>/<pk>.nk
    45  	// creds/<op>/<actname>/<un>.creds
    46  	kp, err := store.ExtractSeed(string(seed))
    47  	if err != nil {
    48  		return err
    49  	}
    50  	prefix, err := store.KeyType(kp)
    51  	if err != nil {
    52  		return err
    53  	}
    54  	ks := filepath.Join(ts.Dir, "keys")
    55  	var target string
    56  	switch prefix {
    57  	case nkeys.PrefixByteOperator:
    58  		target = filepath.Join(ks, operator, fmt.Sprintf("%s.nk", operator))
    59  	case nkeys.PrefixByteAccount:
    60  		target = filepath.Join(ks, operator, "accounts", account, fmt.Sprintf("%s.nk", account))
    61  	case nkeys.PrefixByteUser:
    62  		target = filepath.Join(ks, operator, "accounts", account, "users", fmt.Sprintf("%s.nk", user))
    63  	}
    64  
    65  	if err := os.MkdirAll(filepath.Dir(target), 0700); err != nil {
    66  		return err
    67  	}
    68  
    69  	return ioutil.WriteFile(target, seed, 0700)
    70  }
    71  
    72  func Test_HasOldStructure(t *testing.T) {
    73  	ts := NewEmptyStore(t)
    74  	defer ts.Done(t)
    75  
    76  	ks := filepath.Join(ts.Dir, "keys")
    77  
    78  	oseed, _, _ := CreateOperatorKey(t)
    79  	require.NoError(t, storeOldKey(ts, "O", "", "", oseed))
    80  	require.FileExists(t, filepath.Join(ks, "O", "O.nk"))
    81  
    82  	aseed, _, _ := CreateAccountKey(t)
    83  	require.NoError(t, storeOldKey(ts, "O", "A", "", aseed))
    84  	require.FileExists(t, filepath.Join(ks, "O", "accounts", "A", "A.nk"))
    85  
    86  	useed, _, _ := CreateUserKey(t)
    87  	require.NoError(t, storeOldKey(ts, "O", "A", "U", useed))
    88  	require.FileExists(t, filepath.Join(ks, "O", "accounts", "A", "users", "U.nk"))
    89  
    90  	err := storeOldCreds(ts, "O", "A", "U", []byte("user"))
    91  	require.NoError(t, err)
    92  
    93  	isOld, err := store.IsOldKeyRing(store.GetKeysDir())
    94  	require.NoError(t, err)
    95  	require.True(t, isOld)
    96  }
    97  
    98  func Test_MigrateKeys(t *testing.T) {
    99  	ts := NewEmptyStore(t)
   100  	defer ts.Done(t)
   101  
   102  	ks := filepath.Join(ts.Dir, "keys")
   103  
   104  	oseed, opk, _ := CreateOperatorKey(t)
   105  	require.NoError(t, storeOldKey(ts, "O", "", "", oseed))
   106  	require.FileExists(t, filepath.Join(ks, "O", "O.nk"))
   107  
   108  	aseed, apk, _ := CreateAccountKey(t)
   109  	require.NoError(t, storeOldKey(ts, "O", "A", "", aseed))
   110  	require.FileExists(t, filepath.Join(ks, "O", "accounts", "A", "A.nk"))
   111  
   112  	useed, upk, _ := CreateUserKey(t)
   113  	require.NoError(t, storeOldKey(ts, "O", "A", "U", useed))
   114  	require.FileExists(t, filepath.Join(ks, "O", "accounts", "A", "users", "U.nk"))
   115  
   116  	err := storeOldCreds(ts, "O", "A", "U", []byte("user"))
   117  	require.NoError(t, err)
   118  
   119  	needsUpdate, err := store.KeysNeedMigration()
   120  	require.NoError(t, err)
   121  	require.True(t, needsUpdate)
   122  
   123  	old, err := store.Migrate()
   124  	require.NoError(t, err)
   125  	require.DirExists(t, old)
   126  
   127  	// directory for keystore has a "keys" and "creds"
   128  	keysDir := filepath.Join(ks, "keys")
   129  	require.FileExists(t, filepath.Join(keysDir, "O", opk[1:3], fmt.Sprintf("%s.nk", opk)))
   130  	require.FileExists(t, filepath.Join(keysDir, "A", apk[1:3], fmt.Sprintf("%s.nk", apk)))
   131  	require.FileExists(t, filepath.Join(keysDir, "U", upk[1:3], fmt.Sprintf("%s.nk", upk)))
   132  
   133  	credsDir := filepath.Join(ks, "creds")
   134  	cf := filepath.Join(credsDir, "O", "A", "U.creds")
   135  	require.FileExists(t, cf)
   136  
   137  	for _, pk := range []string{opk, apk, upk} {
   138  		kp, err := ts.KeyStore.GetKeyPair(pk)
   139  		require.NoError(t, err)
   140  		require.NotNil(t, kp)
   141  	}
   142  }