code.vegaprotocol.io/vega@v0.79.0/cmd/vegawallet/commands/key_taint.go (about)

     1  // Copyright (C) 2023 Gobalsky Labs Limited
     2  //
     3  // This program is free software: you can redistribute it and/or modify
     4  // it under the terms of the GNU Affero General Public License as
     5  // published by the Free Software Foundation, either version 3 of the
     6  // License, or (at your option) any later version.
     7  //
     8  // This program is distributed in the hope that it will be useful,
     9  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    10  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    11  // GNU Affero General Public License for more details.
    12  //
    13  // You should have received a copy of the GNU Affero General Public License
    14  // along with this program.  If not, see <http://www.gnu.org/licenses/>.
    15  
    16  package cmd
    17  
    18  import (
    19  	"context"
    20  	"errors"
    21  	"fmt"
    22  	"io"
    23  	"os"
    24  
    25  	"code.vegaprotocol.io/vega/cmd/vegawallet/commands/cli"
    26  	"code.vegaprotocol.io/vega/cmd/vegawallet/commands/flags"
    27  	"code.vegaprotocol.io/vega/cmd/vegawallet/commands/printer"
    28  	"code.vegaprotocol.io/vega/wallet/api"
    29  	"code.vegaprotocol.io/vega/wallet/wallets"
    30  
    31  	"github.com/spf13/cobra"
    32  )
    33  
    34  var (
    35  	taintKeyLong = cli.LongDesc(`
    36  		Tainting a key pair marks it as unsafe to use and ensures it will not be
    37  		used to sign transactions.
    38  
    39  		This mechanism is useful when the key pair has been compromised.
    40  
    41  		When a key is tainted, it is automatically removed from the allowed
    42  		keys if specified. If the key is the only one to be set, the permission
    43  		to access the public keys is revoked. If no allowed key is specified,
    44  		but all keys in the wallet are tainted, the permission of the public
    45  		keys is revoked as well.
    46  	`)
    47  
    48  	taintKeyExample = cli.Examples(`
    49  		# Taint a key pair
    50  		{{.Software}} key taint --wallet WALLET --pubkey PUBKEY
    51  	`)
    52  )
    53  
    54  type TaintKeyHandler func(api.AdminTaintKeyParams, string) error
    55  
    56  func NewCmdTaintKey(w io.Writer, rf *RootFlags) *cobra.Command {
    57  	h := func(params api.AdminTaintKeyParams, passphrase string) error {
    58  		ctx := context.Background()
    59  
    60  		walletStore, err := wallets.InitialiseStore(rf.Home, false)
    61  		if err != nil {
    62  			return fmt.Errorf("couldn't initialise wallets store: %w", err)
    63  		}
    64  		defer walletStore.Close()
    65  
    66  		if _, errDetails := api.NewAdminUnlockWallet(walletStore).Handle(ctx, api.AdminUnlockWalletParams{
    67  			Wallet:     params.Wallet,
    68  			Passphrase: passphrase,
    69  		}); errDetails != nil {
    70  			return errors.New(errDetails.Data)
    71  		}
    72  
    73  		if _, errDetails := api.NewAdminTaintKey(walletStore).Handle(ctx, params); errDetails != nil {
    74  			return errors.New(errDetails.Data)
    75  		}
    76  		return nil
    77  	}
    78  
    79  	return BuildCmdTaintKey(w, h, rf)
    80  }
    81  
    82  func BuildCmdTaintKey(w io.Writer, handler TaintKeyHandler, rf *RootFlags) *cobra.Command {
    83  	f := &TaintKeyFlags{}
    84  
    85  	cmd := &cobra.Command{
    86  		Use:     "taint",
    87  		Short:   "Mark a key pair as tainted",
    88  		Long:    taintKeyLong,
    89  		Example: taintKeyExample,
    90  		RunE: func(_ *cobra.Command, _ []string) error {
    91  			req, pass, err := f.Validate()
    92  			if err != nil {
    93  				return err
    94  			}
    95  
    96  			if err := handler(req, pass); err != nil {
    97  				return err
    98  			}
    99  
   100  			switch rf.Output {
   101  			case flags.InteractiveOutput:
   102  				PrintTaintKeyResponse(w)
   103  			case flags.JSONOutput:
   104  				return nil
   105  			}
   106  
   107  			return nil
   108  		},
   109  	}
   110  
   111  	cmd.Flags().StringVarP(&f.Wallet,
   112  		"wallet", "w",
   113  		"",
   114  		"Wallet holding the public key",
   115  	)
   116  	cmd.Flags().StringVarP(&f.PublicKey,
   117  		"pubkey", "k",
   118  		"",
   119  		"Public key to taint (hex-encoded)",
   120  	)
   121  	cmd.Flags().StringVarP(&f.PassphraseFile,
   122  		"passphrase-file", "p",
   123  		"",
   124  		"Path to the file containing the wallet's passphrase",
   125  	)
   126  
   127  	autoCompleteWallet(cmd, rf.Home, "wallet")
   128  
   129  	return cmd
   130  }
   131  
   132  type TaintKeyFlags struct {
   133  	Wallet         string
   134  	PublicKey      string
   135  	PassphraseFile string
   136  }
   137  
   138  func (f *TaintKeyFlags) Validate() (api.AdminTaintKeyParams, string, error) {
   139  	if len(f.Wallet) == 0 {
   140  		return api.AdminTaintKeyParams{}, "", flags.MustBeSpecifiedError("wallet")
   141  	}
   142  
   143  	if len(f.PublicKey) == 0 {
   144  		return api.AdminTaintKeyParams{}, "", flags.MustBeSpecifiedError("pubkey")
   145  	}
   146  
   147  	passphrase, err := flags.GetPassphrase(f.PassphraseFile)
   148  	if err != nil {
   149  		return api.AdminTaintKeyParams{}, "", err
   150  	}
   151  
   152  	return api.AdminTaintKeyParams{
   153  		Wallet:    f.Wallet,
   154  		PublicKey: f.PublicKey,
   155  	}, passphrase, nil
   156  }
   157  
   158  func PrintTaintKeyResponse(w io.Writer) {
   159  	p := printer.NewInteractivePrinter(w)
   160  
   161  	str := p.String()
   162  	defer p.Print(str)
   163  
   164  	str.CheckMark().SuccessText("Tainting succeeded").NextSection()
   165  
   166  	str.RedArrow().DangerText("Important").NextLine()
   167  	str.Text("If you tainted a key for security reasons, you should not untaint it.").NextSection()
   168  
   169  	str.BlueArrow().InfoText("Untaint a key").NextLine()
   170  	str.Text("You may have tainted a key pair by mistake. If you want to untaint it, see the following command:").NextSection()
   171  	str.Code(fmt.Sprintf("%s key untaint --help", os.Args[0])).NextLine()
   172  }