You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
270 lines
8.3 KiB
270 lines
8.3 KiB
package main
|
|
|
|
import (
|
|
"errors"
|
|
"flag"
|
|
"fmt"
|
|
"strings"
|
|
"sync"
|
|
|
|
"github.com/spf13/cobra"
|
|
|
|
"github.com/harmony-one/harmony/internal/blsgen"
|
|
"github.com/harmony-one/harmony/internal/cli"
|
|
"github.com/harmony-one/harmony/multibls"
|
|
)
|
|
|
|
var (
|
|
blsKeyFile = flag.String("blskey_file", "", "The encrypted file of bls serialized private key by passphrase.")
|
|
blsFolder = flag.String("blsfolder", ".hmy/blskeys", "The folder that stores the bls keys and corresponding passphrases; e.g. <blskey>.key and <blskey>.pass; all bls keys mapped to same shard")
|
|
maxBLSKeysPerNode = flag.Int("max_bls_keys_per_node", 10, "Maximum number of bls keys allowed per node (default 4)")
|
|
|
|
blsPass = flag.String("blspass", "default", "The source for bls passphrases. (default, no-prompt, prompt, file:$PASS_FILE, none)")
|
|
persistPass = flag.Bool("save-passphrase", false, "Whether the prompt passphrase is saved after prompt.")
|
|
awsConfigSource = flag.String("aws-config-source", "default", "The source for aws config. (default, prompt, file:$CONFIG_FILE, none)")
|
|
)
|
|
|
|
var (
|
|
multiBLSPriKey multibls.PrivateKeys
|
|
onceLoadBLSKey sync.Once
|
|
)
|
|
|
|
var blsFlags = []cli.Flag{
|
|
blsDirFlag,
|
|
blsKeyFilesFlag,
|
|
maxBLSKeyFilesFlag,
|
|
passEnabledFlag,
|
|
passSrcTypeFlag,
|
|
passSrcFileFlag,
|
|
passSaveFlag,
|
|
kmsEnabledFlag,
|
|
kmsConfigSrcTypeFlag,
|
|
kmsConfigFileFlag,
|
|
}
|
|
|
|
var legacyBLSFlags = []cli.Flag{
|
|
legacyBLSKeyFileFlag,
|
|
legacyBLSFolderFlag,
|
|
legacyBLSKeysPerNodeFlag,
|
|
legacyBLSPassFlag,
|
|
legacyBLSPersistPassFlag,
|
|
legacyKMSConfigSourceFlag,
|
|
}
|
|
|
|
var (
|
|
blsDirFlag = cli.StringFlag{
|
|
Name: "bls.dir",
|
|
Usage: "directory for BLS keys",
|
|
DefValue: defaultConfig.BLSKeys.KeyDir,
|
|
}
|
|
blsKeyFilesFlag = cli.StringSliceFlag{
|
|
Name: "bls.keys",
|
|
Usage: "a list of BLS key files (separated by ,)",
|
|
DefValue: defaultConfig.BLSKeys.KeyFiles,
|
|
}
|
|
// TODO: shall we move this to a hard coded parameter?
|
|
maxBLSKeyFilesFlag = cli.IntFlag{
|
|
Name: "bls.maxkeys",
|
|
Usage: "maximum number of BLS keys for a node",
|
|
DefValue: defaultConfig.BLSKeys.MaxKeys,
|
|
}
|
|
passEnabledFlag = cli.BoolFlag{
|
|
Name: "bls.pass",
|
|
Usage: "whether BLS key decryption with passphrase is enabled",
|
|
DefValue: defaultConfig.BLSKeys.PassEnabled,
|
|
}
|
|
passSrcTypeFlag = cli.StringFlag{
|
|
Name: "bls.pass.src",
|
|
Usage: "source for BLS passphrase (auto, file, prompt)",
|
|
DefValue: defaultConfig.BLSKeys.PassSrcType,
|
|
}
|
|
passSrcFileFlag = cli.StringFlag{
|
|
Name: "bls.pass.file",
|
|
Usage: "the pass file used for BLS decryption. If specified, this pass file will be used for all BLS keys",
|
|
DefValue: defaultConfig.BLSKeys.PassFile,
|
|
}
|
|
passSaveFlag = cli.BoolFlag{
|
|
Name: "bls.pass.save",
|
|
Usage: "after input the BLS passphrase from console, whether to persist the input passphrases in .pass file",
|
|
DefValue: defaultConfig.BLSKeys.SavePassphrase,
|
|
}
|
|
kmsEnabledFlag = cli.BoolFlag{
|
|
Name: "bls.kms",
|
|
Usage: "whether BLS key decryption with AWS KMS service is enabled",
|
|
DefValue: defaultConfig.BLSKeys.KMSEnabled,
|
|
}
|
|
kmsConfigSrcTypeFlag = cli.StringFlag{
|
|
Name: "bls.kms.src",
|
|
Usage: "the AWS config source (region and credentials) for KMS service (shared, prompt, file)",
|
|
DefValue: defaultConfig.BLSKeys.KMSConfigSrcType,
|
|
}
|
|
kmsConfigFileFlag = cli.StringFlag{
|
|
Name: "bls.kms.config",
|
|
Usage: "json config file for KMS service (region and credentials)",
|
|
DefValue: defaultConfig.BLSKeys.KMSConfigFile,
|
|
}
|
|
legacyBLSKeyFileFlag = cli.StringSliceFlag{
|
|
Name: "blskey_file",
|
|
Usage: "The encrypted file of bls serialized private key by passphrase.",
|
|
DefValue: defaultConfig.BLSKeys.KeyFiles,
|
|
Deprecated: "use --bls.keys",
|
|
}
|
|
legacyBLSFolderFlag = cli.StringFlag{
|
|
Name: "blsfolder",
|
|
Usage: "The folder that stores the bls keys and corresponding passphrases; e.g. <blskey>.key and <blskey>.pass; all bls keys mapped to same shard",
|
|
DefValue: defaultConfig.BLSKeys.KeyDir,
|
|
Deprecated: "use --bls.dir",
|
|
}
|
|
legacyBLSKeysPerNodeFlag = cli.IntFlag{
|
|
Name: "max_bls_keys_per_node",
|
|
Usage: "Maximum number of bls keys allowed per node",
|
|
DefValue: defaultConfig.BLSKeys.MaxKeys,
|
|
Deprecated: "use --bls.maxkeys",
|
|
}
|
|
legacyBLSPassFlag = cli.StringFlag{
|
|
Name: "blspass",
|
|
Usage: "The source for bls passphrases. (default, stdin, no-prompt, prompt, file:$PASS_FILE, none)",
|
|
DefValue: "default",
|
|
Deprecated: "use --bls.pass, --bls.pass.src, --bls.pass.file",
|
|
}
|
|
legacyBLSPersistPassFlag = cli.BoolFlag{
|
|
Name: "save-passphrase",
|
|
Usage: "Whether the prompt passphrase is saved after prompt.",
|
|
DefValue: defaultConfig.BLSKeys.SavePassphrase,
|
|
Deprecated: "use --bls.pass.save",
|
|
}
|
|
legacyKMSConfigSourceFlag = cli.StringFlag{
|
|
Name: "aws-config-source",
|
|
Usage: "The source for aws config. (default, prompt, file:$CONFIG_FILE, none)",
|
|
DefValue: "default",
|
|
Deprecated: "use --bls.kms, --bls.kms.src, --bls.kms.config",
|
|
}
|
|
)
|
|
|
|
func applyBLSFlags(cmd *cobra.Command, config *hmyConfig) {
|
|
if cli.HasFlagChanged(cmd, blsDirFlag) {
|
|
config.BLSKeys.KeyDir = cli.GetStringFlagValue(cmd, blsDirFlag)
|
|
} else if cli.HasFlagChanged(cmd, legacyBLSFolderFlag) {
|
|
config.BLSKeys.KeyDir = cli.GetStringFlagValue(cmd, legacyBLSFolderFlag)
|
|
}
|
|
|
|
if cli.HasFlagChanged(cmd, blsKeyFilesFlag) {
|
|
config.BLSKeys.KeyFiles = cli.GetStringSliceFlagValue(cmd, blsKeyFilesFlag)
|
|
} else if cli.HasFlagChanged(cmd, legacyBLSKeyFileFlag) {
|
|
config.BLSKeys.KeyFiles = cli.GetStringSliceFlagValue(cmd, legacyBLSKeyFileFlag)
|
|
}
|
|
|
|
if cli.HasFlagChanged(cmd, maxBLSKeyFilesFlag) {
|
|
config.BLSKeys.MaxKeys = cli.GetIntFlagValue(cmd, maxBLSKeyFilesFlag)
|
|
} else if cli.HasFlagChanged(cmd, legacyBLSKeysPerNodeFlag) {
|
|
config.BLSKeys.MaxKeys = cli.GetIntFlagValue(cmd, legacyBLSKeysPerNodeFlag)
|
|
}
|
|
|
|
if cli.HasFlagsChanged(cmd, blsFlags) {
|
|
applyBLSPassFlags(cmd, config)
|
|
applyKMSFlags(cmd, config)
|
|
} else if cli.HasFlagsChanged(cmd, legacyBLSFlags) {
|
|
applyLegacyBLSPassFlags(cmd, config)
|
|
applyLegacyKMSFlags(cmd, config)
|
|
}
|
|
}
|
|
|
|
func applyBLSPassFlags(cmd *cobra.Command, config *hmyConfig) {
|
|
|
|
}
|
|
|
|
func applyKMSFlags(cmd *cobra.Command, config *hmyConfig) {
|
|
|
|
}
|
|
|
|
func applyLegacyBLSPassFlags(cmd *cobra.Command, config *hmyConfig) {
|
|
|
|
}
|
|
|
|
func applyLegacyKMSFlags(cmd *cobra.Command, config *hmyConfig) {
|
|
|
|
}
|
|
|
|
func loadBLSKeys() (multibls.PrivateKeys, error) {
|
|
config, err := parseBLSLoadingConfig()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
keys, err := blsgen.LoadKeys(config)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if len(keys) == 0 {
|
|
return nil, fmt.Errorf("0 bls keys loaded")
|
|
}
|
|
if len(keys) > *maxBLSKeysPerNode {
|
|
return nil, fmt.Errorf("bls keys exceed maximum count %v", *maxBLSKeysPerNode)
|
|
}
|
|
return keys, err
|
|
}
|
|
|
|
func parseBLSLoadingConfig() (blsgen.Config, error) {
|
|
var (
|
|
config blsgen.Config
|
|
err error
|
|
)
|
|
if len(*blsKeyFile) != 0 {
|
|
config.MultiBlsKeys = strings.Split(*blsKeyFile, ",")
|
|
}
|
|
config.BlsDir = blsFolder
|
|
|
|
config, err = parseBLSPass(config, *blsPass)
|
|
if err != nil {
|
|
return blsgen.Config{}, err
|
|
}
|
|
config, err = parseAwsConfigSrc(config, *awsConfigSource)
|
|
if err != nil {
|
|
return blsgen.Config{}, err
|
|
}
|
|
return config, nil
|
|
}
|
|
|
|
func parseBLSPass(config blsgen.Config, src string) (blsgen.Config, error) {
|
|
methodArgs := strings.SplitN(src, ":", 2)
|
|
method := methodArgs[0]
|
|
|
|
switch method {
|
|
case "default", "stdin":
|
|
config.PassSrcType = blsgen.PassSrcAuto
|
|
case "file":
|
|
config.PassSrcType = blsgen.PassSrcFile
|
|
if len(methodArgs) < 2 {
|
|
return blsgen.Config{}, errors.New("must specify passphrase file")
|
|
}
|
|
config.PassFile = &methodArgs[1]
|
|
case "no-prompt":
|
|
config.PassSrcType = blsgen.PassSrcFile
|
|
case "prompt":
|
|
config.PassSrcType = blsgen.PassSrcPrompt
|
|
config.PersistPassphrase = *persistPass
|
|
case "none":
|
|
config.PassSrcType = blsgen.PassSrcNil
|
|
}
|
|
config.PersistPassphrase = *persistPass
|
|
return config, nil
|
|
}
|
|
|
|
func parseAwsConfigSrc(config blsgen.Config, src string) (blsgen.Config, error) {
|
|
methodArgs := strings.SplitN(src, ":", 2)
|
|
method := methodArgs[0]
|
|
switch method {
|
|
case "default":
|
|
config.AwsCfgSrcType = blsgen.AwsCfgSrcShared
|
|
case "file":
|
|
config.AwsCfgSrcType = blsgen.AwsCfgSrcFile
|
|
if len(methodArgs) < 2 {
|
|
return blsgen.Config{}, errors.New("must specify aws config file")
|
|
}
|
|
config.AwsConfigFile = &methodArgs[1]
|
|
case "prompt":
|
|
config.AwsCfgSrcType = blsgen.AwsCfgSrcPrompt
|
|
case "none":
|
|
config.AwsCfgSrcType = blsgen.AwsCfgSrcNil
|
|
}
|
|
return config, nil
|
|
}
|
|
|