gitlab.com/SkynetLabs/skyd@v1.6.9/cmd/skyc/skykeycmd.go (about)

     1  package main
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"strings"
     7  	"text/tabwriter"
     8  
     9  	"github.com/spf13/cobra"
    10  
    11  	"gitlab.com/NebulousLabs/errors"
    12  	"gitlab.com/SkynetLabs/skyd/node/api/client"
    13  	"gitlab.com/SkynetLabs/skyd/skykey"
    14  )
    15  
    16  var (
    17  	// errBothNameAndIDUsed is returned if both the Skykey name and ID are
    18  	// supplied for an operation that requires one or the other
    19  	errBothNameAndIDUsed = errors.New("Can only use one flag: --name or --id flag")
    20  
    21  	// errNeitherNameNorIDUsed is returned if neither the Skykey name or ID are
    22  	// supplied for an operation that requires one or the other
    23  	errNeitherNameNorIDUsed = errors.New("Must use either the --name or --id flag")
    24  )
    25  var (
    26  	skykeyCmd = &cobra.Command{
    27  		Use:   "skykey",
    28  		Short: "Perform actions related to Skykeys",
    29  		Long:  `Perform actions related to Skykeys, the encryption keys used for Skyfiles.`,
    30  		Run:   skykeycmd,
    31  	}
    32  
    33  	skykeyAddCmd = &cobra.Command{
    34  		Use:   "add [skykey base64-encoded skykey]",
    35  		Short: "Add a base64-encoded skykey to the key manager.",
    36  		Long:  `Add a base64-encoded skykey to the key manager.`,
    37  		Run:   wrap(skykeyaddcmd),
    38  	}
    39  
    40  	skykeyCreateCmd = &cobra.Command{
    41  		Use:   "create [name]",
    42  		Short: "Create a skykey with the given name.",
    43  		Long: `Create a skykey  with the given name. The --type flag can be
    44  		used to specify the skykey type. Its default is private-id.`,
    45  		Run: wrap(skykeycreatecmd),
    46  	}
    47  
    48  	skykeyDeleteCmd = &cobra.Command{
    49  		Use:   "delete",
    50  		Short: "Delete the skykey by name or id",
    51  		Long:  `Delete the base64-encoded skykey using its name or id`,
    52  	}
    53  
    54  	skykeyDeleteNameCmd = &cobra.Command{
    55  		Use:   "name [name]",
    56  		Short: "Delete the skykey by name",
    57  		Long:  `Delete the base64-encoded skykey using its name`,
    58  		Run:   wrap(skykeydeletenamecmd),
    59  	}
    60  
    61  	skykeyDeleteIDCmd = &cobra.Command{
    62  		Use:   "id [id]",
    63  		Short: "Delete the skykey by id",
    64  		Long:  `Delete the base64-encoded skykey using its id`,
    65  		Run:   wrap(skykeydeleteidcmd),
    66  	}
    67  
    68  	skykeyGetCmd = &cobra.Command{
    69  		Use:   "get",
    70  		Short: "Get the skykey by its name or id",
    71  		Long:  `Get the base64-encoded skykey using either its name with --name or id with --id`,
    72  		Run:   wrap(skykeygetcmd),
    73  	}
    74  
    75  	skykeyGetIDCmd = &cobra.Command{
    76  		Use:   "get-id [name]",
    77  		Short: "Get the skykey id by its name",
    78  		Long:  `Get the base64-encoded skykey id by its name`,
    79  		Run:   wrap(skykeygetidcmd),
    80  	}
    81  
    82  	skykeyListCmd = &cobra.Command{
    83  		Use:   "ls",
    84  		Short: "List all skykeys",
    85  		Long:  "List all skykeys. Use with --show-priv-keys to show full encoding with private key also.",
    86  		Run:   wrap(skykeylistcmd),
    87  	}
    88  )
    89  
    90  // skykeycmd displays the usage info for the command.
    91  func skykeycmd(cmd *cobra.Command, args []string) {
    92  	_ = cmd.UsageFunc()(cmd)
    93  	os.Exit(exitCodeUsage)
    94  }
    95  
    96  // skykeycreatecmd is a wrapper for skykeyCreate used to handle skykey creation.
    97  func skykeycreatecmd(name string) {
    98  	skykeyStr, err := skykeyCreate(httpClient, name, skykeyType)
    99  	if err != nil {
   100  		die(errors.AddContext(err, "Failed to create new skykey"))
   101  	}
   102  	fmt.Printf("Created new skykey: %v\n", skykeyStr)
   103  }
   104  
   105  // skykeyCreate creates a new Skykey with the given name and cipher type
   106  func skykeyCreate(c client.Client, name, skykeyTypeString string) (string, error) {
   107  	var st skykey.SkykeyType
   108  	if skykeyTypeString == "" {
   109  		// If no type is provided, default to Private
   110  		st = skykey.TypePrivateID
   111  	} else {
   112  		err := st.FromString(skykeyTypeString)
   113  		if err != nil {
   114  			return "", errors.AddContext(err, "Unable to decode skykey type")
   115  		}
   116  	}
   117  	sk, err := c.SkykeyCreateKeyPost(name, st)
   118  	if err != nil {
   119  		return "", errors.AddContext(err, "Could not create skykey")
   120  	}
   121  	return sk.ToString()
   122  }
   123  
   124  // skykeyaddcmd is a wrapper for skykeyAdd used to handle the addition of new skykeys.
   125  func skykeyaddcmd(skykeyString string) {
   126  	err := skykeyAdd(httpClient, skykeyString)
   127  	if err != nil && strings.Contains(err.Error(), skykey.ErrSkykeyWithNameAlreadyExists.Error()) {
   128  		die("Skykey name already used. Try using the --rename-as parameter with a different name.")
   129  	}
   130  	if err != nil {
   131  		die(errors.AddContext(err, "Failed to add skykey"))
   132  	}
   133  
   134  	fmt.Printf("Successfully added new skykey: %v\n", skykeyString)
   135  }
   136  
   137  // skykeyAdd adds the given skykey to the renter's skykey manager.
   138  func skykeyAdd(c client.Client, skykeyString string) error {
   139  	var sk skykey.Skykey
   140  	err := sk.FromString(skykeyString)
   141  	if err != nil {
   142  		return errors.AddContext(err, "Could not decode skykey string")
   143  	}
   144  
   145  	// Rename the skykey if the --rename-as flag was provided.
   146  	if skykeyRenameAs != "" {
   147  		sk.Name = skykeyRenameAs
   148  	}
   149  
   150  	err = c.SkykeyAddKeyPost(sk)
   151  	if err != nil {
   152  		return errors.AddContext(err, "Could not add skykey")
   153  	}
   154  
   155  	return nil
   156  }
   157  
   158  // skykeydeleteidcmd is a wrapper for skykeyDeleteID that handles skykey
   159  // delete commands.
   160  func skykeydeleteidcmd(id string) {
   161  	var skykeyID skykey.SkykeyID
   162  	err := skykeyID.FromString(id)
   163  	if err != nil {
   164  		die(errors.AddContext(err, "could not decode skykey ID"))
   165  	}
   166  	err = httpClient.SkykeyDeleteByIDPost(skykeyID)
   167  	if err != nil {
   168  		die(err)
   169  	}
   170  
   171  	fmt.Println("Skykey Deleted!")
   172  }
   173  
   174  // skykeydeletenamecmd is a wrapper for skykeyDeleteName that handles skykey
   175  // delete commands.
   176  func skykeydeletenamecmd(name string) {
   177  	err := httpClient.SkykeyDeleteByNamePost(name)
   178  	if err != nil {
   179  		die(err)
   180  	}
   181  
   182  	fmt.Println("Skykey Deleted!")
   183  }
   184  
   185  // skykeygetcmd is a wrapper for skykeyGet that handles skykey get commands.
   186  func skykeygetcmd() {
   187  	skykeyStr, err := skykeyGet(httpClient, skykeyName, skykeyID)
   188  	if err != nil {
   189  		die(err)
   190  	}
   191  
   192  	fmt.Printf("Found skykey: %v\n", skykeyStr)
   193  }
   194  
   195  // skykeyGet retrieves the skykey using a name or id flag.
   196  func skykeyGet(c client.Client, name, id string) (string, error) {
   197  	err := validateSkyKeyNameAndIDUsage(name, id)
   198  	if err != nil {
   199  		return "", errors.AddContext(err, "cannot validate skykey name and ID usage to get skykey")
   200  	}
   201  
   202  	var sk skykey.Skykey
   203  	if name != "" {
   204  		sk, err = c.SkykeyGetByName(name)
   205  	} else {
   206  		var skykeyID skykey.SkykeyID
   207  		err = skykeyID.FromString(id)
   208  		if err != nil {
   209  			return "", errors.AddContext(err, "Could not decode skykey ID")
   210  		}
   211  		sk, err = c.SkykeyGetByID(skykeyID)
   212  	}
   213  
   214  	if err != nil {
   215  		return "", errors.AddContext(err, "Failed to retrieve skykey")
   216  	}
   217  
   218  	return sk.ToString()
   219  }
   220  
   221  // skykeygetidcmd retrieves the skykey id using its name.
   222  func skykeygetidcmd(skykeyName string) {
   223  	sk, err := httpClient.SkykeyGetByName(skykeyName)
   224  	if err != nil {
   225  		die("Failed to retrieve skykey:", err)
   226  	}
   227  	fmt.Printf("Found skykey ID: %v\n", sk.ID().ToString())
   228  }
   229  
   230  // skykeylistcmd is a wrapper for skykeyListKeys that prints a list of all
   231  // skykeys.
   232  func skykeylistcmd() {
   233  	skykeysString, err := skykeyListKeys(httpClient, skykeyShowPrivateKeys)
   234  	if err != nil {
   235  		die("Failed to get all skykeys:", err)
   236  	}
   237  	fmt.Print(skykeysString)
   238  }
   239  
   240  // skykeyListKeys returns a formatted string containing a list of all skykeys
   241  // being stored by the renter. It includes IDs, Names, and if showPrivateKeys is
   242  // set to true it will include the full encoded skykey.
   243  func skykeyListKeys(c client.Client, showPrivateKeys bool) (string, error) {
   244  	skykeys, err := c.SkykeySkykeysGet()
   245  	if err != nil {
   246  		return "", err
   247  	}
   248  
   249  	var b strings.Builder
   250  	w := tabwriter.NewWriter(&b, 0, 0, 2, ' ', 0)
   251  
   252  	// Print a title row.
   253  	if showPrivateKeys {
   254  		fmt.Fprintf(w, "ID\tName\tType\tFull Skykey\n")
   255  	} else {
   256  		fmt.Fprintf(w, "ID\tName\tType\n")
   257  	}
   258  
   259  	if err = w.Flush(); err != nil {
   260  		return "", err
   261  	}
   262  	titleLen := b.Len() - 1
   263  	for i := 0; i < titleLen; i++ {
   264  		fmt.Fprintf(w, "-")
   265  	}
   266  	fmt.Fprintf(w, "\n")
   267  
   268  	for _, sk := range skykeys {
   269  		idStr := sk.ID().ToString()
   270  		if !showPrivateKeys {
   271  			fmt.Fprintf(w, "%s\t%s\t%s\n", idStr, sk.Name, sk.Type.ToString())
   272  			continue
   273  		}
   274  		skStr, err := sk.ToString()
   275  		if err != nil {
   276  			return "", err
   277  		}
   278  		fmt.Fprintf(w, "%s\t%s\t%s\t%s\n", idStr, sk.Name, sk.Type.ToString(), skStr)
   279  	}
   280  
   281  	if err = w.Flush(); err != nil {
   282  		return "", err
   283  	}
   284  	return b.String(), nil
   285  }