Configure RPC auth per wallet host.
This commit is contained in:
parent
d92a76abd3
commit
6cc246ceea
102
config.go
102
config.go
@ -37,34 +37,35 @@ var (
|
|||||||
|
|
||||||
// config defines the configuration options for the VSP.
|
// config defines the configuration options for the VSP.
|
||||||
type config struct {
|
type config struct {
|
||||||
Listen string `long:"listen" ini-name:"listen" description:"The ip:port to listen for API requests."`
|
Listen string `long:"listen" ini-name:"listen" description:"The ip:port to listen for API requests."`
|
||||||
LogLevel string `long:"loglevel" ini-name:"loglevel" description:"Logging level." choice:"trace" choice:"debug" choice:"info" choice:"warn" choice:"error" choice:"critical"`
|
LogLevel string `long:"loglevel" ini-name:"loglevel" description:"Logging level." choice:"trace" choice:"debug" choice:"info" choice:"warn" choice:"error" choice:"critical"`
|
||||||
Network string `long:"network" ini-name:"network" description:"Decred network to use." choice:"testnet" choice:"mainnet" choice:"simnet"`
|
Network string `long:"network" ini-name:"network" description:"Decred network to use." choice:"testnet" choice:"mainnet" choice:"simnet"`
|
||||||
VSPFee float64 `long:"vspfee" ini-name:"vspfee" description:"Fee percentage charged for VSP use. eg. 2.0 (2%), 0.5 (0.5%)."`
|
VSPFee float64 `long:"vspfee" ini-name:"vspfee" description:"Fee percentage charged for VSP use. eg. 2.0 (2%), 0.5 (0.5%)."`
|
||||||
DcrdHost string `long:"dcrdhost" ini-name:"dcrdhost" description:"The ip:port to establish a JSON-RPC connection with dcrd. Should be the same host where vspd is running."`
|
DcrdHost string `long:"dcrdhost" ini-name:"dcrdhost" description:"The ip:port to establish a JSON-RPC connection with dcrd. Should be the same host where vspd is running."`
|
||||||
DcrdUser string `long:"dcrduser" ini-name:"dcrduser" description:"Username for dcrd RPC connections."`
|
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."`
|
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."`
|
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."`
|
WalletHosts string `long:"wallethost" ini-name:"wallethost" description:"Comma separated list of ip:port to establish JSON-RPC connections with voting dcrwallet."`
|
||||||
WalletUser string `long:"walletuser" ini-name:"walletuser" description:"Username for dcrwallet RPC connections."`
|
WalletUsers string `long:"walletuser" ini-name:"walletuser" description:"Comma separated list of username for dcrwallet RPC connections."`
|
||||||
WalletPass string `long:"walletpass" ini-name:"walletpass" description:"Password for dcrwallet RPC connections."`
|
WalletPasswords string `long:"walletpass" ini-name:"walletpass" description:"Comma separated list of password for dcrwallet RPC connections."`
|
||||||
WalletCert string `long:"walletcert" ini-name:"walletcert" description:"The dcrwallet RPC certificate file."`
|
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)."`
|
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."`
|
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."`
|
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."`
|
||||||
VspClosed bool `long:"vspclosed" ini-name:"vspclosed" description:"Closed prevents the VSP from accepting new tickets."`
|
VspClosed bool `long:"vspclosed" ini-name:"vspclosed" description:"Closed prevents the VSP from accepting new tickets."`
|
||||||
AdminPass string `long:"adminpass" ini-name:"adminpass" description:"Password for accessing admin page."`
|
AdminPass string `long:"adminpass" ini-name:"adminpass" description:"Password for accessing admin page."`
|
||||||
Designation string `long:"designation" ini-name:"designation" description:"Short name for the VSP. Customizes the logo in the top toolbar."`
|
Designation string `long:"designation" ini-name:"designation" description:"Short name for the VSP. Customizes the logo in the top toolbar."`
|
||||||
|
|
||||||
// The following flags should be set on CLI only, not via config file.
|
// The following flags should be set on CLI only, not via config file.
|
||||||
FeeXPub string `long:"feexpub" no-ini:"true" description:"Cold wallet xpub used for collecting fees. Should be provided once to initialize a vspd database."`
|
FeeXPub string `long:"feexpub" no-ini:"true" description:"Cold wallet xpub used for collecting fees. Should be provided once to initialize a vspd database."`
|
||||||
HomeDir string `long:"homedir" no-ini:"true" description:"Path to application home directory. Used for storing VSP database and logs."`
|
HomeDir string `long:"homedir" no-ini:"true" description:"Path to application home directory. Used for storing VSP database and logs."`
|
||||||
ConfigFile string `long:"configfile" no-ini:"true" description:"Path to configuration file."`
|
ConfigFile string `long:"configfile" no-ini:"true" description:"Path to configuration file."`
|
||||||
|
|
||||||
dbPath string
|
dbPath string
|
||||||
netParams *netParams
|
netParams *netParams
|
||||||
dcrdCert []byte
|
dcrdCert []byte
|
||||||
walletCert []byte
|
walletHosts, walletUsers, walletPasswords []string
|
||||||
|
walletCerts [][]byte
|
||||||
}
|
}
|
||||||
|
|
||||||
// fileExists reports whether the named file or directory exists.
|
// fileExists reports whether the named file or directory exists.
|
||||||
@ -162,7 +163,7 @@ func loadConfig() (*config, error) {
|
|||||||
HomeDir: defaultHomeDir,
|
HomeDir: defaultHomeDir,
|
||||||
ConfigFile: defaultConfigFile,
|
ConfigFile: defaultConfigFile,
|
||||||
DcrdHost: defaultDcrdHost,
|
DcrdHost: defaultDcrdHost,
|
||||||
WalletHosts: []string{defaultWalletHost},
|
WalletHosts: defaultWalletHost,
|
||||||
WebServerDebug: defaultWebServerDebug,
|
WebServerDebug: defaultWebServerDebug,
|
||||||
BackupInterval: defaultBackupInterval,
|
BackupInterval: defaultBackupInterval,
|
||||||
VspClosed: defaultVspClosed,
|
VspClosed: defaultVspClosed,
|
||||||
@ -303,36 +304,67 @@ func loadConfig() (*config, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Ensure the dcrwallet RPC username is set.
|
// Ensure the dcrwallet RPC username is set.
|
||||||
if cfg.WalletUser == "" {
|
if cfg.WalletUsers == "" {
|
||||||
return nil, errors.New("the walletuser option is not set")
|
return nil, errors.New("the walletuser option is not set")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure the dcrwallet RPC password is set.
|
// Ensure the dcrwallet RPC password is set.
|
||||||
if cfg.WalletPass == "" {
|
if cfg.WalletPasswords == "" {
|
||||||
return nil, errors.New("the walletpass option is not set")
|
return nil, errors.New("the walletpass option is not set")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure the dcrwallet RPC cert path is 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")
|
return nil, errors.New("the walletcert option is not set")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load dcrwallet RPC certificate.
|
// Parse list of wallet hosts.
|
||||||
cfg.WalletCert = cleanAndExpandPath(cfg.WalletCert)
|
cfg.walletHosts = strings.Split(cfg.WalletHosts, ",")
|
||||||
cfg.walletCert, err = ioutil.ReadFile(cfg.WalletCert)
|
numHost := len(cfg.walletHosts)
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to read dcrwallet cert file: %v", err)
|
// 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.
|
// 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",
|
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.
|
// Add default port for the active network if there is no port specified.
|
||||||
for i := 0; i < len(cfg.WalletHosts); i++ {
|
for i := 0; i < numHost; i++ {
|
||||||
cfg.WalletHosts[i] = normalizeAddress(cfg.WalletHosts[i], cfg.netParams.WalletRPCServerPort)
|
cfg.walletHosts[i] = normalizeAddress(cfg.walletHosts[i], cfg.netParams.WalletRPCServerPort)
|
||||||
}
|
}
|
||||||
cfg.DcrdHost = normalizeAddress(cfg.DcrdHost, cfg.netParams.DcrdRPCServerPort)
|
cfg.DcrdHost = normalizeAddress(cfg.DcrdHost, cfg.netParams.DcrdRPCServerPort)
|
||||||
|
|
||||||
|
|||||||
23
harness.sh
23
harness.sh
@ -74,7 +74,20 @@ sleep 1 # Give dcrd time to start
|
|||||||
|
|
||||||
for ((i = 1; i <= $NUMBER_OF_WALLETS; i++)); do
|
for ((i = 1; i <= $NUMBER_OF_WALLETS; i++)); do
|
||||||
WALLET_RPC_LISTEN="127.0.0.1:2011${i}"
|
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 ""
|
||||||
echo "Writing config for dcrwallet-${i}"
|
echo "Writing config for dcrwallet-${i}"
|
||||||
@ -115,10 +128,10 @@ cat > "${HARNESS_ROOT}/vspd/vspd.conf" <<EOF
|
|||||||
dcrduser = ${RPC_USER}
|
dcrduser = ${RPC_USER}
|
||||||
dcrdpass = ${RPC_PASS}
|
dcrdpass = ${RPC_PASS}
|
||||||
dcrdcert = ${DCRD_RPC_CERT}
|
dcrdcert = ${DCRD_RPC_CERT}
|
||||||
${ALL_WALLETS}
|
wallethost = ${ALL_WALLET_HOST}
|
||||||
walletuser = ${RPC_USER}
|
walletuser = ${ALL_WALLET_USER}
|
||||||
walletpass = ${RPC_PASS}
|
walletpass = ${ALL_WALLET_PASS}
|
||||||
walletcert = ${WALLET_RPC_CERT}
|
walletcert = ${ALL_WALLET_CERT}
|
||||||
loglevel = debug
|
loglevel = debug
|
||||||
network = testnet
|
network = testnet
|
||||||
webserverdebug = false
|
webserverdebug = false
|
||||||
|
|||||||
@ -23,11 +23,11 @@ type WalletRPC struct {
|
|||||||
|
|
||||||
type WalletConnect []*client
|
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))
|
walletConnect := make(WalletConnect, len(addrs))
|
||||||
|
|
||||||
for i := 0; i < len(addrs); i++ {
|
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
|
return walletConnect
|
||||||
|
|||||||
2
vspd.go
2
vspd.go
@ -70,7 +70,7 @@ func run(ctx context.Context) error {
|
|||||||
defer dcrd.Close()
|
defer dcrd.Close()
|
||||||
|
|
||||||
// Create RPC client for remote dcrwallet instance (used for voting).
|
// 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()
|
defer wallets.Close()
|
||||||
|
|
||||||
// Create and start webapi server.
|
// Create and start webapi server.
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user