[node.sh] finished bls loader implementation

pull/3219/head
Jacky Wang 4 years ago
parent 992fdfff4b
commit d5a7df70cd
No known key found for this signature in database
GPG Key ID: 1085CE5F4FF5842C
  1. 4
      cmd/harmony/blsloader/kmsProvider.go
  2. 119
      cmd/harmony/blsloader/loader.go
  3. 3
      cmd/harmony/blsloader/params.go
  4. 12
      cmd/harmony/blsloader/passProvider.go
  5. 49
      cmd/harmony/blsloader/utils.go

@ -125,9 +125,6 @@ type promptKMSProvider struct {
} }
func newPromptKMSProvider(timeout time.Duration) *promptKMSProvider { func newPromptKMSProvider(timeout time.Duration) *promptKMSProvider {
if timeout == 0 {
timeout = defPromptTimeout
}
return &promptKMSProvider{ return &promptKMSProvider{
baseKMSProvider: baseKMSProvider{}, baseKMSProvider: baseKMSProvider{},
timeout: timeout, timeout: timeout,
@ -157,6 +154,7 @@ func (provider *promptKMSProvider) getAWSConfig() (*AwsConfig, error) {
} }
// prompt prompt the user to input a string for a certain field with timeout. // prompt prompt the user to input a string for a certain field with timeout.
// TODO(Jacky): refactor this into a prompt structure
func (provider *promptKMSProvider) prompt(hint string) (string, error) { func (provider *promptKMSProvider) prompt(hint string) (string, error) {
var ( var (
res string res string

@ -1,4 +1,123 @@
package blsloader package blsloader
import (
"errors"
ffibls "github.com/harmony-one/bls/ffi/go/bls"
"github.com/harmony-one/harmony/multibls"
)
type Loader struct { type Loader struct {
BlsKeyFile *string
AwsBlsKey *string
BlsDir *string
BlsPassFile *string
AwsConfigFile *string
UsePromptAwsConfig bool
UsePromptPassword bool
PersistPassphrase bool
}
func (loader *Loader) LoadKeys() (multibls.PrivateKey, error) {
switch {
case stringIsSet(loader.BlsKeyFile):
return loader.loadSingleBasicBlsKey()
case stringIsSet(loader.AwsBlsKey):
return loader.loadSingleKmsBlsKey()
case stringIsSet(loader.BlsDir):
return loader.loadDirBlsKeys()
default:
return multibls.PrivateKey{}, errors.New("empty bls key data source")
}
}
func (loader *Loader) loadSingleBasicBlsKey() (multibls.PrivateKey, error) {
provider := loader.getPassProviderSingleBasic()
secretKey, err := loadBasicKeyFromFile(*loader.BlsPassFile, provider)
if err != nil {
return multibls.PrivateKey{}, err
}
return secretKeyToMultiPrivateKey(secretKey), nil
}
func (loader *Loader) getPassProviderSingleBasic() passProvider {
switch {
case stringIsSet(loader.BlsPassFile):
return newFilePassProvider(*loader.BlsPassFile)
default:
// TODO(Jacky): multi pass provider
return newPromptPassProvider()
}
}
func (loader *Loader) loadSingleKmsBlsKey() (multibls.PrivateKey, error) {
provider := loader.getKmsProviderSingleKms()
secretKey, err := loadKMSKeyFromFile(*loader.AwsBlsKey, provider)
if err != nil {
return multibls.PrivateKey{}, err
}
return secretKeyToMultiPrivateKey(secretKey), nil
}
func (loader *Loader) getKmsProviderSingleKms() kmsClientProvider {
switch {
case loader.UsePromptAwsConfig:
return newPromptKMSProvider(defKmsPromptTimeout)
case stringIsSet(loader.AwsConfigFile):
return newFileKMSProvider(*loader.AwsConfigFile)
default:
return newSharedKMSProvider()
}
}
func (loader *Loader) loadDirBlsKeys() (multibls.PrivateKey, error) {
pp := loader.getPassProviderDirKeys()
kcp := loader.getKmsClientProviderDirKeys()
helper := &blsDirLoadHelper{
dirPath: *loader.BlsDir,
pp: pp,
kcp: kcp,
}
return helper.getKeyFilesFromDir()
}
func (loader *Loader) getPassProviderDirKeys() passProvider {
switch {
case stringIsSet(loader.BlsPassFile):
return newFilePassProvider(*loader.BlsPassFile)
case loader.UsePromptPassword:
return newPromptPassProvider()
default:
if loader.PersistPassphrase {
return multiPassProvider{
newDirPassProvider(*loader.BlsDir),
newPromptPassProvider().
setPersist(*loader.BlsDir, defWritePassFileMode),
}
}
return multiPassProvider{
newDirPassProvider(*loader.BlsDir),
newPromptPassProvider(),
}
}
}
func (loader *Loader) getKmsClientProviderDirKeys() kmsClientProvider {
switch {
case stringIsSet(loader.AwsConfigFile):
return newFileKMSProvider(*loader.AwsConfigFile)
case loader.UsePromptAwsConfig:
return newPromptKMSProvider(defKmsPromptTimeout)
default:
return newSharedKMSProvider()
}
}
func secretKeyToMultiPrivateKey(secretKeys ...*ffibls.SecretKey) multibls.PrivateKey {
return multibls.PrivateKey{PrivateKey: secretKeys}
}
func stringIsSet(val *string) bool {
return val != nil && *val != ""
} }

@ -9,7 +9,8 @@ const (
) )
const ( const (
defPromptTimeout = 1 * time.Second defKmsPromptTimeout = 1 * time.Second
defPassPromptTimeout = 10 * time.Second
) )
const ( const (

@ -54,14 +54,11 @@ func (provider *promptPassProvider) getPassphrase(keyFile string) (string, error
} }
} }
return pass, nil return pass, nil
} }
func (provider *promptPassProvider) persistPassphrase(keyFile string, passPhrase string) error { func (provider *promptPassProvider) persistPassphrase(keyFile string, passPhrase string) error {
passFile := filepath.Join(provider.persistDir, filepath.Base(keyFile)) passFile := filepath.Join(provider.persistDir, filepath.Base(keyFile))
if _, err := os.Stat(passFile); os.IsNotExist(err) { if _, err := os.Stat(passFile); err == nil {
// file not exist. Go on create the file
} else if err == nil {
// File exist. Prompt user to overwrite pass file // File exist. Prompt user to overwrite pass file
overwrite, err := promptYesNo(fmt.Sprintf("pass file [%v] already exist. Overwrite? ", passFile)) overwrite, err := promptYesNo(fmt.Sprintf("pass file [%v] already exist. Overwrite? ", passFile))
if err != nil { if err != nil {
@ -70,6 +67,9 @@ func (provider *promptPassProvider) persistPassphrase(keyFile string, passPhrase
if !overwrite { if !overwrite {
return nil return nil
} }
} else if !os.IsNotExist(err) {
// Unknown error. Directly return
return err
} }
return ioutil.WriteFile(passFile, []byte(passPhrase), defWritePassFileMode) return ioutil.WriteFile(passFile, []byte(passPhrase), defWritePassFileMode)
} }
@ -108,6 +108,10 @@ type dirPassProvider struct {
dirPath string dirPath string
} }
func newDirPassProvider(dirPath string) *dirPassProvider {
return &dirPassProvider{dirPath: }
}
func (provider *dirPassProvider) getPassphrase(keyFile string) (string, error) { func (provider *dirPassProvider) getPassphrase(keyFile string) (string, error) {
baseName := filepath.Base(keyFile) baseName := filepath.Base(keyFile)
passKeyBase := keyFileToPassFile(baseName) passKeyBase := keyFileToPassFile(baseName)

@ -3,18 +3,16 @@ package blsloader
import ( import (
"bufio" "bufio"
"fmt" "fmt"
"io"
"os" "os"
"path/filepath" "path/filepath"
"strings" "strings"
"syscall" "syscall"
"golang.org/x/crypto/ssh/terminal"
ffibls "github.com/harmony-one/bls/ffi/go/bls" ffibls "github.com/harmony-one/bls/ffi/go/bls"
"github.com/harmony-one/harmony/internal/blsgen" "github.com/harmony-one/harmony/internal/blsgen"
"github.com/harmony-one/harmony/multibls" "github.com/harmony-one/harmony/multibls"
"github.com/pkg/errors" "github.com/pkg/errors"
"golang.org/x/crypto/ssh/terminal"
) )
var ( var (
@ -55,55 +53,56 @@ func loadKMSKeyFromFile(blsKeyFile string, kcp kmsClientProvider) (*ffibls.Secre
return secretKey, nil return secretKey, nil
} }
// blsDirLoader is the helper structure // blsDirLoadHelper is the helper structure
type blsDirLoader struct { type blsDirLoadHelper struct {
dirPath string dirPath string
pp passProvider pp passProvider
kcp kmsClientProvider kcp kmsClientProvider
resWriter io.Writer // result field
secretKeys []*ffibls.SecretKey secretKeys []*ffibls.SecretKey
} }
func (loader *blsDirLoader) getKeyFilesFromDir(dir string) (multibls.PrivateKey, error) { func (helper *blsDirLoadHelper) getKeyFilesFromDir() (multibls.PrivateKey, error) {
err := filepath.Walk(dir, loader.processFileWalk) err := filepath.Walk(helper.dirPath, helper.processFileWalk)
if err != nil { if err != nil {
return multibls.PrivateKey{}, err return multibls.PrivateKey{}, err
} }
return multibls.PrivateKey{PrivateKey: loader.secretKeys}, nil return multibls.PrivateKey{PrivateKey: helper.secretKeys}, nil
} }
// error types to be neglected for directory bls loading func (helper *blsDirLoadHelper) processFileWalk(path string, info os.FileInfo, err error) error {
var skippingErrs = []error{ key, err := helper.loadKeyFromFile(path, info)
errUnknownExtension,
errNilPassProvider,
errNilKMSClientProvider,
}
func (loader *blsDirLoader) processFileWalk(path string, info os.FileInfo, err error) error {
key, err := loader.loadKeyFromFile(path, info)
if err != nil { if err != nil {
if errIsErrors(err, skippingErrs) { if errIsErrors(err, helper.skippingErrors()) {
skipStr := fmt.Sprintf("Skipping [%s]: %v\n", path, err) skipStr := fmt.Sprintf("Skipping [%s]: %v\n", path, err)
loader.resWriter.Write([]byte(skipStr)) fmt.Println(skipStr)
return nil return nil
} }
return err return err
} }
loader.secretKeys = append(loader.secretKeys, key) helper.secretKeys = append(helper.secretKeys, key)
return nil return nil
} }
func (loader *blsDirLoader) loadKeyFromFile(path string, info os.FileInfo) (*ffibls.SecretKey, error) { // errors to be neglected for directory bls loading
func (helper *blsDirLoadHelper) skippingErrors() []error {
return []error{
errUnknownExtension,
errNilPassProvider,
errNilKMSClientProvider,
}
}
func (helper *blsDirLoadHelper) loadKeyFromFile(path string, info os.FileInfo) (*ffibls.SecretKey, error) {
var ( var (
key *ffibls.SecretKey key *ffibls.SecretKey
err error err error
) )
switch { switch {
case isBasicKeyFile(info): case isBasicKeyFile(info):
key, err = loadBasicKeyFromFile(path, loader.pp) key, err = loadBasicKeyFromFile(path, helper.pp)
case isKMSKeyFile(info): case isKMSKeyFile(info):
key, err = loadKMSKeyFromFile(path, loader.kcp) key, err = loadKMSKeyFromFile(path, helper.kcp)
default: default:
err = errUnknownExtension err = errUnknownExtension
} }
Loading…
Cancel
Save