github.com/kbehouse/nsc@v0.0.6/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/kbehouse/nsc/cmd/store"
    24  	"github.com/nats-io/nkeys"
    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, &params); err != nil {
    60  				return err
    61  			}
    62  			return nil
    63  		},
    64  	}
    65  	cmd.Flags().BoolVarP(&params.Operator, "operator", "o", false, "show operator keys")
    66  	cmd.Flags().BoolVarP(&params.Accounts, "accounts", "a", false, "show account keys")
    67  	cmd.Flags().BoolVarP(&params.Users, "users", "u", false, "show user keys")
    68  	cmd.Flags().StringVarP(&params.Account, "account", "", "", "show specified account keys")
    69  	cmd.Flags().StringVarP(&params.User, "user", "", "", "show specified user key")
    70  	cmd.Flags().BoolVarP(&params.All, "all", "A", false, "show operator, accounts and users")
    71  	cmd.Flags().StringVarP(&params.Filter, "filter", "f", "", "filter keys containing string")
    72  	cmd.Flags().BoolVarP(&params.Unreferenced, "not-referenced", "", false, "shows keys that are not referenced in the current operator context")
    73  	cmd.Flags().BoolVarP(&params.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  }