mirror of
https://github.com/optim-enterprises-bv/vault.git
synced 2025-11-01 02:57:59 +00:00
Provide base64 keys in addition to hex encoded. (#1734)
* Provide base64 keys in addition to hex encoded. Accept these at unseal/rekey time. Also fix a bug where backup would not be honored when doing a rekey with no operation currently ongoing.
This commit is contained in:
@@ -46,6 +46,8 @@ type InitStatusResponse struct {
|
|||||||
|
|
||||||
type InitResponse struct {
|
type InitResponse struct {
|
||||||
Keys []string `json:"keys"`
|
Keys []string `json:"keys"`
|
||||||
|
KeysB64 []string `json:"keys_base64"`
|
||||||
RecoveryKeys []string `json:"recovery_keys"`
|
RecoveryKeys []string `json:"recovery_keys"`
|
||||||
|
RecoveryKeysB64 []string `json:"recovery_keys_base64"`
|
||||||
RootToken string `json:"root_token"`
|
RootToken string `json:"root_token"`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -190,6 +190,7 @@ type RekeyUpdateResponse struct {
|
|||||||
Nonce string
|
Nonce string
|
||||||
Complete bool
|
Complete bool
|
||||||
Keys []string
|
Keys []string
|
||||||
|
KeysB64 []string `json:"keys_base64"`
|
||||||
PGPFingerprints []string `json:"pgp_fingerprints"`
|
PGPFingerprints []string `json:"pgp_fingerprints"`
|
||||||
Backup bool
|
Backup bool
|
||||||
}
|
}
|
||||||
@@ -197,4 +198,5 @@ type RekeyUpdateResponse struct {
|
|||||||
type RekeyRetrieveResponse struct {
|
type RekeyRetrieveResponse struct {
|
||||||
Nonce string
|
Nonce string
|
||||||
Keys map[string][]string
|
Keys map[string][]string
|
||||||
|
KeysB64 map[string][]string `json:"keys_base64"`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -192,11 +192,21 @@ func (c *InitCommand) runInit(check bool, initRequest *api.InitRequest) int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for i, key := range resp.Keys {
|
for i, key := range resp.Keys {
|
||||||
|
if resp.KeysB64 != nil && len(resp.KeysB64) == len(resp.Keys) {
|
||||||
|
c.Ui.Output(fmt.Sprintf("Unseal Key %d (hex) : %s", i+1, key))
|
||||||
|
c.Ui.Output(fmt.Sprintf("Unseal Key %d (base64): %s", i+1, resp.KeysB64[i]))
|
||||||
|
} else {
|
||||||
c.Ui.Output(fmt.Sprintf("Unseal Key %d: %s", i+1, key))
|
c.Ui.Output(fmt.Sprintf("Unseal Key %d: %s", i+1, key))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
for i, key := range resp.RecoveryKeys {
|
for i, key := range resp.RecoveryKeys {
|
||||||
|
if resp.RecoveryKeysB64 != nil && len(resp.RecoveryKeysB64) == len(resp.RecoveryKeys) {
|
||||||
|
c.Ui.Output(fmt.Sprintf("Recovery Key %d (hex) : %s", i+1, key))
|
||||||
|
c.Ui.Output(fmt.Sprintf("Recovery Key %d (base64): %s", i+1, resp.RecoveryKeysB64[i]))
|
||||||
|
} else {
|
||||||
c.Ui.Output(fmt.Sprintf("Recovery Key %d: %s", i+1, key))
|
c.Ui.Output(fmt.Sprintf("Recovery Key %d: %s", i+1, key))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
c.Ui.Output(fmt.Sprintf("Initial Root Token: %s", resp.RootToken))
|
c.Ui.Output(fmt.Sprintf("Initial Root Token: %s", resp.RootToken))
|
||||||
|
|
||||||
|
|||||||
@@ -244,5 +244,5 @@ func TestInit_PGP(t *testing.T) {
|
|||||||
|
|
||||||
rootToken := matches[0][1]
|
rootToken := matches[0][1]
|
||||||
|
|
||||||
parseDecryptAndTestUnsealKeys(t, ui.OutputWriter.String(), rootToken, false, nil, core)
|
parseDecryptAndTestUnsealKeys(t, ui.OutputWriter.String(), rootToken, false, nil, nil, core)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -66,7 +66,9 @@ func parseDecryptAndTestUnsealKeys(t *testing.T,
|
|||||||
input, rootToken string,
|
input, rootToken string,
|
||||||
fingerprints bool,
|
fingerprints bool,
|
||||||
backupKeys map[string][]string,
|
backupKeys map[string][]string,
|
||||||
|
backupKeysB64 map[string][]string,
|
||||||
core *vault.Core) {
|
core *vault.Core) {
|
||||||
|
|
||||||
decoder := base64.StdEncoding
|
decoder := base64.StdEncoding
|
||||||
priv1Bytes, err := decoder.DecodeString(pgpkeys.TestPrivKey1)
|
priv1Bytes, err := decoder.DecodeString(pgpkeys.TestPrivKey1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -87,11 +89,20 @@ func parseDecryptAndTestUnsealKeys(t *testing.T,
|
|||||||
priv3Bytes,
|
priv3Bytes,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
testFunc := func(b64 bool, bkeys map[string][]string) {
|
||||||
var re *regexp.Regexp
|
var re *regexp.Regexp
|
||||||
if fingerprints {
|
if fingerprints {
|
||||||
re, err = regexp.Compile("\\s*Key\\s+\\d+\\s+fingerprint:\\s+([0-9a-fA-F]+);\\s+value:\\s+(.*)")
|
if b64 {
|
||||||
|
re, err = regexp.Compile("\\s*Key\\s+\\d+\\s+fingerprint:\\s+([0-9a-fA-F]+);\\s+value\\s+\\(base64\\):\\s+(.*)")
|
||||||
} else {
|
} else {
|
||||||
re, err = regexp.Compile("\\s*Key\\s+\\d+:\\s+(.*)")
|
re, err = regexp.Compile("\\s*Key\\s+\\d+\\s+fingerprint:\\s+([0-9a-fA-F]+);\\s+value\\s+\\(hex\\)\\s+:\\s+(.*)")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if b64 {
|
||||||
|
re, err = regexp.Compile("\\s*Key\\s+\\d+\\s\\(base64\\):\\s+(.*)")
|
||||||
|
} else {
|
||||||
|
re, err = regexp.Compile("\\s*Key\\s+\\d+\\s\\(hex\\)\\s+:\\s+(.*)")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Error compiling regex: %s", err)
|
t.Fatalf("Error compiling regex: %s", err)
|
||||||
@@ -118,14 +129,14 @@ func parseDecryptAndTestUnsealKeys(t *testing.T,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if backupKeys != nil && len(matchedFingerprints) != 0 {
|
if bkeys != nil && len(matchedFingerprints) != 0 {
|
||||||
testMap := map[string][]string{}
|
testMap := map[string][]string{}
|
||||||
for i, v := range matchedFingerprints {
|
for i, v := range matchedFingerprints {
|
||||||
testMap[v] = append(testMap[v], encodedKeys[i])
|
testMap[v] = append(testMap[v], encodedKeys[i])
|
||||||
sort.Strings(testMap[v])
|
sort.Strings(testMap[v])
|
||||||
}
|
}
|
||||||
if !reflect.DeepEqual(testMap, backupKeys) {
|
if !reflect.DeepEqual(testMap, bkeys) {
|
||||||
t.Fatalf("test map and backup map do not match, test map is\n%#v\nbackup map is\n%#v", testMap, backupKeys)
|
t.Fatalf("test map and backup map do not match, test map is\n%#v\nbackup map is\n%#v", testMap, bkeys)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -140,9 +151,14 @@ func parseDecryptAndTestUnsealKeys(t *testing.T,
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Error parsing private key %d: %s", i, err)
|
t.Fatalf("Error parsing private key %d: %s", i, err)
|
||||||
}
|
}
|
||||||
keyBytes, err := hex.DecodeString(encodedKeys[i])
|
var keyBytes []byte
|
||||||
|
if b64 {
|
||||||
|
keyBytes, err = base64.StdEncoding.DecodeString(encodedKeys[i])
|
||||||
|
} else {
|
||||||
|
keyBytes, err = hex.DecodeString(encodedKeys[i])
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Error hex-decoding key %d: %s", i, err)
|
t.Fatalf("Error decoding key %d: %s", i, err)
|
||||||
}
|
}
|
||||||
entityList := &openpgp.EntityList{entity}
|
entityList := &openpgp.EntityList{entity}
|
||||||
md, err := openpgp.ReadMessage(bytes.NewBuffer(keyBytes), entityList, nil, nil)
|
md, err := openpgp.ReadMessage(bytes.NewBuffer(keyBytes), entityList, nil, nil)
|
||||||
@@ -171,5 +187,8 @@ func parseDecryptAndTestUnsealKeys(t *testing.T,
|
|||||||
t.Fatalf("Error: Provided two unseal keys but core is not unsealed")
|
t.Fatalf("Error: Provided two unseal keys but core is not unsealed")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
testFunc(false, backupKeys)
|
||||||
|
testFunc(true, backupKeysB64)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -93,12 +93,14 @@ func (c *RekeyCommand) Run(args []string) int {
|
|||||||
SecretShares: shares,
|
SecretShares: shares,
|
||||||
SecretThreshold: threshold,
|
SecretThreshold: threshold,
|
||||||
PGPKeys: pgpKeys,
|
PGPKeys: pgpKeys,
|
||||||
|
Backup: backup,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
rekeyStatus, err = client.Sys().RekeyInit(&api.RekeyInitRequest{
|
rekeyStatus, err = client.Sys().RekeyInit(&api.RekeyInitRequest{
|
||||||
SecretShares: shares,
|
SecretShares: shares,
|
||||||
SecretThreshold: threshold,
|
SecretThreshold: threshold,
|
||||||
PGPKeys: pgpKeys,
|
PGPKeys: pgpKeys,
|
||||||
|
Backup: backup,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -158,13 +160,27 @@ func (c *RekeyCommand) Run(args []string) int {
|
|||||||
// Space between the key prompt, if any, and the output
|
// Space between the key prompt, if any, and the output
|
||||||
c.Ui.Output("\n")
|
c.Ui.Output("\n")
|
||||||
// Provide the keys
|
// Provide the keys
|
||||||
|
var haveB64 bool
|
||||||
|
if result.KeysB64 != nil && len(result.KeysB64) == len(result.Keys) {
|
||||||
|
haveB64 = true
|
||||||
|
}
|
||||||
for i, key := range result.Keys {
|
for i, key := range result.Keys {
|
||||||
if len(result.PGPFingerprints) > 0 {
|
if len(result.PGPFingerprints) > 0 {
|
||||||
|
if haveB64 {
|
||||||
|
c.Ui.Output(fmt.Sprintf("Key %d fingerprint: %s; value (hex) : %s", i+1, result.PGPFingerprints[i], key))
|
||||||
|
c.Ui.Output(fmt.Sprintf("Key %d fingerprint: %s; value (base64): %s", i+1, result.PGPFingerprints[i], result.KeysB64[i]))
|
||||||
|
} else {
|
||||||
c.Ui.Output(fmt.Sprintf("Key %d fingerprint: %s; value: %s", i+1, result.PGPFingerprints[i], key))
|
c.Ui.Output(fmt.Sprintf("Key %d fingerprint: %s; value: %s", i+1, result.PGPFingerprints[i], key))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if haveB64 {
|
||||||
|
c.Ui.Output(fmt.Sprintf("Key %d (hex) : %s", i+1, key))
|
||||||
|
c.Ui.Output(fmt.Sprintf("Key %d (base64): %s", i+1, result.KeysB64[i]))
|
||||||
} else {
|
} else {
|
||||||
c.Ui.Output(fmt.Sprintf("Key %d: %s", i+1, key))
|
c.Ui.Output(fmt.Sprintf("Key %d: %s", i+1, key))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
c.Ui.Output(fmt.Sprintf("\nOperation nonce: %s", result.Nonce))
|
c.Ui.Output(fmt.Sprintf("\nOperation nonce: %s", result.Nonce))
|
||||||
|
|
||||||
|
|||||||
@@ -228,6 +228,7 @@ func TestRekey_init_pgp(t *testing.T) {
|
|||||||
|
|
||||||
type backupStruct struct {
|
type backupStruct struct {
|
||||||
Keys map[string][]string
|
Keys map[string][]string
|
||||||
|
KeysB64 map[string][]string
|
||||||
}
|
}
|
||||||
backupVals := &backupStruct{}
|
backupVals := &backupStruct{}
|
||||||
|
|
||||||
@@ -247,6 +248,7 @@ func TestRekey_init_pgp(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
backupVals.Keys = resp.Data["keys"].(map[string][]string)
|
backupVals.Keys = resp.Data["keys"].(map[string][]string)
|
||||||
|
backupVals.KeysB64 = resp.Data["keys_base64"].(map[string][]string)
|
||||||
|
|
||||||
// Now delete and try again; the values should be inaccessible
|
// Now delete and try again; the values should be inaccessible
|
||||||
req = logical.TestRequest(t, logical.DeleteOperation, "rekey/backup")
|
req = logical.TestRequest(t, logical.DeleteOperation, "rekey/backup")
|
||||||
@@ -269,7 +271,8 @@ func TestRekey_init_pgp(t *testing.T) {
|
|||||||
// Sort, because it'll be tested with DeepEqual later
|
// Sort, because it'll be tested with DeepEqual later
|
||||||
for k, _ := range backupVals.Keys {
|
for k, _ := range backupVals.Keys {
|
||||||
sort.Strings(backupVals.Keys[k])
|
sort.Strings(backupVals.Keys[k])
|
||||||
|
sort.Strings(backupVals.KeysB64[k])
|
||||||
}
|
}
|
||||||
|
|
||||||
parseDecryptAndTestUnsealKeys(t, ui.OutputWriter.String(), token, true, backupVals.Keys, core)
|
parseDecryptAndTestUnsealKeys(t, ui.OutputWriter.String(), token, true, backupVals.Keys, backupVals.KeysB64, core)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package command
|
package command
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/base64"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
@@ -489,8 +490,9 @@ func (c *ServerCommand) Run(args []string) int {
|
|||||||
" "+export+" VAULT_ADDR="+quote+"http://"+config.Listeners[0].Config["address"]+quote+"\n\n"+
|
" "+export+" VAULT_ADDR="+quote+"http://"+config.Listeners[0].Config["address"]+quote+"\n\n"+
|
||||||
"The unseal key and root token are reproduced below in case you\n"+
|
"The unseal key and root token are reproduced below in case you\n"+
|
||||||
"want to seal/unseal the Vault or play with authentication.\n\n"+
|
"want to seal/unseal the Vault or play with authentication.\n\n"+
|
||||||
"Unseal Key: %s\nRoot Token: %s\n",
|
"Unseal Key (hex) : %s\nUnseal Key (base64): %s\nRoot Token: %s\n",
|
||||||
hex.EncodeToString(init.SecretShares[0]),
|
hex.EncodeToString(init.SecretShares[0]),
|
||||||
|
base64.StdEncoding.EncodeToString(init.SecretShares[0]),
|
||||||
init.RootToken,
|
init.RootToken,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package http
|
package http
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/base64"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
@@ -123,14 +124,21 @@ func handleSysGenerateRootUpdate(core *vault.Core) http.Handler {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decode the key, which is hex encoded
|
// Decode the key, which is base64 or hex encoded
|
||||||
|
min, max := core.BarrierKeyLength()
|
||||||
key, err := hex.DecodeString(req.Key)
|
key, err := hex.DecodeString(req.Key)
|
||||||
|
// We check min and max here to ensure that a string that is base64
|
||||||
|
// encoded but also valid hex will not be valid and we instead base64
|
||||||
|
// decode it
|
||||||
|
if err != nil || len(key) < min || len(key) > max {
|
||||||
|
key, err = base64.StdEncoding.DecodeString(req.Key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
respondError(
|
respondError(
|
||||||
w, http.StatusBadRequest,
|
w, http.StatusBadRequest,
|
||||||
errors.New("'key' must be a valid hex-string"))
|
errors.New("'key' must be a valid hex or base64 string"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Use the key to make progress on root generation
|
// Use the key to make progress on root generation
|
||||||
result, err := core.GenerateRootUpdate(key, req.Nonce)
|
result, err := core.GenerateRootUpdate(key, req.Nonce)
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package http
|
package http
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/base64"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
@@ -93,19 +94,24 @@ func handleSysInitPut(core *vault.Core, w http.ResponseWriter, r *http.Request)
|
|||||||
|
|
||||||
// Encode the keys
|
// Encode the keys
|
||||||
keys := make([]string, 0, len(result.SecretShares))
|
keys := make([]string, 0, len(result.SecretShares))
|
||||||
|
keysB64 := make([]string, 0, len(result.SecretShares))
|
||||||
for _, k := range result.SecretShares {
|
for _, k := range result.SecretShares {
|
||||||
keys = append(keys, hex.EncodeToString(k))
|
keys = append(keys, hex.EncodeToString(k))
|
||||||
|
keysB64 = append(keysB64, base64.StdEncoding.EncodeToString(k))
|
||||||
}
|
}
|
||||||
|
|
||||||
resp := &InitResponse{
|
resp := &InitResponse{
|
||||||
Keys: keys,
|
Keys: keys,
|
||||||
|
KeysB64: keysB64,
|
||||||
RootToken: result.RootToken,
|
RootToken: result.RootToken,
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(result.RecoveryShares) > 0 {
|
if len(result.RecoveryShares) > 0 {
|
||||||
resp.RecoveryKeys = make([]string, 0, len(result.RecoveryShares))
|
resp.RecoveryKeys = make([]string, 0, len(result.RecoveryShares))
|
||||||
|
resp.RecoveryKeysB64 = make([]string, 0, len(result.RecoveryShares))
|
||||||
for _, k := range result.RecoveryShares {
|
for _, k := range result.RecoveryShares {
|
||||||
resp.RecoveryKeys = append(resp.RecoveryKeys, hex.EncodeToString(k))
|
resp.RecoveryKeys = append(resp.RecoveryKeys, hex.EncodeToString(k))
|
||||||
|
resp.RecoveryKeysB64 = append(resp.RecoveryKeysB64, base64.StdEncoding.EncodeToString(k))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,7 +132,9 @@ type InitRequest struct {
|
|||||||
|
|
||||||
type InitResponse struct {
|
type InitResponse struct {
|
||||||
Keys []string `json:"keys"`
|
Keys []string `json:"keys"`
|
||||||
|
KeysB64 []string `json:"keys_base64"`
|
||||||
RecoveryKeys []string `json:"recovery_keys,omitempty"`
|
RecoveryKeys []string `json:"recovery_keys,omitempty"`
|
||||||
|
RecoveryKeysB64 []string `json:"recovery_keys_base64,omitempty"`
|
||||||
RootToken string `json:"root_token"`
|
RootToken string `json:"root_token"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package http
|
package http
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/base64"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
@@ -146,14 +147,21 @@ func handleSysRekeyUpdate(core *vault.Core, recovery bool) http.Handler {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decode the key, which is hex encoded
|
// Decode the key, which is base64 or hex encoded
|
||||||
|
min, max := core.BarrierKeyLength()
|
||||||
key, err := hex.DecodeString(req.Key)
|
key, err := hex.DecodeString(req.Key)
|
||||||
|
// We check min and max here to ensure that a string that is base64
|
||||||
|
// encoded but also valid hex will not be valid and we instead base64
|
||||||
|
// decode it
|
||||||
|
if err != nil || len(key) < min || len(key) > max {
|
||||||
|
key, err = base64.StdEncoding.DecodeString(req.Key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
respondError(
|
respondError(
|
||||||
w, http.StatusBadRequest,
|
w, http.StatusBadRequest,
|
||||||
errors.New("'key' must be a valid hex-string"))
|
errors.New("'key' must be a valid hex or base64 string"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Use the key to make progress on rekey
|
// Use the key to make progress on rekey
|
||||||
result, err := core.RekeyUpdate(key, req.Nonce, recovery)
|
result, err := core.RekeyUpdate(key, req.Nonce, recovery)
|
||||||
@@ -167,16 +175,18 @@ func handleSysRekeyUpdate(core *vault.Core, recovery bool) http.Handler {
|
|||||||
if result != nil {
|
if result != nil {
|
||||||
resp.Complete = true
|
resp.Complete = true
|
||||||
resp.Nonce = req.Nonce
|
resp.Nonce = req.Nonce
|
||||||
|
resp.Backup = result.Backup
|
||||||
|
resp.PGPFingerprints = result.PGPFingerprints
|
||||||
|
|
||||||
// Encode the keys
|
// Encode the keys
|
||||||
keys := make([]string, 0, len(result.SecretShares))
|
keys := make([]string, 0, len(result.SecretShares))
|
||||||
|
keysB64 := make([]string, 0, len(result.SecretShares))
|
||||||
for _, k := range result.SecretShares {
|
for _, k := range result.SecretShares {
|
||||||
keys = append(keys, hex.EncodeToString(k))
|
keys = append(keys, hex.EncodeToString(k))
|
||||||
|
keysB64 = append(keysB64, base64.StdEncoding.EncodeToString(k))
|
||||||
}
|
}
|
||||||
resp.Keys = keys
|
resp.Keys = keys
|
||||||
|
resp.KeysB64 = keysB64
|
||||||
resp.Backup = result.Backup
|
|
||||||
resp.PGPFingerprints = result.PGPFingerprints
|
|
||||||
}
|
}
|
||||||
respondOk(w, resp)
|
respondOk(w, resp)
|
||||||
})
|
})
|
||||||
@@ -210,6 +220,7 @@ type RekeyUpdateResponse struct {
|
|||||||
Nonce string `json:"nonce"`
|
Nonce string `json:"nonce"`
|
||||||
Complete bool `json:"complete"`
|
Complete bool `json:"complete"`
|
||||||
Keys []string `json:"keys"`
|
Keys []string `json:"keys"`
|
||||||
|
KeysB64 []string `json:"keys_base64"`
|
||||||
PGPFingerprints []string `json:"pgp_fingerprints"`
|
PGPFingerprints []string `json:"pgp_fingerprints"`
|
||||||
Backup bool `json:"backup"`
|
Backup bool `json:"backup"`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -180,8 +180,13 @@ func TestSysRekey_Update(t *testing.T) {
|
|||||||
if len(keys) != 5 {
|
if len(keys) != 5 {
|
||||||
t.Fatalf("bad: %#v", keys)
|
t.Fatalf("bad: %#v", keys)
|
||||||
}
|
}
|
||||||
|
keysB64 := actual["keys_base64"].([]interface{})
|
||||||
|
if len(keysB64) != 5 {
|
||||||
|
t.Fatalf("bad: %#v", keysB64)
|
||||||
|
}
|
||||||
|
|
||||||
delete(actual, "keys")
|
delete(actual, "keys")
|
||||||
|
delete(actual, "keys_base64")
|
||||||
if !reflect.DeepEqual(actual, expected) {
|
if !reflect.DeepEqual(actual, expected) {
|
||||||
t.Fatalf("\nexpected: %#v\nactual: %#v", expected, actual)
|
t.Fatalf("\nexpected: %#v\nactual: %#v", expected, actual)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package http
|
package http
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/base64"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
@@ -97,14 +98,21 @@ func handleSysUnseal(core *vault.Core) http.Handler {
|
|||||||
}
|
}
|
||||||
core.ResetUnsealProcess()
|
core.ResetUnsealProcess()
|
||||||
} else {
|
} else {
|
||||||
// Decode the key, which is hex encoded
|
// Decode the key, which is base64 or hex encoded
|
||||||
|
min, max := core.BarrierKeyLength()
|
||||||
key, err := hex.DecodeString(req.Key)
|
key, err := hex.DecodeString(req.Key)
|
||||||
|
// We check min and max here to ensure that a string that is base64
|
||||||
|
// encoded but also valid hex will not be valid and we instead base64
|
||||||
|
// decode it
|
||||||
|
if err != nil || len(key) < min || len(key) > max {
|
||||||
|
key, err = base64.StdEncoding.DecodeString(req.Key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
respondError(
|
respondError(
|
||||||
w, http.StatusBadRequest,
|
w, http.StatusBadRequest,
|
||||||
errors.New("'key' must be a valid hex-string"))
|
errors.New("'key' must be a valid hex or base64 string"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Attempt the unseal
|
// Attempt the unseal
|
||||||
if _, err := core.Unseal(key); err != nil {
|
if _, err := core.Unseal(key); err != nil {
|
||||||
|
|||||||
@@ -1490,3 +1490,9 @@ func (c *Core) SealAccess() *SealAccess {
|
|||||||
func (c *Core) Logger() *log.Logger {
|
func (c *Core) Logger() *log.Logger {
|
||||||
return c.logger
|
return c.logger
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Core) BarrierKeyLength() (min, max int) {
|
||||||
|
min, max = c.barrier.KeyLength()
|
||||||
|
max += shamir.ShareOverhead
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
package vault
|
package vault
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/base64"
|
||||||
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
@@ -607,11 +609,28 @@ func (b *SystemBackend) handleRekeyRetrieve(
|
|||||||
return logical.ErrorResponse("no backed-up keys found"), nil
|
return logical.ErrorResponse("no backed-up keys found"), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
keysB64 := map[string][]string{}
|
||||||
|
for k, v := range backup.Keys {
|
||||||
|
for _, j := range v {
|
||||||
|
currB64Keys := keysB64[k]
|
||||||
|
if currB64Keys == nil {
|
||||||
|
currB64Keys = []string{}
|
||||||
|
}
|
||||||
|
key, err := hex.DecodeString(j)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error decoding hex-encoded backup key: %v", err)
|
||||||
|
}
|
||||||
|
currB64Keys = append(currB64Keys, base64.StdEncoding.EncodeToString(key))
|
||||||
|
keysB64[k] = currB64Keys
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Format the status
|
// Format the status
|
||||||
resp := &logical.Response{
|
resp := &logical.Response{
|
||||||
Data: map[string]interface{}{
|
Data: map[string]interface{}{
|
||||||
"nonce": backup.Nonce,
|
"nonce": backup.Nonce,
|
||||||
"keys": backup.Keys,
|
"keys": backup.Keys,
|
||||||
|
"keys_base64": keysB64,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user