github.com/kbehouse/nsc@v0.0.6/cmd/keycollector.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 "sort" 20 "strings" 21 22 "github.com/kbehouse/nsc/cmd/store" 23 "github.com/nats-io/nkeys" 24 ) 25 26 type KeyCollectorParams struct { 27 Operator bool 28 Accounts bool 29 Users bool 30 All bool 31 Unreferenced bool 32 Account string 33 User string 34 Filter string 35 } 36 37 func (p *KeyCollectorParams) SetDefaults(ctx ActionCtx) error { 38 conf := GetConfig() 39 40 if ctx.NothingToDo("operator", "accounts", "users", "all") { 41 // default if no args 42 account := p.Account 43 if account == "" { 44 account = conf.Account 45 } 46 p.Operator = true 47 p.Account = account 48 p.Accounts = true 49 p.Users = true 50 } 51 if p.All { 52 p.Operator = true 53 p.Accounts = true 54 p.Users = true 55 } 56 return nil 57 } 58 59 func (p *KeyCollectorParams) handleOperator(ctx ActionCtx) (KeyList, error) { 60 var keys KeyList 61 sctx := ctx.StoreCtx() 62 63 // if we don't have a store - ignore this operator details 64 if sctx.Operator.Name == "" { 65 return nil, nil 66 } 67 oc, err := sctx.Store.ReadOperatorClaim() 68 if err != nil { 69 return nil, err 70 } 71 var oki Key 72 oki.Name = oc.Name 73 oki.ExpectedKind = nkeys.PrefixByteOperator 74 oki.Pub = oc.Subject 75 oki.Resolve(sctx.KeyStore) 76 keys = append(keys, &oki) 77 78 for _, k := range oc.SigningKeys { 79 var sk Key 80 sk.Name = oc.Name 81 sk.Pub = k 82 sk.Signing = true 83 sk.ExpectedKind = nkeys.PrefixByteOperator 84 sk.Resolve(sctx.KeyStore) 85 keys = append(keys, &sk) 86 } 87 88 return keys, nil 89 } 90 91 func (p *KeyCollectorParams) handleAccount(ctx ActionCtx, parent string, name string) (KeyList, error) { 92 s := ctx.StoreCtx().Store 93 ks := ctx.StoreCtx().KeyStore 94 95 var keys KeyList 96 97 ac, err := s.ReadAccountClaim(name) 98 if err != nil { 99 return nil, err 100 } 101 var aki Key 102 aki.Parent = parent 103 aki.Name = ac.Name 104 aki.ExpectedKind = nkeys.PrefixByteAccount 105 aki.Pub = ac.Subject 106 aki.Resolve(ks) 107 keys = append(keys, &aki) 108 109 for k := range ac.SigningKeys { 110 var ask Key 111 ask.Name = ac.Name 112 ask.Pub = k 113 ask.Signing = true 114 ask.Resolve(ks) 115 keys = append(keys, &ask) 116 } 117 return keys, nil 118 } 119 120 func (p *KeyCollectorParams) handleUsers(ctx ActionCtx, account string) (KeyList, error) { 121 var keys KeyList 122 123 s := ctx.StoreCtx().Store 124 ac, err := s.ReadAccountClaim(account) 125 if err != nil { 126 return nil, err 127 } 128 129 users, err := s.ListEntries(store.Accounts, account, store.Users) 130 if err != nil { 131 return nil, err 132 } 133 sort.Strings(users) 134 for _, u := range users { 135 uk, err := p.handleUser(ctx, account, u) 136 if err != nil { 137 return nil, err 138 } 139 uk.Parent = ac.Subject 140 keys = append(keys, uk) 141 } 142 return keys, nil 143 } 144 145 func (p *KeyCollectorParams) handleUser(ctx ActionCtx, account string, name string) (*Key, error) { 146 s := ctx.StoreCtx().Store 147 ks := ctx.StoreCtx().KeyStore 148 149 uc, err := s.ReadUserClaim(account, name) 150 if err != nil { 151 return nil, err 152 } 153 var uki Key 154 uki.Name = uc.Name 155 uki.Pub = uc.Subject 156 uki.ExpectedKind = nkeys.PrefixByteUser 157 uki.Resolve(ks) 158 return &uki, nil 159 } 160 161 func (p *KeyCollectorParams) Run(ctx ActionCtx) (KeyList, error) { 162 keys, err := p.handleOperator(ctx) 163 if err != nil { 164 return nil, err 165 } 166 167 // if we have an operator, we can resolve other things 168 if keys != nil { 169 var accounts []string 170 if p.Account != "" { 171 accounts = append(accounts, p.Account) 172 } else { 173 an, err := GetConfig().ListAccounts() 174 if err != nil { 175 return nil, err 176 } 177 accounts = append(accounts, an...) 178 } 179 for _, a := range accounts { 180 akeys, err := p.handleAccount(ctx, keys[0].Pub, a) 181 if err != nil { 182 return nil, err 183 } 184 keys = append(keys, akeys...) 185 186 if p.User != "" { 187 uk, err := p.handleUser(ctx, a, p.User) 188 if err != nil { 189 return nil, err 190 } 191 keys = append(keys, uk) 192 } else { 193 ukeys, err := p.handleUsers(ctx, a) 194 if err != nil { 195 return nil, err 196 } 197 keys = append(keys, ukeys...) 198 } 199 } 200 } 201 202 if p.Unreferenced { 203 all, err := ctx.StoreCtx().KeyStore.AllKeys() 204 if err != nil { 205 return nil, err 206 } 207 m := make(map[string]*Key) 208 for _, v := range keys { 209 m[v.Pub] = v 210 } 211 ks := ctx.StoreCtx().KeyStore 212 var okeys KeyList 213 var akeys KeyList 214 var ukeys KeyList 215 for _, v := range all { 216 _, ok := m[v] 217 if !ok { 218 var k Key 219 k.Name = "?" 220 k.Pub = v 221 k.ExpectedKind, err = store.PubKeyType(k.Pub) 222 if err != nil { 223 return nil, err 224 } 225 k.Resolve(ks) 226 switch k.ExpectedKind { 227 case nkeys.PrefixByteOperator: 228 okeys = append(okeys, &k) 229 case nkeys.PrefixByteAccount: 230 akeys = append(akeys, &k) 231 case nkeys.PrefixByteUser: 232 ukeys = append(ukeys, &k) 233 } 234 } 235 } 236 sort.Sort(okeys) 237 sort.Sort(akeys) 238 sort.Sort(ukeys) 239 keys = KeyList{} 240 keys = append(keys, okeys...) 241 keys = append(keys, akeys...) 242 keys = append(keys, ukeys...) 243 } 244 245 var keyFilter = strings.ToUpper(p.Filter) 246 var filteredKeys KeyList 247 for _, k := range keys { 248 if !p.Operator && k.ExpectedKind == nkeys.PrefixByteOperator { 249 continue 250 } 251 if !p.Accounts && k.ExpectedKind == nkeys.PrefixByteAccount { 252 continue 253 } 254 if !p.Users && k.ExpectedKind == nkeys.PrefixByteUser { 255 continue 256 } 257 if keyFilter != "" && !strings.Contains(k.Pub, keyFilter) { 258 continue 259 } 260 filteredKeys = append(filteredKeys, k) 261 } 262 263 return filteredKeys, nil 264 } 265 266 type Key struct { 267 Name string 268 Pub string 269 Parent string 270 ExpectedKind nkeys.PrefixByte 271 Signing bool 272 KeyPath string 273 Invalid bool 274 } 275 276 func (k *Key) Resolve(ks store.KeyStore) { 277 kp, _ := ks.GetKeyPair(k.Pub) 278 if kp != nil { 279 k.KeyPath = ks.GetKeyPath(k.Pub) 280 pk, _ := kp.PublicKey() 281 k.Invalid = pk != k.Pub 282 } 283 } 284 285 func (k *Key) HasKey() bool { 286 return k.KeyPath != "" 287 } 288 289 type Keys struct { 290 KeyList 291 MessageFn func(ks Keys) string 292 } 293 294 func (keys Keys) Message() string { 295 return keys.MessageFn(keys) 296 } 297 298 type KeyList []*Key 299 300 func (ks KeyList) Code() store.StatusCode { 301 return store.OK 302 } 303 304 func (ks KeyList) Len() int { 305 return len(ks) 306 } 307 308 func (ks KeyList) Swap(i, j int) { 309 ks[i], ks[j] = ks[j], ks[i] 310 } 311 312 func (ks KeyList) Less(i, j int) bool { 313 return ks[i].Pub < ks[j].Pub 314 }