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 }