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:
parent
159255b5a6
commit
62c69f8e19
|
@ -45,7 +45,9 @@ type InitStatusResponse struct {
|
|||
}
|
||||
|
||||
type InitResponse struct {
|
||||
Keys []string `json:"keys"`
|
||||
RecoveryKeys []string `json:"recovery_keys"`
|
||||
RootToken string `json:"root_token"`
|
||||
Keys []string `json:"keys"`
|
||||
KeysB64 []string `json:"keys_base64"`
|
||||
RecoveryKeys []string `json:"recovery_keys"`
|
||||
RecoveryKeysB64 []string `json:"recovery_keys_base64"`
|
||||
RootToken string `json:"root_token"`
|
||||
}
|
||||
|
|
|
@ -190,11 +190,13 @@ type RekeyUpdateResponse struct {
|
|||
Nonce string
|
||||
Complete bool
|
||||
Keys []string
|
||||
KeysB64 []string `json:"keys_base64"`
|
||||
PGPFingerprints []string `json:"pgp_fingerprints"`
|
||||
Backup bool
|
||||
}
|
||||
|
||||
type RekeyRetrieveResponse struct {
|
||||
Nonce string
|
||||
Keys map[string][]string
|
||||
Nonce string
|
||||
Keys map[string][]string
|
||||
KeysB64 map[string][]string `json:"keys_base64"`
|
||||
}
|
||||
|
|
|
@ -192,10 +192,20 @@ func (c *InitCommand) runInit(check bool, initRequest *api.InitRequest) int {
|
|||
}
|
||||
|
||||
for i, key := range resp.Keys {
|
||||
c.Ui.Output(fmt.Sprintf("Unseal Key %d: %s", i+1, key))
|
||||
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))
|
||||
}
|
||||
}
|
||||
for i, key := range resp.RecoveryKeys {
|
||||
c.Ui.Output(fmt.Sprintf("Recovery Key %d: %s", i+1, key))
|
||||
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("Initial Root Token: %s", resp.RootToken))
|
||||
|
|
|
@ -244,5 +244,5 @@ func TestInit_PGP(t *testing.T) {
|
|||
|
||||
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,
|
||||
fingerprints bool,
|
||||
backupKeys map[string][]string,
|
||||
backupKeysB64 map[string][]string,
|
||||
core *vault.Core) {
|
||||
|
||||
decoder := base64.StdEncoding
|
||||
priv1Bytes, err := decoder.DecodeString(pgpkeys.TestPrivKey1)
|
||||
if err != nil {
|
||||
|
@ -87,89 +89,106 @@ func parseDecryptAndTestUnsealKeys(t *testing.T,
|
|||
priv3Bytes,
|
||||
}
|
||||
|
||||
var re *regexp.Regexp
|
||||
if fingerprints {
|
||||
re, err = regexp.Compile("\\s*Key\\s+\\d+\\s+fingerprint:\\s+([0-9a-fA-F]+);\\s+value:\\s+(.*)")
|
||||
} else {
|
||||
re, err = regexp.Compile("\\s*Key\\s+\\d+:\\s+(.*)")
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("Error compiling regex: %s", err)
|
||||
}
|
||||
matches := re.FindAllStringSubmatch(input, -1)
|
||||
if len(matches) != 4 {
|
||||
t.Fatalf("Unexpected number of keys returned, got %d, matches was \n\n%#v\n\n, input was \n\n%s\n\n", len(matches), matches, input)
|
||||
}
|
||||
|
||||
encodedKeys := []string{}
|
||||
matchedFingerprints := []string{}
|
||||
for _, tuple := range matches {
|
||||
testFunc := func(b64 bool, bkeys map[string][]string) {
|
||||
var re *regexp.Regexp
|
||||
if fingerprints {
|
||||
if len(tuple) != 3 {
|
||||
t.Fatalf("Key not found: %#v", tuple)
|
||||
if b64 {
|
||||
re, err = regexp.Compile("\\s*Key\\s+\\d+\\s+fingerprint:\\s+([0-9a-fA-F]+);\\s+value\\s+\\(base64\\):\\s+(.*)")
|
||||
} else {
|
||||
re, err = regexp.Compile("\\s*Key\\s+\\d+\\s+fingerprint:\\s+([0-9a-fA-F]+);\\s+value\\s+\\(hex\\)\\s+:\\s+(.*)")
|
||||
}
|
||||
matchedFingerprints = append(matchedFingerprints, tuple[1])
|
||||
encodedKeys = append(encodedKeys, tuple[2])
|
||||
} else {
|
||||
if len(tuple) != 2 {
|
||||
t.Fatalf("Key not found: %#v", tuple)
|
||||
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 {
|
||||
t.Fatalf("Error compiling regex: %s", err)
|
||||
}
|
||||
matches := re.FindAllStringSubmatch(input, -1)
|
||||
if len(matches) != 4 {
|
||||
t.Fatalf("Unexpected number of keys returned, got %d, matches was \n\n%#v\n\n, input was \n\n%s\n\n", len(matches), matches, input)
|
||||
}
|
||||
|
||||
encodedKeys := []string{}
|
||||
matchedFingerprints := []string{}
|
||||
for _, tuple := range matches {
|
||||
if fingerprints {
|
||||
if len(tuple) != 3 {
|
||||
t.Fatalf("Key not found: %#v", tuple)
|
||||
}
|
||||
matchedFingerprints = append(matchedFingerprints, tuple[1])
|
||||
encodedKeys = append(encodedKeys, tuple[2])
|
||||
} else {
|
||||
if len(tuple) != 2 {
|
||||
t.Fatalf("Key not found: %#v", tuple)
|
||||
}
|
||||
encodedKeys = append(encodedKeys, tuple[1])
|
||||
}
|
||||
}
|
||||
|
||||
if bkeys != nil && len(matchedFingerprints) != 0 {
|
||||
testMap := map[string][]string{}
|
||||
for i, v := range matchedFingerprints {
|
||||
testMap[v] = append(testMap[v], encodedKeys[i])
|
||||
sort.Strings(testMap[v])
|
||||
}
|
||||
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, bkeys)
|
||||
}
|
||||
}
|
||||
|
||||
unsealKeys := []string{}
|
||||
ptBuf := bytes.NewBuffer(nil)
|
||||
for i, privKeyBytes := range privBytes {
|
||||
if i > 2 {
|
||||
break
|
||||
}
|
||||
ptBuf.Reset()
|
||||
entity, err := openpgp.ReadEntity(packet.NewReader(bytes.NewBuffer(privKeyBytes)))
|
||||
if err != nil {
|
||||
t.Fatalf("Error parsing private key %d: %s", i, err)
|
||||
}
|
||||
var keyBytes []byte
|
||||
if b64 {
|
||||
keyBytes, err = base64.StdEncoding.DecodeString(encodedKeys[i])
|
||||
} else {
|
||||
keyBytes, err = hex.DecodeString(encodedKeys[i])
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("Error decoding key %d: %s", i, err)
|
||||
}
|
||||
entityList := &openpgp.EntityList{entity}
|
||||
md, err := openpgp.ReadMessage(bytes.NewBuffer(keyBytes), entityList, nil, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Error decrypting with key %d (%s): %s", i, encodedKeys[i], err)
|
||||
}
|
||||
ptBuf.ReadFrom(md.UnverifiedBody)
|
||||
unsealKeys = append(unsealKeys, ptBuf.String())
|
||||
}
|
||||
|
||||
err = core.Seal(rootToken)
|
||||
if err != nil {
|
||||
t.Fatalf("Error sealing vault with provided root token: %s", err)
|
||||
}
|
||||
|
||||
for i, unsealKey := range unsealKeys {
|
||||
unsealBytes, err := hex.DecodeString(unsealKey)
|
||||
if err != nil {
|
||||
t.Fatalf("Error hex decoding unseal key %s: %s", unsealKey, err)
|
||||
}
|
||||
unsealed, err := core.Unseal(unsealBytes)
|
||||
if err != nil {
|
||||
t.Fatalf("Error using unseal key %s: %s", unsealKey, err)
|
||||
}
|
||||
if i >= 2 && !unsealed {
|
||||
t.Fatalf("Error: Provided two unseal keys but core is not unsealed")
|
||||
}
|
||||
encodedKeys = append(encodedKeys, tuple[1])
|
||||
}
|
||||
}
|
||||
|
||||
if backupKeys != nil && len(matchedFingerprints) != 0 {
|
||||
testMap := map[string][]string{}
|
||||
for i, v := range matchedFingerprints {
|
||||
testMap[v] = append(testMap[v], encodedKeys[i])
|
||||
sort.Strings(testMap[v])
|
||||
}
|
||||
if !reflect.DeepEqual(testMap, backupKeys) {
|
||||
t.Fatalf("test map and backup map do not match, test map is\n%#v\nbackup map is\n%#v", testMap, backupKeys)
|
||||
}
|
||||
}
|
||||
|
||||
unsealKeys := []string{}
|
||||
ptBuf := bytes.NewBuffer(nil)
|
||||
for i, privKeyBytes := range privBytes {
|
||||
if i > 2 {
|
||||
break
|
||||
}
|
||||
ptBuf.Reset()
|
||||
entity, err := openpgp.ReadEntity(packet.NewReader(bytes.NewBuffer(privKeyBytes)))
|
||||
if err != nil {
|
||||
t.Fatalf("Error parsing private key %d: %s", i, err)
|
||||
}
|
||||
keyBytes, err := hex.DecodeString(encodedKeys[i])
|
||||
if err != nil {
|
||||
t.Fatalf("Error hex-decoding key %d: %s", i, err)
|
||||
}
|
||||
entityList := &openpgp.EntityList{entity}
|
||||
md, err := openpgp.ReadMessage(bytes.NewBuffer(keyBytes), entityList, nil, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Error decrypting with key %d (%s): %s", i, encodedKeys[i], err)
|
||||
}
|
||||
ptBuf.ReadFrom(md.UnverifiedBody)
|
||||
unsealKeys = append(unsealKeys, ptBuf.String())
|
||||
}
|
||||
|
||||
err = core.Seal(rootToken)
|
||||
if err != nil {
|
||||
t.Fatalf("Error sealing vault with provided root token: %s", err)
|
||||
}
|
||||
|
||||
for i, unsealKey := range unsealKeys {
|
||||
unsealBytes, err := hex.DecodeString(unsealKey)
|
||||
if err != nil {
|
||||
t.Fatalf("Error hex decoding unseal key %s: %s", unsealKey, err)
|
||||
}
|
||||
unsealed, err := core.Unseal(unsealBytes)
|
||||
if err != nil {
|
||||
t.Fatalf("Error using unseal key %s: %s", unsealKey, err)
|
||||
}
|
||||
if i >= 2 && !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,
|
||||
SecretThreshold: threshold,
|
||||
PGPKeys: pgpKeys,
|
||||
Backup: backup,
|
||||
})
|
||||
} else {
|
||||
rekeyStatus, err = client.Sys().RekeyInit(&api.RekeyInitRequest{
|
||||
SecretShares: shares,
|
||||
SecretThreshold: threshold,
|
||||
PGPKeys: pgpKeys,
|
||||
Backup: backup,
|
||||
})
|
||||
}
|
||||
if err != nil {
|
||||
|
@ -158,11 +160,25 @@ func (c *RekeyCommand) Run(args []string) int {
|
|||
// Space between the key prompt, if any, and the output
|
||||
c.Ui.Output("\n")
|
||||
// Provide the keys
|
||||
var haveB64 bool
|
||||
if result.KeysB64 != nil && len(result.KeysB64) == len(result.Keys) {
|
||||
haveB64 = true
|
||||
}
|
||||
for i, key := range result.Keys {
|
||||
if len(result.PGPFingerprints) > 0 {
|
||||
c.Ui.Output(fmt.Sprintf("Key %d fingerprint: %s; value: %s", i+1, result.PGPFingerprints[i], key))
|
||||
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))
|
||||
}
|
||||
} else {
|
||||
c.Ui.Output(fmt.Sprintf("Key %d: %s", i+1, key))
|
||||
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 {
|
||||
c.Ui.Output(fmt.Sprintf("Key %d: %s", i+1, key))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -227,7 +227,8 @@ func TestRekey_init_pgp(t *testing.T) {
|
|||
}
|
||||
|
||||
type backupStruct struct {
|
||||
Keys map[string][]string
|
||||
Keys map[string][]string
|
||||
KeysB64 map[string][]string
|
||||
}
|
||||
backupVals := &backupStruct{}
|
||||
|
||||
|
@ -247,6 +248,7 @@ func TestRekey_init_pgp(t *testing.T) {
|
|||
}
|
||||
|
||||
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
|
||||
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
|
||||
for k, _ := range backupVals.Keys {
|
||||
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
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"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"+
|
||||
"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"+
|
||||
"Unseal Key: %s\nRoot Token: %s\n",
|
||||
"Unseal Key (hex) : %s\nUnseal Key (base64): %s\nRoot Token: %s\n",
|
||||
hex.EncodeToString(init.SecretShares[0]),
|
||||
base64.StdEncoding.EncodeToString(init.SecretShares[0]),
|
||||
init.RootToken,
|
||||
))
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package http
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
@ -123,13 +124,20 @@ func handleSysGenerateRootUpdate(core *vault.Core) http.Handler {
|
|||
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)
|
||||
if err != nil {
|
||||
respondError(
|
||||
w, http.StatusBadRequest,
|
||||
errors.New("'key' must be a valid hex-string"))
|
||||
return
|
||||
// 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 {
|
||||
respondError(
|
||||
w, http.StatusBadRequest,
|
||||
errors.New("'key' must be a valid hex or base64 string"))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Use the key to make progress on root generation
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package http
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
@ -93,19 +94,24 @@ func handleSysInitPut(core *vault.Core, w http.ResponseWriter, r *http.Request)
|
|||
|
||||
// Encode the keys
|
||||
keys := make([]string, 0, len(result.SecretShares))
|
||||
keysB64 := make([]string, 0, len(result.SecretShares))
|
||||
for _, k := range result.SecretShares {
|
||||
keys = append(keys, hex.EncodeToString(k))
|
||||
keysB64 = append(keysB64, base64.StdEncoding.EncodeToString(k))
|
||||
}
|
||||
|
||||
resp := &InitResponse{
|
||||
Keys: keys,
|
||||
KeysB64: keysB64,
|
||||
RootToken: result.RootToken,
|
||||
}
|
||||
|
||||
if len(result.RecoveryShares) > 0 {
|
||||
resp.RecoveryKeys = make([]string, 0, len(result.RecoveryShares))
|
||||
resp.RecoveryKeysB64 = make([]string, 0, len(result.RecoveryShares))
|
||||
for _, k := range result.RecoveryShares {
|
||||
resp.RecoveryKeys = append(resp.RecoveryKeys, hex.EncodeToString(k))
|
||||
resp.RecoveryKeysB64 = append(resp.RecoveryKeysB64, base64.StdEncoding.EncodeToString(k))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -125,9 +131,11 @@ type InitRequest struct {
|
|||
}
|
||||
|
||||
type InitResponse struct {
|
||||
Keys []string `json:"keys"`
|
||||
RecoveryKeys []string `json:"recovery_keys,omitempty"`
|
||||
RootToken string `json:"root_token"`
|
||||
Keys []string `json:"keys"`
|
||||
KeysB64 []string `json:"keys_base64"`
|
||||
RecoveryKeys []string `json:"recovery_keys,omitempty"`
|
||||
RecoveryKeysB64 []string `json:"recovery_keys_base64,omitempty"`
|
||||
RootToken string `json:"root_token"`
|
||||
}
|
||||
|
||||
type InitStatusResponse struct {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package http
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
@ -146,13 +147,20 @@ func handleSysRekeyUpdate(core *vault.Core, recovery bool) http.Handler {
|
|||
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)
|
||||
if err != nil {
|
||||
respondError(
|
||||
w, http.StatusBadRequest,
|
||||
errors.New("'key' must be a valid hex-string"))
|
||||
return
|
||||
// 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 {
|
||||
respondError(
|
||||
w, http.StatusBadRequest,
|
||||
errors.New("'key' must be a valid hex or base64 string"))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Use the key to make progress on rekey
|
||||
|
@ -167,16 +175,18 @@ func handleSysRekeyUpdate(core *vault.Core, recovery bool) http.Handler {
|
|||
if result != nil {
|
||||
resp.Complete = true
|
||||
resp.Nonce = req.Nonce
|
||||
resp.Backup = result.Backup
|
||||
resp.PGPFingerprints = result.PGPFingerprints
|
||||
|
||||
// Encode the keys
|
||||
keys := make([]string, 0, len(result.SecretShares))
|
||||
keysB64 := make([]string, 0, len(result.SecretShares))
|
||||
for _, k := range result.SecretShares {
|
||||
keys = append(keys, hex.EncodeToString(k))
|
||||
keysB64 = append(keysB64, base64.StdEncoding.EncodeToString(k))
|
||||
}
|
||||
resp.Keys = keys
|
||||
|
||||
resp.Backup = result.Backup
|
||||
resp.PGPFingerprints = result.PGPFingerprints
|
||||
resp.KeysB64 = keysB64
|
||||
}
|
||||
respondOk(w, resp)
|
||||
})
|
||||
|
@ -210,6 +220,7 @@ type RekeyUpdateResponse struct {
|
|||
Nonce string `json:"nonce"`
|
||||
Complete bool `json:"complete"`
|
||||
Keys []string `json:"keys"`
|
||||
KeysB64 []string `json:"keys_base64"`
|
||||
PGPFingerprints []string `json:"pgp_fingerprints"`
|
||||
Backup bool `json:"backup"`
|
||||
}
|
||||
|
|
|
@ -180,8 +180,13 @@ func TestSysRekey_Update(t *testing.T) {
|
|||
if len(keys) != 5 {
|
||||
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_base64")
|
||||
if !reflect.DeepEqual(actual, expected) {
|
||||
t.Fatalf("\nexpected: %#v\nactual: %#v", expected, actual)
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package http
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
@ -97,13 +98,20 @@ func handleSysUnseal(core *vault.Core) http.Handler {
|
|||
}
|
||||
core.ResetUnsealProcess()
|
||||
} 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)
|
||||
if err != nil {
|
||||
respondError(
|
||||
w, http.StatusBadRequest,
|
||||
errors.New("'key' must be a valid hex-string"))
|
||||
return
|
||||
// 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 {
|
||||
respondError(
|
||||
w, http.StatusBadRequest,
|
||||
errors.New("'key' must be a valid hex or base64 string"))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Attempt the unseal
|
||||
|
|
|
@ -1490,3 +1490,9 @@ func (c *Core) SealAccess() *SealAccess {
|
|||
func (c *Core) Logger() *log.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
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"strings"
|
||||
"sync"
|
||||
|
@ -607,11 +609,28 @@ func (b *SystemBackend) handleRekeyRetrieve(
|
|||
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
|
||||
resp := &logical.Response{
|
||||
Data: map[string]interface{}{
|
||||
"nonce": backup.Nonce,
|
||||
"keys": backup.Keys,
|
||||
"nonce": backup.Nonce,
|
||||
"keys": backup.Keys,
|
||||
"keys_base64": keysB64,
|
||||
},
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue