mirror of https://github.com/poanetwork/quorum.git
Refactor retrieval of address and key from vault
* Create getSecretFromVault for common key and acct retrieval behaviour * Use getKeyFromVault in privateKeyRetrievalLoop * Create getAddressFromVault method to handle address retrieval
This commit is contained in:
parent
307ad2dee1
commit
c8b47deb09
|
@ -306,7 +306,6 @@ func (h *hashicorpService) open() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO move account and key retrieval into function
|
|
||||||
func (h *hashicorpService) accountRetrievalLoop(ticker *time.Ticker) {
|
func (h *hashicorpService) accountRetrievalLoop(ticker *time.Ticker) {
|
||||||
for range ticker.C {
|
for range ticker.C {
|
||||||
if len(h.accts) == len(h.secrets) {
|
if len(h.accts) == len(h.secrets) {
|
||||||
|
@ -319,39 +318,10 @@ func (h *hashicorpService) accountRetrievalLoop(ticker *time.Ticker) {
|
||||||
|
|
||||||
url := fmt.Sprintf("%v/v1/%v?version=%v", h.client.Address(), path, s.AddressSecretVersion)
|
url := fmt.Sprintf("%v/v1/%v?version=%v", h.client.Address(), path, s.AddressSecretVersion)
|
||||||
|
|
||||||
versionData := make(map[string][]string)
|
address, err := h.getAddressFromVault(s)
|
||||||
versionData["version"] = []string{strconv.Itoa(s.AddressSecretVersion)}
|
|
||||||
|
|
||||||
// get address from vault
|
|
||||||
resp, err := h.client.Logical().ReadWithData(path, versionData)
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warn("unable to get secret from Hashicorp Vault", "url", url, "err", err)
|
log.Warn("unable to get address from Hashicorp Vault", "url", url, "err", err)
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
respData, ok := resp.Data["data"].(map[string]interface{})
|
|
||||||
|
|
||||||
if !ok {
|
|
||||||
log.Warn("Hashicorp Vault response does not contain data", "url", url)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(respData) != 1 {
|
|
||||||
log.Warn("only one key/value pair is allowed in each Hashicorp Vault secret", "url", url)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// get secret regardless of key in map
|
|
||||||
var addr interface{}
|
|
||||||
for _, d := range respData {
|
|
||||||
addr = d
|
|
||||||
}
|
|
||||||
|
|
||||||
address, ok := addr.(string)
|
|
||||||
|
|
||||||
if !ok {
|
|
||||||
log.Warn("Hashicorp Vault response data is not in string format", "url", url)
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -366,7 +336,7 @@ func (h *hashicorpService) accountRetrievalLoop(ticker *time.Ticker) {
|
||||||
}
|
}
|
||||||
|
|
||||||
acct := accounts.Account{
|
acct := accounts.Account{
|
||||||
Address: common.HexToAddress(address),
|
Address: address,
|
||||||
URL: parsedUrl,
|
URL: parsedUrl,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -393,6 +363,16 @@ func (h *hashicorpService) accountRetrievalLoop(ticker *time.Ticker) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (h *hashicorpService) getAddressFromVault(s hashicorpSecretConfig) (common.Address, error) {
|
||||||
|
hexAddr, err := h.getSecretFromVault(s.AddressSecret, s.AddressSecretVersion, s.SecretEngine)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return common.Address{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return common.HexToAddress(hexAddr), nil
|
||||||
|
}
|
||||||
|
|
||||||
func countRetrievedKeys(keyHandlers map[common.Address]map[accounts.URL]hashicorpKeyHandler) int {
|
func countRetrievedKeys(keyHandlers map[common.Address]map[accounts.URL]hashicorpKeyHandler) int {
|
||||||
var n int
|
var n int
|
||||||
|
|
||||||
|
@ -419,53 +399,14 @@ func (h *hashicorpService) privateKeyRetrievalLoop(ticker *time.Ticker) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for addr, byUrl := range keyHandlers {
|
for addr, byUrl := range keyHandlers {
|
||||||
|
|
||||||
for u, kh := range byUrl {
|
for u, kh := range byUrl {
|
||||||
path := fmt.Sprintf("%s/data/%s", kh.secret.SecretEngine, kh.secret.PrivateKeySecret)
|
key, err := h.getKeyFromVault(kh.secret)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
path := fmt.Sprintf("%s/data/%s", kh.secret.SecretEngine, kh.secret.PrivateKeySecret)
|
||||||
url := fmt.Sprintf("%v/v1/%v?version=%v", h.client.Address(), path, kh.secret.PrivateKeySecretVersion)
|
url := fmt.Sprintf("%v/v1/%v?version=%v", h.client.Address(), path, kh.secret.PrivateKeySecretVersion)
|
||||||
|
|
||||||
versionData := make(map[string][]string)
|
log.Warn("unable to get key from Hashicorp Vault", "url", url, "err", err)
|
||||||
versionData["version"] = []string{strconv.Itoa(kh.secret.PrivateKeySecretVersion)}
|
|
||||||
|
|
||||||
// get key from vault
|
|
||||||
resp, err := h.client.Logical().ReadWithData(path, versionData)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
log.Warn("unable to get secret from Hashicorp Vault", "url", url, "err", err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
respData, ok := resp.Data["data"].(map[string]interface{})
|
|
||||||
|
|
||||||
if !ok {
|
|
||||||
log.Warn("Hashicorp Vault response does not contain data", "url", url)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(respData) != 1 {
|
|
||||||
log.Warn("only one key/value pair is allowed in each Hashicorp Vault secret", "url", url)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// get secret regardless of key in map
|
|
||||||
var k interface{}
|
|
||||||
for _, d := range respData {
|
|
||||||
k = d
|
|
||||||
}
|
|
||||||
|
|
||||||
hex, ok := k.(string)
|
|
||||||
|
|
||||||
if !ok {
|
|
||||||
log.Warn("Hashicorp Vault response data is not in string format", "url", url)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// create *ecdsa.PrivateKey
|
|
||||||
key, err := crypto.HexToECDSA(hex)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
log.Warn("unable to parse data from Hashicorp Vault to *ecdsa.PrivateKey", "url", url, "err", err)
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -480,58 +421,57 @@ func (h *hashicorpService) privateKeyRetrievalLoop(ticker *time.Ticker) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *hashicorpService) getKeyFromVault(s hashicorpSecretConfig) (*ecdsa.PrivateKey, error) {
|
func (h *hashicorpService) getKeyFromVault(s hashicorpSecretConfig) (*ecdsa.PrivateKey, error) {
|
||||||
path := fmt.Sprintf("%s/data/%s", s.SecretEngine, s.PrivateKeySecret)
|
hexKey, err := h.getSecretFromVault(s.PrivateKeySecret, s.PrivateKeySecretVersion, s.SecretEngine)
|
||||||
|
|
||||||
url := fmt.Sprintf("%v/v1/%v?version=%v", h.client.Address(), path, s.PrivateKeySecretVersion)
|
|
||||||
|
|
||||||
versionData := make(map[string][]string)
|
|
||||||
versionData["version"] = []string{strconv.Itoa(s.PrivateKeySecretVersion)}
|
|
||||||
|
|
||||||
// get key from vault
|
|
||||||
resp, err := h.client.Logical().ReadWithData(path, versionData)
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// TODO make an error type to be returned
|
return nil, err
|
||||||
log.Warn("unable to get secret from Hashicorp Vault", "url", url, "err", err)
|
|
||||||
return nil, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
respData, ok := resp.Data["data"].(map[string]interface{})
|
key, err := crypto.HexToECDSA(hexKey)
|
||||||
|
|
||||||
if !ok {
|
|
||||||
log.Warn("Hashicorp Vault response does not contain data", "url", url)
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(respData) != 1 {
|
|
||||||
log.Warn("only one key/value pair is allowed in each Hashicorp Vault secret", "url", url)
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// get secret regardless of key in map
|
|
||||||
var k interface{}
|
|
||||||
for _, d := range respData {
|
|
||||||
k = d
|
|
||||||
}
|
|
||||||
|
|
||||||
hex, ok := k.(string)
|
|
||||||
|
|
||||||
if !ok {
|
|
||||||
log.Warn("Hashicorp Vault response data is not in string format", "url", url)
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// create *ecdsa.PrivateKey
|
|
||||||
key, err := crypto.HexToECDSA(hex)
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warn("unable to parse data from Hashicorp Vault to *ecdsa.PrivateKey", "url", url, "err", err)
|
return nil, fmt.Errorf("unable to parse data from Hashicorp Vault to *ecdsa.PrivateKey: %v", err)
|
||||||
return nil, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return key, nil
|
return key, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (h *hashicorpService) getSecretFromVault(name string, version int, engine string) (string, error) {
|
||||||
|
path := fmt.Sprintf("%s/data/%s", engine, name)
|
||||||
|
|
||||||
|
versionData := make(map[string][]string)
|
||||||
|
versionData["version"] = []string{strconv.Itoa(version)}
|
||||||
|
|
||||||
|
resp, err := h.client.Logical().ReadWithData(path, versionData)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("unable to get secret from Hashicorp Vault: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
respData, ok := resp.Data["data"].(map[string]interface{})
|
||||||
|
|
||||||
|
if !ok {
|
||||||
|
return "", errors.New("Hashicorp Vault response does not contain data")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(respData) != 1 {
|
||||||
|
return "", errors.New("only one key/value pair is allowed in each Hashicorp Vault secret")
|
||||||
|
}
|
||||||
|
|
||||||
|
// get secret regardless of key in map
|
||||||
|
var s interface{}
|
||||||
|
for _, d := range respData {
|
||||||
|
s = d
|
||||||
|
}
|
||||||
|
|
||||||
|
secret, ok := s.(string)
|
||||||
|
|
||||||
|
if !ok {
|
||||||
|
return "", errors.New("Hashicorp Vault response data is not in string format")
|
||||||
|
}
|
||||||
|
|
||||||
|
return secret, nil
|
||||||
|
}
|
||||||
|
|
||||||
func usingApproleAuth(roleID, secretID string) bool {
|
func usingApproleAuth(roleID, secretID string) bool {
|
||||||
return roleID != "" && secretID != ""
|
return roleID != "" && secretID != ""
|
||||||
|
|
Loading…
Reference in New Issue