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 }