github.com/nats-io/nsc@v0.0.0-20221206222106-35db9400b257/cmd/listkeys.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 "errors" 20 "fmt" 21 "os" 22 23 "github.com/nats-io/nkeys" 24 "github.com/nats-io/nsc/cmd/store" 25 "github.com/spf13/cobra" 26 "github.com/xlab/tablewriter" 27 ) 28 29 func createListKeysCmd() *cobra.Command { 30 var params ListKeysParams 31 cmd := &cobra.Command{ 32 Use: "keys", 33 Short: "List operator, account and user keys in the current operator and account context", 34 Long: `List operator, account and user keys in the current operator and account context. 35 Additional flags allow you to specify which types of keys to display. For example 36 the --operator shows the operator key, the --accounts show account keys, etc. 37 38 You can further limit the account and user displayed by specifying the 39 --account and --user flags respectively. To list all keys specify 40 the --all flag. 41 42 The --not-referenced flag displays all keys not relevant to the current 43 operator, accounts and users. These keys may be referenced in a different 44 operator context. 45 46 The --filter flag allows you to specify a few letters in a public key 47 and display only those keys that match provided the --operator, 48 --accounts, and --user or --all flags match the key type. 49 `, 50 Example: `nsc list keys 51 nsc list keys --all (same as specifying --operator --accounts --users) 52 nsc list keys --operator --not-referenced (shows all other operator keys) 53 nsc list keys --all --filter VSVMGA (shows all keys containing the filter) 54 nsc list keys --account A (changes the account context to the specified account) 55 `, 56 Args: MaxArgs(0), 57 SilenceUsage: false, 58 RunE: func(cmd *cobra.Command, args []string) error { 59 if err := RunMaybeStorelessAction(cmd, args, ¶ms); err != nil { 60 return err 61 } 62 return nil 63 }, 64 } 65 cmd.Flags().BoolVarP(¶ms.Operator, "operator", "o", false, "show operator keys") 66 cmd.Flags().BoolVarP(¶ms.Accounts, "accounts", "a", false, "show account keys") 67 cmd.Flags().BoolVarP(¶ms.Users, "users", "u", false, "show user keys") 68 cmd.Flags().StringVarP(¶ms.Account, "account", "", "", "show specified account keys") 69 cmd.Flags().StringVarP(¶ms.User, "user", "", "", "show specified user key") 70 cmd.Flags().BoolVarP(¶ms.All, "all", "A", false, "show operator, accounts and users") 71 cmd.Flags().StringVarP(¶ms.Filter, "filter", "f", "", "filter keys containing string") 72 cmd.Flags().BoolVarP(¶ms.Unreferenced, "not-referenced", "", false, "shows keys that are not referenced in the current operator context") 73 cmd.Flags().BoolVarP(¶ms.Seeds, "show-seeds", "S", false, "shows seed keys value") 74 75 return cmd 76 } 77 78 func init() { 79 listCmd.AddCommand(createListKeysCmd()) 80 } 81 82 type ListKeysParams struct { 83 Seeds bool 84 KeyCollectorParams 85 KS store.KeyStore 86 } 87 88 func (p *ListKeysParams) SetDefaults(ctx ActionCtx) error { 89 p.KS = ctx.StoreCtx().KeyStore 90 return p.KeyCollectorParams.SetDefaults(ctx) 91 } 92 93 func (p *ListKeysParams) PreInteractive(ctx ActionCtx) error { 94 return nil 95 } 96 97 func (p *ListKeysParams) Load(ctx ActionCtx) error { 98 return nil 99 } 100 101 func (p *ListKeysParams) PostInteractive(ctx ActionCtx) error { 102 return nil 103 } 104 105 func (p *ListKeysParams) Validate(ctx ActionCtx) error { 106 kdir := store.GetKeysDir() 107 _, err := os.Stat(kdir) 108 if os.IsNotExist(err) { 109 return fmt.Errorf("keystore %#q does not exist", kdir) 110 } 111 if ctx.StoreCtx().Operator.Name == "" && !p.Unreferenced { 112 return errors.New("operator is not set -- set an operator first or try --not-referenced to list all keys not in the context") 113 } 114 if p.Unreferenced && p.Seeds { 115 return errors.New("specify one of --show-seeds or --not-referenced") 116 } 117 return nil 118 } 119 120 func (p *ListKeysParams) Run(ctx ActionCtx) (store.Status, error) { 121 var err error 122 var keys Keys 123 124 keys.KeyList, err = p.KeyCollectorParams.Run(ctx) 125 keys.MessageFn = p.Report 126 return keys, err 127 } 128 129 func (p *ListKeysParams) Report(ks Keys) string { 130 if ks.Len() == 0 { 131 return "no keys matched query" 132 } 133 if p.Seeds { 134 return p.ReportSeeds(ks) 135 } 136 var hasUnreferenced bool 137 table := tablewriter.CreateTable() 138 table.AddTitle("Keys") 139 table.AddHeaders("Entity", "Key", "Signing Key", "Stored") 140 for _, k := range ks.KeyList { 141 unreferenced := false 142 if k.Name == "?" { 143 hasUnreferenced = true 144 unreferenced = true 145 } 146 sk := "" 147 if k.Signing { 148 sk = "*" 149 } 150 stored := "" 151 if k.HasKey() { 152 stored = "*" 153 } 154 if k.Invalid { 155 stored = "BAD" 156 } 157 pad := "" 158 if !unreferenced { 159 switch k.ExpectedKind { 160 case nkeys.PrefixByteAccount: 161 pad = " " 162 case nkeys.PrefixByteUser: 163 pad = " " 164 } 165 } 166 n := fmt.Sprintf("%s%s", pad, k.Name) 167 table.AddRow(n, k.Pub, sk, stored) 168 } 169 s := table.Render() 170 if hasUnreferenced { 171 s = fmt.Sprintf("%s[?] unreferenced key - may belong to a different operator context", s) 172 } 173 return s 174 } 175 176 func (p *ListKeysParams) ReportSeeds(ks Keys) string { 177 table := tablewriter.CreateTable() 178 table.AddTitle("Seeds Keys") 179 table.AddHeaders("Entity", "Private Key", "Signing Key") 180 for _, k := range ks.KeyList { 181 sk := "" 182 if k.Signing { 183 sk = "*" 184 } 185 186 pad := "" 187 switch k.ExpectedKind { 188 case nkeys.PrefixByteAccount: 189 pad = " " 190 case nkeys.PrefixByteUser: 191 pad = " " 192 } 193 194 n := fmt.Sprintf("%s%s", pad, k.Name) 195 if k.Invalid || k.KeyPath == "" { 196 k.Pub = fmt.Sprintf("%s [!]", k.Pub) 197 } else { 198 seed, err := p.KS.GetSeed(k.Pub) 199 if err != nil { 200 k.Pub = fmt.Sprintf("%s [ERR]", k.Pub) 201 } else { 202 k.Pub = seed 203 } 204 } 205 206 table.AddRow(n, k.Pub, sk) 207 } 208 s := table.Render() 209 s = fmt.Sprintf("%s[ ! ] seed is not stored\n", s) 210 s = fmt.Sprintf("%s[ERR] error reading seed\n", s) 211 return s 212 }