RootGeneration->GenerateRoot

This commit is contained in:
Jeff Mitchell 2016-01-15 10:55:35 -05:00
parent 3b100c5965
commit 973c888833
13 changed files with 215 additions and 216 deletions

View File

@ -1,25 +1,25 @@
package api
func (c *Sys) RootGenerationStatus() (*RootGenerationStatusResponse, error) {
r := c.c.NewRequest("GET", "/v1/sys/root-generation/attempt")
func (c *Sys) GenerateRootStatus() (*GenerateRootStatusResponse, error) {
r := c.c.NewRequest("GET", "/v1/sys/generate-root/attempt")
resp, err := c.c.RawRequest(r)
if err != nil {
return nil, err
}
defer resp.Body.Close()
var result RootGenerationStatusResponse
var result GenerateRootStatusResponse
err = resp.DecodeJSON(&result)
return &result, err
}
func (c *Sys) RootGenerationInit(otp, pgpKey string) error {
func (c *Sys) GenerateRootInit(otp, pgpKey string) error {
body := map[string]interface{}{
"otp": otp,
"pgp_key": pgpKey,
}
r := c.c.NewRequest("PUT", "/v1/sys/root-generation/attempt")
r := c.c.NewRequest("PUT", "/v1/sys/generate-root/attempt")
if err := r.SetJSONBody(body); err != nil {
return err
}
@ -31,8 +31,8 @@ func (c *Sys) RootGenerationInit(otp, pgpKey string) error {
return err
}
func (c *Sys) RootGenerationCancel() error {
r := c.c.NewRequest("DELETE", "/v1/sys/root-generation/attempt")
func (c *Sys) GenerateRootCancel() error {
r := c.c.NewRequest("DELETE", "/v1/sys/generate-root/attempt")
resp, err := c.c.RawRequest(r)
if err == nil {
defer resp.Body.Close()
@ -40,13 +40,13 @@ func (c *Sys) RootGenerationCancel() error {
return err
}
func (c *Sys) RootGenerationUpdate(shard, nonce string) (*RootGenerationStatusResponse, error) {
func (c *Sys) GenerateRootUpdate(shard, nonce string) (*GenerateRootStatusResponse, error) {
body := map[string]interface{}{
"key": shard,
"nonce": nonce,
}
r := c.c.NewRequest("PUT", "/v1/sys/root-generation/update")
r := c.c.NewRequest("PUT", "/v1/sys/generate-root/update")
if err := r.SetJSONBody(body); err != nil {
return nil, err
}
@ -57,12 +57,12 @@ func (c *Sys) RootGenerationUpdate(shard, nonce string) (*RootGenerationStatusRe
}
defer resp.Body.Close()
var result RootGenerationStatusResponse
var result GenerateRootStatusResponse
err = resp.DecodeJSON(&result)
return &result, err
}
type RootGenerationStatusResponse struct {
type GenerateRootStatusResponse struct {
Nonce string
Started bool
Progress int

View File

@ -75,7 +75,7 @@ func (c *GenerateRootCommand) Run(args []string) int {
}
// Check if the root generation is started
rootGenerationStatus, err := client.Sys().RootGenerationStatus()
rootGenerationStatus, err := client.Sys().GenerateRootStatus()
if err != nil {
c.Ui.Error(fmt.Sprintf("Error reading root generation status: %s", err))
return 1
@ -131,21 +131,21 @@ func (c *GenerateRootCommand) Run(args []string) int {
// Check if we are running doing any restricted variants
switch {
case init:
return c.initRootGeneration(client, otp, pgpKey)
return c.initGenerateRoot(client, otp, pgpKey)
case cancel:
return c.cancelRootGeneration(client)
return c.cancelGenerateRoot(client)
case status:
return c.rootGenerationStatus(client)
}
// Start the root generation process if not started
if !rootGenerationStatus.Started {
err = client.Sys().RootGenerationInit(otp, pgpKey)
err = client.Sys().GenerateRootInit(otp, pgpKey)
if err != nil {
c.Ui.Error(fmt.Sprintf("Error initializing root generation: %s", err))
return 1
}
rootGenerationStatus, err = client.Sys().RootGenerationStatus()
rootGenerationStatus, err = client.Sys().GenerateRootStatus()
if err != nil {
c.Ui.Error(fmt.Sprintf("Error reading root generation status: %s", err))
return 1
@ -182,7 +182,7 @@ func (c *GenerateRootCommand) Run(args []string) int {
}
// Provide the key, this may potentially complete the update
statusResp, err := client.Sys().RootGenerationUpdate(strings.TrimSpace(key), c.Nonce)
statusResp, err := client.Sys().GenerateRootUpdate(strings.TrimSpace(key), c.Nonce)
if err != nil {
c.Ui.Error(fmt.Sprintf("Error attempting generate-root update: %s", err))
return 1
@ -226,10 +226,10 @@ func (c *GenerateRootCommand) decode(encodedVal, otp string) int {
return 0
}
// initRootGeneration is used to start the generation process
func (c *GenerateRootCommand) initRootGeneration(client *api.Client, otp string, pgpKey string) int {
// initGenerateRoot is used to start the generation process
func (c *GenerateRootCommand) initGenerateRoot(client *api.Client, otp string, pgpKey string) int {
// Start the rekey
err := client.Sys().RootGenerationInit(otp, pgpKey)
err := client.Sys().GenerateRootInit(otp, pgpKey)
if err != nil {
c.Ui.Error(fmt.Sprintf("Error initializing root generation: %s", err))
return 1
@ -239,9 +239,9 @@ func (c *GenerateRootCommand) initRootGeneration(client *api.Client, otp string,
return c.rootGenerationStatus(client)
}
// cancelRootGeneration is used to abort the generation process
func (c *GenerateRootCommand) cancelRootGeneration(client *api.Client) int {
err := client.Sys().RootGenerationCancel()
// cancelGenerateRoot is used to abort the generation process
func (c *GenerateRootCommand) cancelGenerateRoot(client *api.Client) int {
err := client.Sys().GenerateRootCancel()
if err != nil {
c.Ui.Error(fmt.Sprintf("Failed to cancel root generation: %s", err))
return 1
@ -253,7 +253,7 @@ func (c *GenerateRootCommand) cancelRootGeneration(client *api.Client) int {
// rootGenerationStatus is used just to fetch and dump the status
func (c *GenerateRootCommand) rootGenerationStatus(client *api.Client) int {
// Check the status
status, err := client.Sys().RootGenerationStatus()
status, err := client.Sys().GenerateRootStatus()
if err != nil {
c.Ui.Error(fmt.Sprintf("Error reading root generation status: %s", err))
return 1
@ -265,7 +265,7 @@ func (c *GenerateRootCommand) rootGenerationStatus(client *api.Client) int {
}
// dumpStatus dumps the status to output
func (c *GenerateRootCommand) dumpStatus(status *api.RootGenerationStatusResponse) {
func (c *GenerateRootCommand) dumpStatus(status *api.GenerateRootStatusResponse) {
// Dump the status
statString := fmt.Sprintf(
"Nonce: %s\n"+

View File

@ -29,7 +29,7 @@ func TestGenerateRoot_Cancel(t *testing.T) {
},
}
otpBytes, err := xor.GenerateRandBytes(16)
otpBytes, err := vault.GenerateRandBytes(16)
if err != nil {
t.Fatal(err)
}
@ -45,7 +45,7 @@ func TestGenerateRoot_Cancel(t *testing.T) {
t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
}
config, err := core.RootGenerationConfiguration()
config, err := core.GenerateRootConfiguration()
if err != nil {
t.Fatalf("err: %s", err)
}
@ -67,7 +67,7 @@ func TestGenerateRoot_status(t *testing.T) {
},
}
otpBytes, err := xor.GenerateRandBytes(16)
otpBytes, err := vault.GenerateRandBytes(16)
if err != nil {
t.Fatal(err)
}
@ -102,7 +102,7 @@ func TestGenerateRoot_OTP(t *testing.T) {
}
// Generate an OTP
otpBytes, err := xor.GenerateRandBytes(16)
otpBytes, err := vault.GenerateRandBytes(16)
if err != nil {
t.Fatal(err)
}
@ -118,7 +118,7 @@ func TestGenerateRoot_OTP(t *testing.T) {
t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
}
config, err := core.RootGenerationConfiguration()
config, err := core.GenerateRootConfiguration()
if err != nil {
t.Fatalf("err: %v", err)
}
@ -202,7 +202,7 @@ func TestGenerateRoot_PGP(t *testing.T) {
t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
}
config, err := core.RootGenerationConfiguration()
config, err := core.GenerateRootConfiguration()
if err != nil {
t.Fatalf("err: %v", err)
}

View File

@ -1,9 +1,7 @@
package xor
import (
"crypto/rand"
"encoding/base64"
"fmt"
"testing"
)
@ -13,27 +11,6 @@ const (
expectedB64 = "7AmkVw0p6ksamAwv19BVuA=="
)
func GenerateRandBytes(length int) ([]byte, error) {
if length < 0 {
return nil, fmt.Errorf("length must be >= 0")
}
buf := make([]byte, length)
if length == 0 {
return buf, nil
}
n, err := rand.Read(buf)
if err != nil {
return nil, err
}
if n != length {
return nil, fmt.Errorf("unable to read %d bytes; only read %d", length, n)
}
return buf, nil
}
func TestBase64XOR(t *testing.T) {
ret, err := XORBase64(tokenB64, xorB64)
if err != nil {

View File

@ -41,8 +41,8 @@ func Handler(core *vault.Core) http.Handler {
mux.Handle("/v1/sys/health", handleSysHealth(core))
mux.Handle("/v1/sys/rotate", proxySysRequest(core))
mux.Handle("/v1/sys/key-status", proxySysRequest(core))
mux.Handle("/v1/sys/root-generation/attempt", handleSysRootGenerationInit(core))
mux.Handle("/v1/sys/root-generation/update", handleSysRootGenerationUpdate(core))
mux.Handle("/v1/sys/generate-root/attempt", handleSysGenerateRootAttempt(core))
mux.Handle("/v1/sys/generate-root/update", handleSysGenerateRootUpdate(core))
mux.Handle("/v1/sys/rekey/init", handleSysRekeyInit(core))
mux.Handle("/v1/sys/rekey/backup", proxySysRequest(core))
mux.Handle("/v1/sys/rekey/update", handleSysRekeyUpdate(core))

View File

@ -9,22 +9,22 @@ import (
"github.com/hashicorp/vault/vault"
)
func handleSysRootGenerationInit(core *vault.Core) http.Handler {
func handleSysGenerateRootAttempt(core *vault.Core) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
switch r.Method {
case "GET":
handleSysRootGenerationInitGet(core, w, r)
handleSysGenerateRootAttemptGet(core, w, r)
case "POST", "PUT":
handleSysRootGenerationInitPut(core, w, r)
handleSysGenerateRootAttemptPut(core, w, r)
case "DELETE":
handleSysRootGenerationInitDelete(core, w, r)
handleSysGenerateRootAttemptDelete(core, w, r)
default:
respondError(w, http.StatusMethodNotAllowed, nil)
}
})
}
func handleSysRootGenerationInitGet(core *vault.Core, w http.ResponseWriter, r *http.Request) {
func handleSysGenerateRootAttemptGet(core *vault.Core, w http.ResponseWriter, r *http.Request) {
// Get the current seal configuration
sealConfig, err := core.SealConfig()
if err != nil {
@ -38,21 +38,21 @@ func handleSysRootGenerationInitGet(core *vault.Core, w http.ResponseWriter, r *
}
// Get the generation configuration
generationConfig, err := core.RootGenerationConfiguration()
generationConfig, err := core.GenerateRootConfiguration()
if err != nil {
respondError(w, http.StatusInternalServerError, err)
return
}
// Get the progress
progress, err := core.RootGenerationProgress()
progress, err := core.GenerateRootProgress()
if err != nil {
respondError(w, http.StatusInternalServerError, err)
return
}
// Format the status
status := &RootGenerationStatusResponse{
status := &GenerateRootStatusResponse{
Started: false,
Progress: progress,
Required: sealConfig.SecretThreshold,
@ -67,9 +67,9 @@ func handleSysRootGenerationInitGet(core *vault.Core, w http.ResponseWriter, r *
respondOk(w, status)
}
func handleSysRootGenerationInitPut(core *vault.Core, w http.ResponseWriter, r *http.Request) {
func handleSysGenerateRootAttemptPut(core *vault.Core, w http.ResponseWriter, r *http.Request) {
// Parse the request
var req RootGenerationInitRequest
var req GenerateRootInitRequest
if err := parseRequest(r, &req); err != nil {
respondError(w, http.StatusBadRequest, err)
return
@ -80,8 +80,8 @@ func handleSysRootGenerationInitPut(core *vault.Core, w http.ResponseWriter, r *
return
}
// Initialize the generation
err := core.RootGenerationInit(req.OTP, req.PGPKey)
// Attemptialize the generation
err := core.GenerateRootInit(req.OTP, req.PGPKey)
if err != nil {
respondError(w, http.StatusBadRequest, err)
return
@ -89,8 +89,8 @@ func handleSysRootGenerationInitPut(core *vault.Core, w http.ResponseWriter, r *
respondOk(w, nil)
}
func handleSysRootGenerationInitDelete(core *vault.Core, w http.ResponseWriter, r *http.Request) {
err := core.RootGenerationCancel()
func handleSysGenerateRootAttemptDelete(core *vault.Core, w http.ResponseWriter, r *http.Request) {
err := core.GenerateRootCancel()
if err != nil {
respondError(w, http.StatusInternalServerError, err)
return
@ -98,10 +98,10 @@ func handleSysRootGenerationInitDelete(core *vault.Core, w http.ResponseWriter,
respondOk(w, nil)
}
func handleSysRootGenerationUpdate(core *vault.Core) http.Handler {
func handleSysGenerateRootUpdate(core *vault.Core) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Parse the request
var req RootGenerationUpdateRequest
var req GenerateRootUpdateRequest
if err := parseRequest(r, &req); err != nil {
respondError(w, http.StatusBadRequest, err)
return
@ -123,13 +123,13 @@ func handleSysRootGenerationUpdate(core *vault.Core) http.Handler {
}
// Use the key to make progress on root generation
result, err := core.RootGenerationUpdate(key, req.Nonce)
result, err := core.GenerateRootUpdate(key, req.Nonce)
if err != nil {
respondError(w, http.StatusBadRequest, err)
return
}
resp := &RootGenerationStatusResponse{
resp := &GenerateRootStatusResponse{
Complete: result.Progress == result.Required,
Nonce: req.Nonce,
Progress: result.Progress,
@ -143,12 +143,12 @@ func handleSysRootGenerationUpdate(core *vault.Core) http.Handler {
})
}
type RootGenerationInitRequest struct {
type GenerateRootInitRequest struct {
OTP string `json:"otp"`
PGPKey string `json:"pgp_key"`
}
type RootGenerationStatusResponse struct {
type GenerateRootStatusResponse struct {
Nonce string `json:"nonce"`
Started bool `json:"started"`
Progress int `json:"progress"`
@ -158,7 +158,7 @@ type RootGenerationStatusResponse struct {
PGPFingerprint string `json:"pgp_fingerprint"`
}
type RootGenerationUpdateRequest struct {
type GenerateRootUpdateRequest struct {
Nonce string
Key string
}

View File

@ -13,13 +13,13 @@ import (
"github.com/hashicorp/vault/vault"
)
func TestSysRootGenerationInit_Status(t *testing.T) {
func TestSysGenerateRootAttempt_Status(t *testing.T) {
core, _, token := vault.TestCoreUnsealed(t)
ln, addr := TestServer(t, core)
defer ln.Close()
TestServerAuth(t, addr, token)
resp, err := http.Get(addr + "/v1/sys/root-generation/attempt")
resp, err := http.Get(addr + "/v1/sys/generate-root/attempt")
if err != nil {
t.Fatalf("err: %s", err)
}
@ -41,24 +41,24 @@ func TestSysRootGenerationInit_Status(t *testing.T) {
}
}
func TestSysRootGenerationInit_Setup_OTP(t *testing.T) {
func TestSysGenerateRootAttempt_Setup_OTP(t *testing.T) {
core, _, token := vault.TestCoreUnsealed(t)
ln, addr := TestServer(t, core)
defer ln.Close()
TestServerAuth(t, addr, token)
otpBytes, err := xor.GenerateRandBytes(16)
otpBytes, err := vault.GenerateRandBytes(16)
if err != nil {
t.Fatal(err)
}
otp := base64.StdEncoding.EncodeToString(otpBytes)
resp := testHttpPut(t, token, addr+"/v1/sys/root-generation/attempt", map[string]interface{}{
resp := testHttpPut(t, token, addr+"/v1/sys/generate-root/attempt", map[string]interface{}{
"otp": otp,
})
testResponseStatus(t, resp, 204)
resp = testHttpGet(t, token, addr+"/v1/sys/root-generation/attempt")
resp = testHttpGet(t, token, addr+"/v1/sys/generate-root/attempt")
var actual map[string]interface{}
expected := map[string]interface{}{
@ -77,18 +77,18 @@ func TestSysRootGenerationInit_Setup_OTP(t *testing.T) {
}
}
func TestSysRootGenerationInit_Setup_PGP(t *testing.T) {
func TestSysGenerateRootAttempt_Setup_PGP(t *testing.T) {
core, _, token := vault.TestCoreUnsealed(t)
ln, addr := TestServer(t, core)
defer ln.Close()
TestServerAuth(t, addr, token)
resp := testHttpPut(t, token, addr+"/v1/sys/root-generation/attempt", map[string]interface{}{
resp := testHttpPut(t, token, addr+"/v1/sys/generate-root/attempt", map[string]interface{}{
"pgp_key": pgpkeys.TestPubKey1,
})
testResponseStatus(t, resp, 204)
resp = testHttpGet(t, token, addr+"/v1/sys/root-generation/attempt")
resp = testHttpGet(t, token, addr+"/v1/sys/generate-root/attempt")
var actual map[string]interface{}
expected := map[string]interface{}{
@ -107,26 +107,26 @@ func TestSysRootGenerationInit_Setup_PGP(t *testing.T) {
}
}
func TestSysRootGenerationInit_Cancel(t *testing.T) {
func TestSysGenerateRootAttempt_Cancel(t *testing.T) {
core, _, token := vault.TestCoreUnsealed(t)
ln, addr := TestServer(t, core)
defer ln.Close()
TestServerAuth(t, addr, token)
otpBytes, err := xor.GenerateRandBytes(16)
otpBytes, err := vault.GenerateRandBytes(16)
if err != nil {
t.Fatal(err)
}
otp := base64.StdEncoding.EncodeToString(otpBytes)
resp := testHttpPut(t, token, addr+"/v1/sys/root-generation/attempt", map[string]interface{}{
resp := testHttpPut(t, token, addr+"/v1/sys/generate-root/attempt", map[string]interface{}{
"otp": otp,
})
resp = testHttpDelete(t, token, addr+"/v1/sys/root-generation/attempt")
resp = testHttpDelete(t, token, addr+"/v1/sys/generate-root/attempt")
testResponseStatus(t, resp, 204)
resp, err = http.Get(addr + "/v1/sys/root-generation/attempt")
resp, err = http.Get(addr + "/v1/sys/generate-root/attempt")
if err != nil {
t.Fatalf("err: %s", err)
}
@ -148,70 +148,70 @@ func TestSysRootGenerationInit_Cancel(t *testing.T) {
}
}
func TestSysRootGeneration_badKey(t *testing.T) {
func TestSysGenerateRoot_badKey(t *testing.T) {
core, _, token := vault.TestCoreUnsealed(t)
ln, addr := TestServer(t, core)
defer ln.Close()
TestServerAuth(t, addr, token)
otpBytes, err := xor.GenerateRandBytes(16)
otpBytes, err := vault.GenerateRandBytes(16)
if err != nil {
t.Fatal(err)
}
otp := base64.StdEncoding.EncodeToString(otpBytes)
resp := testHttpPut(t, token, addr+"/v1/sys/root-generation/update", map[string]interface{}{
resp := testHttpPut(t, token, addr+"/v1/sys/generate-root/update", map[string]interface{}{
"key": "0123",
"otp": otp,
})
testResponseStatus(t, resp, 400)
}
func TestSysRootGeneration_ReInitUpdate(t *testing.T) {
func TestSysGenerateRoot_ReAttemptUpdate(t *testing.T) {
core, _, token := vault.TestCoreUnsealed(t)
ln, addr := TestServer(t, core)
defer ln.Close()
TestServerAuth(t, addr, token)
otpBytes, err := xor.GenerateRandBytes(16)
otpBytes, err := vault.GenerateRandBytes(16)
if err != nil {
t.Fatal(err)
}
otp := base64.StdEncoding.EncodeToString(otpBytes)
resp := testHttpPut(t, token, addr+"/v1/sys/root-generation/attempt", map[string]interface{}{
resp := testHttpPut(t, token, addr+"/v1/sys/generate-root/attempt", map[string]interface{}{
"otp": otp,
})
testResponseStatus(t, resp, 204)
resp = testHttpDelete(t, token, addr+"/v1/sys/root-generation/attempt")
resp = testHttpDelete(t, token, addr+"/v1/sys/generate-root/attempt")
testResponseStatus(t, resp, 204)
resp = testHttpPut(t, token, addr+"/v1/sys/root-generation/attempt", map[string]interface{}{
resp = testHttpPut(t, token, addr+"/v1/sys/generate-root/attempt", map[string]interface{}{
"pgp_key": pgpkeys.TestPubKey1,
})
testResponseStatus(t, resp, 204)
}
func TestSysRootGeneration_Update_OTP(t *testing.T) {
func TestSysGenerateRoot_Update_OTP(t *testing.T) {
core, master, token := vault.TestCoreUnsealed(t)
ln, addr := TestServer(t, core)
defer ln.Close()
TestServerAuth(t, addr, token)
otpBytes, err := xor.GenerateRandBytes(16)
otpBytes, err := vault.GenerateRandBytes(16)
if err != nil {
t.Fatal(err)
}
otp := base64.StdEncoding.EncodeToString(otpBytes)
resp := testHttpPut(t, token, addr+"/v1/sys/root-generation/attempt", map[string]interface{}{
resp := testHttpPut(t, token, addr+"/v1/sys/generate-root/attempt", map[string]interface{}{
"otp": otp,
})
testResponseStatus(t, resp, 204)
// We need to get the nonce first before we update
resp, err = http.Get(addr + "/v1/sys/root-generation/attempt")
resp, err = http.Get(addr + "/v1/sys/generate-root/attempt")
if err != nil {
t.Fatalf("err: %s", err)
}
@ -219,7 +219,7 @@ func TestSysRootGeneration_Update_OTP(t *testing.T) {
testResponseStatus(t, resp, 200)
testResponseBody(t, resp, &rootGenerationStatus)
resp = testHttpPut(t, token, addr+"/v1/sys/root-generation/update", map[string]interface{}{
resp = testHttpPut(t, token, addr+"/v1/sys/generate-root/update", map[string]interface{}{
"nonce": rootGenerationStatus["nonce"].(string),
"key": hex.EncodeToString(master),
})
@ -277,19 +277,19 @@ func TestSysRootGeneration_Update_OTP(t *testing.T) {
}
}
func TestSysRootGeneration_Update_PGP(t *testing.T) {
func TestSysGenerateRoot_Update_PGP(t *testing.T) {
core, master, token := vault.TestCoreUnsealed(t)
ln, addr := TestServer(t, core)
defer ln.Close()
TestServerAuth(t, addr, token)
resp := testHttpPut(t, token, addr+"/v1/sys/root-generation/attempt", map[string]interface{}{
resp := testHttpPut(t, token, addr+"/v1/sys/generate-root/attempt", map[string]interface{}{
"pgp_key": pgpkeys.TestPubKey1,
})
testResponseStatus(t, resp, 204)
// We need to get the nonce first before we update
resp, err := http.Get(addr + "/v1/sys/root-generation/attempt")
resp, err := http.Get(addr + "/v1/sys/generate-root/attempt")
if err != nil {
t.Fatalf("err: %s", err)
}
@ -297,7 +297,7 @@ func TestSysRootGeneration_Update_PGP(t *testing.T) {
testResponseStatus(t, resp, 200)
testResponseBody(t, resp, &rootGenerationStatus)
resp = testHttpPut(t, token, addr+"/v1/sys/root-generation/update", map[string]interface{}{
resp = testHttpPut(t, token, addr+"/v1/sys/generate-root/update", map[string]interface{}{
"nonce": rootGenerationStatus["nonce"].(string),
"key": hex.EncodeToString(master),
})

View File

@ -214,11 +214,11 @@ type Core struct {
// the threshold number of parts is available.
unlockParts [][]byte
// rootGenerationProgress holds the shares until we reach enough
// generateRootProgress holds the shares until we reach enough
// to verify the master key
rootGenerationConfig *RootGenerationConfig
rootGenerationProgress [][]byte
rootGenerationLock sync.Mutex
generateRootConfig *GenerateRootConfig
generateRootProgress [][]byte
generateRootLock sync.Mutex
// rekeyProgress holds the shares we have until we reach enough
// to verify the master key.

View File

@ -12,26 +12,26 @@ import (
"github.com/hashicorp/vault/shamir"
)
// RootGenerationConfig holds the configuration for a root generation
// GenerateRootConfig holds the configuration for a root generation
// command.
type RootGenerationConfig struct {
type GenerateRootConfig struct {
Nonce string
PGPKey string
PGPFingerprint string
OTP string
}
// RootGenerationResult holds the result of a root generation update
// GenerateRootResult holds the result of a root generation update
// command
type RootGenerationResult struct {
type GenerateRootResult struct {
Progress int
Required int
EncodedRootToken string
PGPFingerprint string
}
// RootGeneration is used to return the root generation progress (num shares)
func (c *Core) RootGenerationProgress() (int, error) {
// GenerateRoot is used to return the root generation progress (num shares)
func (c *Core) GenerateRootProgress() (int, error) {
c.stateLock.RLock()
defer c.stateLock.RUnlock()
if c.sealed {
@ -41,15 +41,15 @@ func (c *Core) RootGenerationProgress() (int, error) {
return 0, ErrStandby
}
c.rootGenerationLock.Lock()
defer c.rootGenerationLock.Unlock()
c.generateRootLock.Lock()
defer c.generateRootLock.Unlock()
return len(c.rootGenerationProgress), nil
return len(c.generateRootProgress), nil
}
// RootGenerationConfig is used to read the root generation configuration
// GenerateRootConfig is used to read the root generation configuration
// It stubbornly refuses to return the OTP if one is there.
func (c *Core) RootGenerationConfiguration() (*RootGenerationConfig, error) {
func (c *Core) GenerateRootConfiguration() (*GenerateRootConfig, error) {
c.stateLock.RLock()
defer c.stateLock.RUnlock()
if c.sealed {
@ -59,21 +59,21 @@ func (c *Core) RootGenerationConfiguration() (*RootGenerationConfig, error) {
return nil, ErrStandby
}
c.rootGenerationLock.Lock()
defer c.rootGenerationLock.Unlock()
c.generateRootLock.Lock()
defer c.generateRootLock.Unlock()
// Copy the config if any
var conf *RootGenerationConfig
if c.rootGenerationConfig != nil {
conf = new(RootGenerationConfig)
*conf = *c.rootGenerationConfig
var conf *GenerateRootConfig
if c.generateRootConfig != nil {
conf = new(GenerateRootConfig)
*conf = *c.generateRootConfig
conf.OTP = ""
}
return conf, nil
}
// RootGenerationInit is used to initialize the root generation settings
func (c *Core) RootGenerationInit(otp, pgpKey string) error {
// GenerateRootInit is used to initialize the root generation settings
func (c *Core) GenerateRootInit(otp, pgpKey string) error {
var fingerprint string
switch {
case len(otp) > 0:
@ -108,11 +108,11 @@ func (c *Core) RootGenerationInit(otp, pgpKey string) error {
return ErrStandby
}
c.rootGenerationLock.Lock()
defer c.rootGenerationLock.Unlock()
c.generateRootLock.Lock()
defer c.generateRootLock.Unlock()
// Prevent multiple concurrent root generations
if c.rootGenerationConfig != nil {
if c.generateRootConfig != nil {
return fmt.Errorf("root generation already in progress")
}
@ -122,7 +122,7 @@ func (c *Core) RootGenerationInit(otp, pgpKey string) error {
return err
}
c.rootGenerationConfig = &RootGenerationConfig{
c.generateRootConfig = &GenerateRootConfig{
Nonce: generationNonce,
OTP: otp,
PGPKey: pgpKey,
@ -130,12 +130,12 @@ func (c *Core) RootGenerationInit(otp, pgpKey string) error {
}
c.logger.Printf("[INFO] core: root generation initialized (nonce: %s)",
c.rootGenerationConfig.Nonce)
c.generateRootConfig.Nonce)
return nil
}
// RootGenerationUpdate is used to provide a new key part
func (c *Core) RootGenerationUpdate(key []byte, nonce string) (*RootGenerationResult, error) {
// GenerateRootUpdate is used to provide a new key part
func (c *Core) GenerateRootUpdate(key []byte, nonce string) (*GenerateRootResult, error) {
// Verify the key length
min, max := c.barrier.KeyLength()
max += shamir.ShareOverhead
@ -167,48 +167,48 @@ func (c *Core) RootGenerationUpdate(key []byte, nonce string) (*RootGenerationRe
return nil, ErrStandby
}
c.rootGenerationLock.Lock()
defer c.rootGenerationLock.Unlock()
c.generateRootLock.Lock()
defer c.generateRootLock.Unlock()
// Ensure a rootGeneration is in progress
if c.rootGenerationConfig == nil {
// Ensure a generateRoot is in progress
if c.generateRootConfig == nil {
return nil, fmt.Errorf("no root generation in progress")
}
if nonce != c.rootGenerationConfig.Nonce {
return nil, fmt.Errorf("incorrect nonce supplied; nonce for this root generation operation is %s", c.rootGenerationConfig.Nonce)
if nonce != c.generateRootConfig.Nonce {
return nil, fmt.Errorf("incorrect nonce supplied; nonce for this root generation operation is %s", c.generateRootConfig.Nonce)
}
// Check if we already have this piece
for _, existing := range c.rootGenerationProgress {
for _, existing := range c.generateRootProgress {
if bytes.Equal(existing, key) {
return nil, nil
}
}
// Store this key
c.rootGenerationProgress = append(c.rootGenerationProgress, key)
progress := len(c.rootGenerationProgress)
c.generateRootProgress = append(c.generateRootProgress, key)
progress := len(c.generateRootProgress)
// Check if we don't have enough keys to unlock
if len(c.rootGenerationProgress) < config.SecretThreshold {
if len(c.generateRootProgress) < config.SecretThreshold {
c.logger.Printf("[DEBUG] core: cannot generate root, have %d of %d keys",
progress, config.SecretThreshold)
return &RootGenerationResult{
return &GenerateRootResult{
Progress: progress,
Required: config.SecretThreshold,
PGPFingerprint: c.rootGenerationConfig.PGPFingerprint,
PGPFingerprint: c.generateRootConfig.PGPFingerprint,
}, nil
}
// Recover the master key
var masterKey []byte
if config.SecretThreshold == 1 {
masterKey = c.rootGenerationProgress[0]
c.rootGenerationProgress = nil
masterKey = c.generateRootProgress[0]
c.generateRootProgress = nil
} else {
masterKey, err = shamir.Combine(c.rootGenerationProgress)
c.rootGenerationProgress = nil
masterKey, err = shamir.Combine(c.generateRootProgress)
c.generateRootProgress = nil
if err != nil {
return nil, fmt.Errorf("failed to compute master key: %v", err)
}
@ -237,17 +237,17 @@ func (c *Core) RootGenerationUpdate(key []byte, nonce string) (*RootGenerationRe
// Get the encoded value first so that if there is an error we don't create
// the root token.
switch {
case len(c.rootGenerationConfig.OTP) > 0:
case len(c.generateRootConfig.OTP) > 0:
// This function performs decoding checks so rather than decode the OTP,
// just encode the value we're passing in.
tokenBytes, err = xor.XORBase64(c.rootGenerationConfig.OTP, base64.StdEncoding.EncodeToString(buf))
tokenBytes, err = xor.XORBase64(c.generateRootConfig.OTP, base64.StdEncoding.EncodeToString(buf))
if err != nil {
c.logger.Printf("[ERR] core: xor of root token failed: %v", err)
return nil, err
}
case len(c.rootGenerationConfig.PGPKey) > 0:
_, tokenBytesArr, err := pgpkeys.EncryptShares([][]byte{[]byte(uuidStr)}, []string{c.rootGenerationConfig.PGPKey})
case len(c.generateRootConfig.PGPKey) > 0:
_, tokenBytesArr, err := pgpkeys.EncryptShares([][]byte{[]byte(uuidStr)}, []string{c.generateRootConfig.PGPKey})
if err != nil {
c.logger.Printf("[ERR] core: error encrypting new root token: %v", err)
return nil, err
@ -264,23 +264,23 @@ func (c *Core) RootGenerationUpdate(key []byte, nonce string) (*RootGenerationRe
return nil, err
}
results := &RootGenerationResult{
results := &GenerateRootResult{
Progress: progress,
Required: config.SecretThreshold,
EncodedRootToken: base64.StdEncoding.EncodeToString(tokenBytes),
PGPFingerprint: c.rootGenerationConfig.PGPFingerprint,
PGPFingerprint: c.generateRootConfig.PGPFingerprint,
}
c.logger.Printf("[INFO] core: root generation finished (nonce: %s)",
c.rootGenerationConfig.Nonce)
c.generateRootConfig.Nonce)
c.rootGenerationProgress = nil
c.rootGenerationConfig = nil
c.generateRootProgress = nil
c.generateRootConfig = nil
return results, nil
}
// RootGenerationCancel is used to cancel an in-progress root generation
func (c *Core) RootGenerationCancel() error {
// GenerateRootCancel is used to cancel an in-progress root generation
func (c *Core) GenerateRootCancel() error {
c.stateLock.RLock()
defer c.stateLock.RUnlock()
if c.sealed {
@ -290,11 +290,11 @@ func (c *Core) RootGenerationCancel() error {
return ErrStandby
}
c.rootGenerationLock.Lock()
defer c.rootGenerationLock.Unlock()
c.generateRootLock.Lock()
defer c.generateRootLock.Unlock()
// Clear any progress or config
c.rootGenerationConfig = nil
c.rootGenerationProgress = nil
c.generateRootConfig = nil
c.generateRootProgress = nil
return nil
}

View File

@ -9,16 +9,16 @@ import (
"github.com/hashicorp/vault/helper/xor"
)
func TestCore_RootGeneration_Lifecycle(t *testing.T) {
func TestCore_GenerateRoot_Lifecycle(t *testing.T) {
c, master, _ := TestCoreUnsealed(t)
// Verify update not allowed
if _, err := c.RootGenerationUpdate(master, ""); err == nil {
if _, err := c.GenerateRootUpdate(master, ""); err == nil {
t.Fatalf("no root generation in progress")
}
// Should be no progress
num, err := c.RootGenerationProgress()
num, err := c.GenerateRootProgress()
if err != nil {
t.Fatalf("err: %v", err)
}
@ -27,7 +27,7 @@ func TestCore_RootGeneration_Lifecycle(t *testing.T) {
}
// Should be no config
conf, err := c.RootGenerationConfiguration()
conf, err := c.GenerateRootConfiguration()
if err != nil {
t.Fatalf("err: %v", err)
}
@ -36,36 +36,36 @@ func TestCore_RootGeneration_Lifecycle(t *testing.T) {
}
// Cancel should be idempotent
err = c.RootGenerationCancel()
err = c.GenerateRootCancel()
if err != nil {
t.Fatalf("err: %v", err)
}
otpBytes, err := xor.GenerateRandBytes(16)
otpBytes, err := GenerateRandBytes(16)
if err != nil {
t.Fatal(err)
}
// Start a root generation
err = c.RootGenerationInit(base64.StdEncoding.EncodeToString(otpBytes), "")
err = c.GenerateRootInit(base64.StdEncoding.EncodeToString(otpBytes), "")
if err != nil {
t.Fatalf("err: %v", err)
}
// Should get config
conf, err = c.RootGenerationConfiguration()
conf, err = c.GenerateRootConfiguration()
if err != nil {
t.Fatalf("err: %v", err)
}
// Cancel should be clear
err = c.RootGenerationCancel()
err = c.GenerateRootCancel()
if err != nil {
t.Fatalf("err: %v", err)
}
// Should be no config
conf, err = c.RootGenerationConfiguration()
conf, err = c.GenerateRootConfiguration()
if err != nil {
t.Fatalf("err: %v", err)
}
@ -74,41 +74,41 @@ func TestCore_RootGeneration_Lifecycle(t *testing.T) {
}
}
func TestCore_RootGeneration_Init(t *testing.T) {
func TestCore_GenerateRoot_Init(t *testing.T) {
c, _, _ := TestCoreUnsealed(t)
otpBytes, err := xor.GenerateRandBytes(16)
otpBytes, err := GenerateRandBytes(16)
if err != nil {
t.Fatal(err)
}
err = c.RootGenerationInit(base64.StdEncoding.EncodeToString(otpBytes), "")
err = c.GenerateRootInit(base64.StdEncoding.EncodeToString(otpBytes), "")
if err != nil {
t.Fatalf("err: %v", err)
}
// Second should fail
err = c.RootGenerationInit("", pgpkeys.TestPubKey1)
err = c.GenerateRootInit("", pgpkeys.TestPubKey1)
if err == nil {
t.Fatalf("should fail")
}
}
func TestCore_RootGeneration_InvalidMaster(t *testing.T) {
func TestCore_GenerateRoot_InvalidMaster(t *testing.T) {
c, master, _ := TestCoreUnsealed(t)
otpBytes, err := xor.GenerateRandBytes(16)
otpBytes, err := GenerateRandBytes(16)
if err != nil {
t.Fatal(err)
}
err = c.RootGenerationInit(base64.StdEncoding.EncodeToString(otpBytes), "")
err = c.GenerateRootInit(base64.StdEncoding.EncodeToString(otpBytes), "")
if err != nil {
t.Fatalf("err: %v", err)
}
// Fetch new config with generated nonce
rgconf, err := c.RootGenerationConfiguration()
rgconf, err := c.GenerateRootConfiguration()
if err != nil {
t.Fatalf("err: %v", err)
}
@ -118,49 +118,49 @@ func TestCore_RootGeneration_InvalidMaster(t *testing.T) {
// Provide the master (invalid)
master[0]++
_, err = c.RootGenerationUpdate(master, rgconf.Nonce)
_, err = c.GenerateRootUpdate(master, rgconf.Nonce)
if err == nil {
t.Fatalf("expected error")
}
}
func TestCore_RootGeneration_InvalidNonce(t *testing.T) {
func TestCore_GenerateRoot_InvalidNonce(t *testing.T) {
c, master, _ := TestCoreUnsealed(t)
otpBytes, err := xor.GenerateRandBytes(16)
otpBytes, err := GenerateRandBytes(16)
if err != nil {
t.Fatal(err)
}
err = c.RootGenerationInit(base64.StdEncoding.EncodeToString(otpBytes), "")
err = c.GenerateRootInit(base64.StdEncoding.EncodeToString(otpBytes), "")
if err != nil {
t.Fatalf("err: %v", err)
}
// Provide the nonce (invalid)
_, err = c.RootGenerationUpdate(master, "abcd")
_, err = c.GenerateRootUpdate(master, "abcd")
if err == nil {
t.Fatalf("expected error")
}
}
func TestCore_RootGeneration_Update_OTP(t *testing.T) {
func TestCore_GenerateRoot_Update_OTP(t *testing.T) {
c, master, _ := TestCoreUnsealed(t)
otpBytes, err := xor.GenerateRandBytes(16)
otpBytes, err := GenerateRandBytes(16)
if err != nil {
t.Fatal(err)
}
otp := base64.StdEncoding.EncodeToString(otpBytes)
// Start a root generation
err = c.RootGenerationInit(otp, "")
err = c.GenerateRootInit(otp, "")
if err != nil {
t.Fatalf("err: %v", err)
}
// Fetch new config with generated nonce
rkconf, err := c.RootGenerationConfiguration()
rkconf, err := c.GenerateRootConfiguration()
if err != nil {
t.Fatalf("err: %v", err)
}
@ -169,7 +169,7 @@ func TestCore_RootGeneration_Update_OTP(t *testing.T) {
}
// Provide the master
result, err := c.RootGenerationUpdate(master, rkconf.Nonce)
result, err := c.GenerateRootUpdate(master, rkconf.Nonce)
if err != nil {
t.Fatalf("err: %v", err)
}
@ -180,7 +180,7 @@ func TestCore_RootGeneration_Update_OTP(t *testing.T) {
encodedRootToken := result.EncodedRootToken
// Should be no progress
num, err := c.RootGenerationProgress()
num, err := c.GenerateRootProgress()
if err != nil {
t.Fatalf("err: %v", err)
}
@ -189,7 +189,7 @@ func TestCore_RootGeneration_Update_OTP(t *testing.T) {
}
// Should be no config
conf, err := c.RootGenerationConfiguration()
conf, err := c.GenerateRootConfiguration()
if err != nil {
t.Fatalf("err: %v", err)
}
@ -220,17 +220,17 @@ func TestCore_RootGeneration_Update_OTP(t *testing.T) {
}
}
func TestCore_RootGeneration_Update_PGP(t *testing.T) {
func TestCore_GenerateRoot_Update_PGP(t *testing.T) {
c, master, _ := TestCoreUnsealed(t)
// Start a root generation
err := c.RootGenerationInit("", pgpkeys.TestPubKey1)
err := c.GenerateRootInit("", pgpkeys.TestPubKey1)
if err != nil {
t.Fatalf("err: %v", err)
}
// Fetch new config with generated nonce
rkconf, err := c.RootGenerationConfiguration()
rkconf, err := c.GenerateRootConfiguration()
if err != nil {
t.Fatalf("err: %v", err)
}
@ -239,7 +239,7 @@ func TestCore_RootGeneration_Update_PGP(t *testing.T) {
}
// Provide the master
result, err := c.RootGenerationUpdate(master, rkconf.Nonce)
result, err := c.GenerateRootUpdate(master, rkconf.Nonce)
if err != nil {
t.Fatalf("err: %v", err)
}
@ -250,7 +250,7 @@ func TestCore_RootGeneration_Update_PGP(t *testing.T) {
encodedRootToken := result.EncodedRootToken
// Should be no progress
num, err := c.RootGenerationProgress()
num, err := c.GenerateRootProgress()
if err != nil {
t.Fatalf("err: %v", err)
}
@ -259,7 +259,7 @@ func TestCore_RootGeneration_Update_PGP(t *testing.T) {
}
// Should be no config
conf, err := c.RootGenerationConfiguration()
conf, err := c.GenerateRootConfiguration()
if err != nil {
t.Fatalf("err: %v", err)
}

View File

@ -2,6 +2,7 @@ package vault
import (
"bytes"
"crypto/rand"
"crypto/sha256"
"fmt"
"log"
@ -341,3 +342,24 @@ func (n *rawHTTP) System() logical.SystemView {
func (n *rawHTTP) Cleanup() {
// noop
}
func GenerateRandBytes(length int) ([]byte, error) {
if length < 0 {
return nil, fmt.Errorf("length must be >= 0")
}
buf := make([]byte, length)
if length == 0 {
return buf, nil
}
n, err := rand.Read(buf)
if err != nil {
return nil, err
}
if n != length {
return nil, fmt.Errorf("unable to read %d bytes; only read %d", length, n)
}
return buf, nil
}

View File

@ -1,12 +1,12 @@
---
layout: "http"
page_title: "HTTP API: /sys/root-generation/"
sidebar_current: "docs-http-sys-root-generation"
page_title: "HTTP API: /sys/generate-root/"
sidebar_current: "docs-http-sys-generate-root"
description: |-
The `/sys/root-generation/` endpoints are used to create a new root key for Vault.
The `/sys/generate-root/` endpoints are used to create a new root key for Vault.
---
# /sys/root-generation/attempt
# /sys/generate-root/attempt
## GET
@ -21,7 +21,7 @@ description: |-
<dd>GET</dd>
<dt>URL</dt>
<dd>`/sys/root-generation/attempt`</dd>
<dd>`/sys/generate-root/attempt`</dd>
<dt>Parameters</dt>
<dd>
@ -65,7 +65,7 @@ description: |-
<dd>PUT</dd>
<dt>URL</dt>
<dd>`/sys/root-generation/attempt`</dd>
<dd>`/sys/generate-root/attempt`</dd>
<dt>Parameters</dt>
<dd>
@ -118,7 +118,7 @@ description: |-
<dd>DELETE</dd>
<dt>URL</dt>
<dd>`/sys/root-generation/attempt`</dd>
<dd>`/sys/generate-root/attempt`</dd>
<dt>Parameters</dt>
<dd>None
@ -129,7 +129,7 @@ description: |-
</dd>
</dl>
# /sys/root-generation/update
# /sys/generate-root/update
## PUT
@ -147,7 +147,7 @@ description: |-
<dd>PUT</dd>
<dt>URL</dt>
<dd>`/sys/root-generation/update`</dd>
<dd>`/sys/generate-root/update`</dd>
<dt>Parameters</dt>
<dd>

View File

@ -22,8 +22,8 @@
<li<%= sidebar_current("docs-http-sys-init") %>>
<a href="/docs/http/sys-init.html">/sys/init</a>
</li>
<li<%= sidebar_current("docs-http-sys-root-generation") %>>
<a href="/docs/http/sys-root-generation.html">/sys/root-generation</a>
<li<%= sidebar_current("docs-http-sys-generate-root") %>>
<a href="/docs/http/sys-generate-root.html">/sys/generate-root</a>
</li>
</ul>