Configure RPC auth per wallet host.

This commit is contained in:
jholdstock 2020-07-30 17:11:47 +01:00 committed by David Hill
parent d92a76abd3
commit 6cc246ceea
4 changed files with 88 additions and 43 deletions

View File

@ -45,10 +45,10 @@ type config struct {
DcrdUser string `long:"dcrduser" ini-name:"dcrduser" description:"Username for dcrd RPC connections."`
DcrdPass string `long:"dcrdpass" ini-name:"dcrdpass" description:"Password for dcrd RPC connections."`
DcrdCert string `long:"dcrdcert" ini-name:"dcrdcert" description:"The dcrd RPC certificate file."`
WalletHosts []string `long:"wallethost" ini-name:"wallethost" description:"Add an ip:port to establish a JSON-RPC connection with voting dcrwallet."`
WalletUser string `long:"walletuser" ini-name:"walletuser" description:"Username for dcrwallet RPC connections."`
WalletPass string `long:"walletpass" ini-name:"walletpass" description:"Password for dcrwallet RPC connections."`
WalletCert string `long:"walletcert" ini-name:"walletcert" description:"The dcrwallet RPC certificate file."`
WalletHosts string `long:"wallethost" ini-name:"wallethost" description:"Comma separated list of ip:port to establish JSON-RPC connections with voting dcrwallet."`
WalletUsers string `long:"walletuser" ini-name:"walletuser" description:"Comma separated list of username for dcrwallet RPC connections."`
WalletPasswords string `long:"walletpass" ini-name:"walletpass" description:"Comma separated list of password for dcrwallet RPC connections."`
WalletCerts string `long:"walletcert" ini-name:"walletcert" description:"Comma separated list of dcrwallet RPC certificate files."`
WebServerDebug bool `long:"webserverdebug" ini-name:"webserverdebug" description:"Enable web server debug mode (verbose logging to terminal and live-reloading templates)."`
SupportEmail string `long:"supportemail" ini-name:"supportemail" description:"Email address for users in need of support."`
BackupInterval time.Duration `long:"backupinterval" ini-name:"backupinterval" description:"Time period between automatic database backups. Valid time units are {s,m,h}. Minimum 30 seconds."`
@ -64,7 +64,8 @@ type config struct {
dbPath string
netParams *netParams
dcrdCert []byte
walletCert []byte
walletHosts, walletUsers, walletPasswords []string
walletCerts [][]byte
}
// fileExists reports whether the named file or directory exists.
@ -162,7 +163,7 @@ func loadConfig() (*config, error) {
HomeDir: defaultHomeDir,
ConfigFile: defaultConfigFile,
DcrdHost: defaultDcrdHost,
WalletHosts: []string{defaultWalletHost},
WalletHosts: defaultWalletHost,
WebServerDebug: defaultWebServerDebug,
BackupInterval: defaultBackupInterval,
VspClosed: defaultVspClosed,
@ -303,36 +304,67 @@ func loadConfig() (*config, error) {
}
// Ensure the dcrwallet RPC username is set.
if cfg.WalletUser == "" {
if cfg.WalletUsers == "" {
return nil, errors.New("the walletuser option is not set")
}
// Ensure the dcrwallet RPC password is set.
if cfg.WalletPass == "" {
if cfg.WalletPasswords == "" {
return nil, errors.New("the walletpass option is not set")
}
// Ensure the dcrwallet RPC cert path is set.
if cfg.WalletCert == "" {
if cfg.WalletCerts == "" {
return nil, errors.New("the walletcert option is not set")
}
// Load dcrwallet RPC certificate.
cfg.WalletCert = cleanAndExpandPath(cfg.WalletCert)
cfg.walletCert, err = ioutil.ReadFile(cfg.WalletCert)
// Parse list of wallet hosts.
cfg.walletHosts = strings.Split(cfg.WalletHosts, ",")
numHost := len(cfg.walletHosts)
// An RPC username must be specified for each wallet host.
cfg.walletUsers = strings.Split(cfg.WalletUsers, ",")
numUser := len(cfg.walletUsers)
if numUser != numHost {
return nil, fmt.Errorf("%d wallet hosts specified, expected %d RPC usernames, got %d",
numHost, numHost, numUser)
}
// An RPC password must be specified for each wallet host.
cfg.walletPasswords = strings.Split(cfg.WalletPasswords, ",")
numPass := len(cfg.walletPasswords)
if numPass != numHost {
return nil, fmt.Errorf("%d wallet hosts specified, expected %d RPC passwords, got %d",
numHost, numHost, numPass)
}
// An RPC certificate must be specified for each wallet host.
certs := strings.Split(cfg.WalletCerts, ",")
numCert := len(certs)
if numCert != numHost {
return nil, fmt.Errorf("%d wallet hosts specified, expected %d RPC certificates, got %d",
numHost, numHost, numCert)
}
// Load dcrwallet RPC certificate(s).
cfg.walletCerts = make([][]byte, numCert)
for i := 0; i < numCert; i++ {
certs[i] = cleanAndExpandPath(certs[i])
cfg.walletCerts[i], err = ioutil.ReadFile(certs[i])
if err != nil {
return nil, fmt.Errorf("failed to read dcrwallet cert file: %v", err)
}
}
// Verify minimum number of voting wallets are configured.
if len(cfg.WalletHosts) < minRequired {
if numHost < minRequired {
return nil, fmt.Errorf("minimum required voting wallets has not been met: %d < %d",
len(cfg.WalletHosts), minRequired)
numHost, minRequired)
}
// Add default port for the active network if there is no port specified.
for i := 0; i < len(cfg.WalletHosts); i++ {
cfg.WalletHosts[i] = normalizeAddress(cfg.WalletHosts[i], cfg.netParams.WalletRPCServerPort)
for i := 0; i < numHost; i++ {
cfg.walletHosts[i] = normalizeAddress(cfg.walletHosts[i], cfg.netParams.WalletRPCServerPort)
}
cfg.DcrdHost = normalizeAddress(cfg.DcrdHost, cfg.netParams.DcrdRPCServerPort)

View File

@ -74,7 +74,20 @@ sleep 1 # Give dcrd time to start
for ((i = 1; i <= $NUMBER_OF_WALLETS; i++)); do
WALLET_RPC_LISTEN="127.0.0.1:2011${i}"
ALL_WALLETS="${ALL_WALLETS}"$'\n'wallethost="${WALLET_RPC_LISTEN}"
# Concatenate all wallet details for vspd config file.
if [ $i == 1 ]; then
ALL_WALLET_HOST="${WALLET_RPC_LISTEN}"
ALL_WALLET_USER="${RPC_USER}"
ALL_WALLET_PASS="${RPC_PASS}"
ALL_WALLET_CERT="${WALLET_RPC_CERT}"
else
ALL_WALLET_HOST="${ALL_WALLET_HOST},${WALLET_RPC_LISTEN}"
ALL_WALLET_USER="${ALL_WALLET_USER},${RPC_USER}"
ALL_WALLET_PASS="${ALL_WALLET_PASS},${RPC_PASS}"
ALL_WALLET_CERT="${ALL_WALLET_CERT},${WALLET_RPC_CERT}"
fi
echo ""
echo "Writing config for dcrwallet-${i}"
@ -115,10 +128,10 @@ cat > "${HARNESS_ROOT}/vspd/vspd.conf" <<EOF
dcrduser = ${RPC_USER}
dcrdpass = ${RPC_PASS}
dcrdcert = ${DCRD_RPC_CERT}
${ALL_WALLETS}
walletuser = ${RPC_USER}
walletpass = ${RPC_PASS}
walletcert = ${WALLET_RPC_CERT}
wallethost = ${ALL_WALLET_HOST}
walletuser = ${ALL_WALLET_USER}
walletpass = ${ALL_WALLET_PASS}
walletcert = ${ALL_WALLET_CERT}
loglevel = debug
network = testnet
webserverdebug = false

View File

@ -23,11 +23,11 @@ type WalletRPC struct {
type WalletConnect []*client
func SetupWallet(user, pass string, addrs []string, cert []byte) WalletConnect {
func SetupWallet(user, pass, addrs []string, cert [][]byte) WalletConnect {
walletConnect := make(WalletConnect, len(addrs))
for i := 0; i < len(addrs); i++ {
walletConnect[i] = setup(user, pass, addrs[i], cert, nil)
walletConnect[i] = setup(user[i], pass[i], addrs[i], cert[i], nil)
}
return walletConnect

View File

@ -70,7 +70,7 @@ func run(ctx context.Context) error {
defer dcrd.Close()
// Create RPC client for remote dcrwallet instance (used for voting).
wallets := rpc.SetupWallet(cfg.WalletUser, cfg.WalletPass, cfg.WalletHosts, cfg.walletCert)
wallets := rpc.SetupWallet(cfg.walletUsers, cfg.walletPasswords, cfg.walletHosts, cfg.walletCerts)
defer wallets.Close()
// Create and start webapi server.