mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 10:52:25 +00:00
cmd/clef, signer: support removing stored keys (delpw + rules)
This commit is contained in:
parent
793db11483
commit
31c2781d49
4 changed files with 82 additions and 12 deletions
|
|
@ -93,7 +93,7 @@ var (
|
|||
chainIdFlag = cli.Int64Flag{
|
||||
Name: "chainid",
|
||||
Value: params.MainnetChainConfig.ChainID.Int64(),
|
||||
Usage: "Chain id to use for signing (1=mainnet, 3=ropsten, 4=rinkeby, 5=Goerli)",
|
||||
Usage: "Chain id to use for signing (1=mainnet, 3=Ropsten, 4=Rinkeby, 5=Goerli)",
|
||||
}
|
||||
rpcPortFlag = cli.IntFlag{
|
||||
Name: "rpcport",
|
||||
|
|
@ -116,8 +116,7 @@ var (
|
|||
}
|
||||
ruleFlag = cli.StringFlag{
|
||||
Name: "rules",
|
||||
Usage: "Enable rule-engine",
|
||||
Value: "",
|
||||
Usage: "Path to the rule file to auto-authorize requests with",
|
||||
}
|
||||
stdiouiFlag = cli.BoolFlag{
|
||||
Name: "stdio-ui",
|
||||
|
|
@ -160,7 +159,6 @@ incoming requests.
|
|||
Whenever you make an edit to the rule file, you need to use attestation to tell
|
||||
Clef that the file is 'safe' to execute.`,
|
||||
}
|
||||
|
||||
setCredentialCommand = cli.Command{
|
||||
Action: utils.MigrateFlags(setCredential),
|
||||
Name: "setpw",
|
||||
|
|
@ -173,6 +171,19 @@ Clef that the file is 'safe' to execute.`,
|
|||
},
|
||||
Description: `
|
||||
The setpw command stores a password for a given address (keyfile).
|
||||
`}
|
||||
delCredentialCommand = cli.Command{
|
||||
Action: utils.MigrateFlags(removeCredential),
|
||||
Name: "delpw",
|
||||
Usage: "Remove a credential for a keystore file",
|
||||
ArgsUsage: "<address>",
|
||||
Flags: []cli.Flag{
|
||||
logLevelFlag,
|
||||
configdirFlag,
|
||||
signerSecretFlag,
|
||||
},
|
||||
Description: `
|
||||
The delpw command removes a password for a given address (keyfile).
|
||||
`}
|
||||
gendocCommand = cli.Command{
|
||||
Action: GenDoc,
|
||||
|
|
@ -209,9 +220,9 @@ func init() {
|
|||
advancedMode,
|
||||
}
|
||||
app.Action = signer
|
||||
app.Commands = []cli.Command{initCommand, attestCommand, setCredentialCommand, gendocCommand}
|
||||
|
||||
app.Commands = []cli.Command{initCommand, attestCommand, setCredentialCommand, delCredentialCommand, gendocCommand}
|
||||
}
|
||||
|
||||
func main() {
|
||||
if err := app.Run(os.Args); err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
|
|
@ -317,7 +328,6 @@ func setCredential(ctx *cli.Context) error {
|
|||
if err := initialize(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
addr := ctx.Args().First()
|
||||
if !common.IsHexAddress(addr) {
|
||||
utils.Fatalf("Invalid address specified: %s", addr)
|
||||
|
|
@ -334,10 +344,38 @@ func setCredential(ctx *cli.Context) error {
|
|||
vaultLocation := filepath.Join(configDir, common.Bytes2Hex(crypto.Keccak256([]byte("vault"), stretchedKey)[:10]))
|
||||
pwkey := crypto.Keccak256([]byte("credentials"), stretchedKey)
|
||||
|
||||
// Initialize the encrypted storages
|
||||
pwStorage := storage.NewAESEncryptedStorage(filepath.Join(vaultLocation, "credentials.json"), pwkey)
|
||||
pwStorage.Put(address.Hex(), password)
|
||||
log.Info("Credential store updated", "key", address)
|
||||
|
||||
log.Info("Credential store updated", "set", address)
|
||||
return nil
|
||||
}
|
||||
|
||||
func removeCredential(ctx *cli.Context) error {
|
||||
if len(ctx.Args()) < 1 {
|
||||
utils.Fatalf("This command requires an address to be passed as an argument")
|
||||
}
|
||||
if err := initialize(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
addr := ctx.Args().First()
|
||||
if !common.IsHexAddress(addr) {
|
||||
utils.Fatalf("Invalid address specified: %s", addr)
|
||||
}
|
||||
address := common.HexToAddress(addr)
|
||||
|
||||
stretchedKey, err := readMasterKey(ctx, nil)
|
||||
if err != nil {
|
||||
utils.Fatalf(err.Error())
|
||||
}
|
||||
configDir := ctx.GlobalString(configdirFlag.Name)
|
||||
vaultLocation := filepath.Join(configDir, common.Bytes2Hex(crypto.Keccak256([]byte("vault"), stretchedKey)[:10]))
|
||||
pwkey := crypto.Keccak256([]byte("credentials"), stretchedKey)
|
||||
|
||||
pwStorage := storage.NewAESEncryptedStorage(filepath.Join(vaultLocation, "credentials.json"), pwkey)
|
||||
pwStorage.Del(address.Hex())
|
||||
|
||||
log.Info("Credential store updated", "unset", address)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -359,6 +397,10 @@ func initialize(c *cli.Context) error {
|
|||
}
|
||||
|
||||
func signer(c *cli.Context) error {
|
||||
// If we have some unrecognized command, bail out
|
||||
if args := c.Args(); len(args) > 0 {
|
||||
return fmt.Errorf("invalid command: %q", args[0])
|
||||
}
|
||||
if err := initialize(c); err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -83,7 +83,12 @@ func (r *rulesetUI) execute(jsfunc string, jsarg interface{}) (otto.Value, error
|
|||
vm.Set("storage", struct{}{})
|
||||
storageObj, _ := vm.Get("storage")
|
||||
storageObj.Object().Set("put", func(call otto.FunctionCall) otto.Value {
|
||||
r.storage.Put(call.Argument(0).String(), call.Argument(1).String())
|
||||
key, val := call.Argument(0).String(), call.Argument(1).String()
|
||||
if val == "" {
|
||||
r.storage.Del(key)
|
||||
} else {
|
||||
r.storage.Put(key, val)
|
||||
}
|
||||
return otto.NullValue()
|
||||
})
|
||||
storageObj.Object().Set("get", func(call otto.FunctionCall) otto.Value {
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ func NewAESEncryptedStorage(filename string, key []byte) *AESEncryptedStorage {
|
|||
}
|
||||
}
|
||||
|
||||
// Put stores a value by key. 0-length keys results in no-op
|
||||
// Put stores a value by key. 0-length keys results in noop.
|
||||
func (s *AESEncryptedStorage) Put(key, value string) {
|
||||
if len(key) == 0 {
|
||||
return
|
||||
|
|
@ -99,6 +99,19 @@ func (s *AESEncryptedStorage) Get(key string) (string, error) {
|
|||
return string(entry), nil
|
||||
}
|
||||
|
||||
// Del removes a key-value pair. If the key doesn't exist, the method is a noop.
|
||||
func (s *AESEncryptedStorage) Del(key string) {
|
||||
data, err := s.readEncryptedStorage()
|
||||
if err != nil {
|
||||
log.Warn("Failed to read encrypted storage", "err", err, "file", s.filename)
|
||||
return
|
||||
}
|
||||
delete(data, key)
|
||||
if err = s.writeEncryptedStorage(data); err != nil {
|
||||
log.Warn("Failed to write entry", "err", err)
|
||||
}
|
||||
}
|
||||
|
||||
// readEncryptedStorage reads the file with encrypted creds
|
||||
func (s *AESEncryptedStorage) readEncryptedStorage() (map[string]storedCredential, error) {
|
||||
creds := make(map[string]storedCredential)
|
||||
|
|
|
|||
|
|
@ -28,12 +28,15 @@ var (
|
|||
)
|
||||
|
||||
type Storage interface {
|
||||
// Put stores a value by key. 0-length keys results in no-op
|
||||
// Put stores a value by key. 0-length keys results in noop.
|
||||
Put(key, value string)
|
||||
|
||||
// Get returns the previously stored value, or an error if the key is 0-length
|
||||
// or unknown.
|
||||
Get(key string) (string, error)
|
||||
|
||||
// Del removes a key-value pair. If the key doesn't exist, the method is a noop.
|
||||
Del(key string)
|
||||
}
|
||||
|
||||
// EphemeralStorage is an in-memory storage that does
|
||||
|
|
@ -43,6 +46,7 @@ type EphemeralStorage struct {
|
|||
namespace string
|
||||
}
|
||||
|
||||
// Put stores a value by key. 0-length keys results in noop.
|
||||
func (s *EphemeralStorage) Put(key, value string) {
|
||||
if len(key) == 0 {
|
||||
return
|
||||
|
|
@ -62,6 +66,11 @@ func (s *EphemeralStorage) Get(key string) (string, error) {
|
|||
return "", ErrNotFound
|
||||
}
|
||||
|
||||
// Del removes a key-value pair. If the key doesn't exist, the method is a noop.
|
||||
func (s *EphemeralStorage) Del(key string) {
|
||||
delete(s.data, key)
|
||||
}
|
||||
|
||||
func NewEphemeralStorage() Storage {
|
||||
s := &EphemeralStorage{
|
||||
data: make(map[string]string),
|
||||
|
|
@ -73,6 +82,7 @@ func NewEphemeralStorage() Storage {
|
|||
type NoStorage struct{}
|
||||
|
||||
func (s *NoStorage) Put(key, value string) {}
|
||||
func (s *NoStorage) Del(key string) {}
|
||||
func (s *NoStorage) Get(key string) (string, error) {
|
||||
return "", errors.New("I forgot")
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue