Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow wallet passphrases to be environment variables #5879

Merged
merged 12 commits into from
May 18, 2020
Merged
12 changes: 12 additions & 0 deletions validator/keymanager/wallet.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"encoding/json"
"errors"
"fmt"
"os"
"regexp"
"strings"

Expand Down Expand Up @@ -55,6 +56,17 @@ func NewWallet(input string) (KeyManager, string, error) {
if len(opts.Passphrases) == 0 {
return nil, walletOptsHelp, errors.New("at least one passphrase is required to decrypt accounts")
}
for i, passphrase := range opts.Passphrases {
if strings.HasPrefix(passphrase, "$") {
envPassphrase := os.Getenv(strings.TrimPrefix(passphrase, "$"))
if envPassphrase != "" {
// N.B. We do not log here if the environment variable is not found, as it is possible that this is actually a
// passphrase that just happens to begin with the '$' character. If this is a missing environment variable it will
// be noticed when the account fails to decrypt.
opts.Passphrases[i] = envPassphrase
}
}
}

km := &Wallet{
accounts: make(map[[48]byte]e2wtypes.Account),
Expand Down
73 changes: 73 additions & 0 deletions validator/keymanager/wallet_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,3 +95,76 @@ func TestMultiplePassphrases(t *testing.T) {
})
}
}

func TestEnvPassphrases(t *testing.T) {
path := SetupWallet(t)
defer func() {
if err := os.RemoveAll(path); err != nil {
t.Log(err)
}
}()

if err := os.Setenv("TESTENVPASSPHRASES_NEITHER", "neither"); err != nil {
t.Fatalf("Error setting environment variable TESTENVPASSPHRASES_NEITHER: %v", err)
}
defer func() {
if err := os.Unsetenv("TESTENVPASSPHRASES_NEITHER"); err != nil {
t.Fatalf("Error unsetting environment variable TESTENVPASSPHRASES_NEITHER: %v", err)
}
}()
if err := os.Setenv("TESTENVPASSPHRASES_FOO", "foo"); err != nil {
t.Fatalf("Error setting environment variable TESTENVPASSPHRASES_FOO: %v", err)
}
defer func() {
if err := os.Unsetenv("TESTENVPASSPHRASES_FOO"); err != nil {
t.Fatalf("Error unsetting environment variable TESTENVPASSPHRASES_FOO: %v", err)
}
}()
if err := os.Setenv("TESTENVPASSPHRASES_BAR", "bar"); err != nil {
t.Fatalf("Error setting environment variable TESTENVPASSPHRASES_BAR: %v", err)
}
defer func() {
if err := os.Unsetenv("TESTENVPASSPHRASES_BAR"); err != nil {
t.Fatalf("Error unsetting environment variable TESTENVPASSPHRASES_BAR: %v", err)
}
}()

tests := []struct {
name string
wallet keymanager.KeyManager
accounts int
}{
{
name: "Neither",
wallet: wallet(t, fmt.Sprintf(`{"location":%q,"accounts":["Wallet 1"],"passphrases":["$TESTENVPASSPHRASES_NEITHER"]}`, path)),
accounts: 0,
},
{
name: "Foo",
wallet: wallet(t, fmt.Sprintf(`{"location":%q,"accounts":["Wallet 1"],"passphrases":["$TESTENVPASSPHRASES_FOO"]}`, path)),
accounts: 1,
},
{
name: "Bar",
wallet: wallet(t, fmt.Sprintf(`{"location":%q,"accounts":["Wallet 1"],"passphrases":["$TESTENVPASSPHRASES_BAR"]}`, path)),
accounts: 1,
},
{
name: "Both",
wallet: wallet(t, fmt.Sprintf(`{"location":%q,"accounts":["Wallet 1"],"passphrases":["$TESTENVPASSPHRASES_FOO","$TESTENVPASSPHRASES_BAR"]}`, path)),
accounts: 2,
},
}

for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
keys, err := test.wallet.FetchValidatingKeys()
if err != nil {
t.Error(err)
}
if len(keys) != test.accounts {
t.Errorf("Found %d keys; expected %d", len(keys), test.accounts)
}
})
}
}