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

View file

@ -75,7 +75,7 @@ func (c *GenerateRootCommand) Run(args []string) int {
} }
// Check if the root generation is started // Check if the root generation is started
rootGenerationStatus, err := client.Sys().RootGenerationStatus() rootGenerationStatus, err := client.Sys().GenerateRootStatus()
if err != nil { if err != nil {
c.Ui.Error(fmt.Sprintf("Error reading root generation status: %s", err)) c.Ui.Error(fmt.Sprintf("Error reading root generation status: %s", err))
return 1 return 1
@ -131,21 +131,21 @@ func (c *GenerateRootCommand) Run(args []string) int {
// Check if we are running doing any restricted variants // Check if we are running doing any restricted variants
switch { switch {
case init: case init:
return c.initRootGeneration(client, otp, pgpKey) return c.initGenerateRoot(client, otp, pgpKey)
case cancel: case cancel:
return c.cancelRootGeneration(client) return c.cancelGenerateRoot(client)
case status: case status:
return c.rootGenerationStatus(client) return c.rootGenerationStatus(client)
} }
// Start the root generation process if not started // Start the root generation process if not started
if !rootGenerationStatus.Started { if !rootGenerationStatus.Started {
err = client.Sys().RootGenerationInit(otp, pgpKey) err = client.Sys().GenerateRootInit(otp, pgpKey)
if err != nil { if err != nil {
c.Ui.Error(fmt.Sprintf("Error initializing root generation: %s", err)) c.Ui.Error(fmt.Sprintf("Error initializing root generation: %s", err))
return 1 return 1
} }
rootGenerationStatus, err = client.Sys().RootGenerationStatus() rootGenerationStatus, err = client.Sys().GenerateRootStatus()
if err != nil { if err != nil {
c.Ui.Error(fmt.Sprintf("Error reading root generation status: %s", err)) c.Ui.Error(fmt.Sprintf("Error reading root generation status: %s", err))
return 1 return 1
@ -182,7 +182,7 @@ func (c *GenerateRootCommand) Run(args []string) int {
} }
// Provide the key, this may potentially complete the update // 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 { if err != nil {
c.Ui.Error(fmt.Sprintf("Error attempting generate-root update: %s", err)) c.Ui.Error(fmt.Sprintf("Error attempting generate-root update: %s", err))
return 1 return 1
@ -226,10 +226,10 @@ func (c *GenerateRootCommand) decode(encodedVal, otp string) int {
return 0 return 0
} }
// initRootGeneration is used to start the generation process // initGenerateRoot is used to start the generation process
func (c *GenerateRootCommand) initRootGeneration(client *api.Client, otp string, pgpKey string) int { func (c *GenerateRootCommand) initGenerateRoot(client *api.Client, otp string, pgpKey string) int {
// Start the rekey // Start the rekey
err := client.Sys().RootGenerationInit(otp, pgpKey) err := client.Sys().GenerateRootInit(otp, pgpKey)
if err != nil { if err != nil {
c.Ui.Error(fmt.Sprintf("Error initializing root generation: %s", err)) c.Ui.Error(fmt.Sprintf("Error initializing root generation: %s", err))
return 1 return 1
@ -239,9 +239,9 @@ func (c *GenerateRootCommand) initRootGeneration(client *api.Client, otp string,
return c.rootGenerationStatus(client) return c.rootGenerationStatus(client)
} }
// cancelRootGeneration is used to abort the generation process // cancelGenerateRoot is used to abort the generation process
func (c *GenerateRootCommand) cancelRootGeneration(client *api.Client) int { func (c *GenerateRootCommand) cancelGenerateRoot(client *api.Client) int {
err := client.Sys().RootGenerationCancel() err := client.Sys().GenerateRootCancel()
if err != nil { if err != nil {
c.Ui.Error(fmt.Sprintf("Failed to cancel root generation: %s", err)) c.Ui.Error(fmt.Sprintf("Failed to cancel root generation: %s", err))
return 1 return 1
@ -253,7 +253,7 @@ func (c *GenerateRootCommand) cancelRootGeneration(client *api.Client) int {
// rootGenerationStatus is used just to fetch and dump the status // rootGenerationStatus is used just to fetch and dump the status
func (c *GenerateRootCommand) rootGenerationStatus(client *api.Client) int { func (c *GenerateRootCommand) rootGenerationStatus(client *api.Client) int {
// Check the status // Check the status
status, err := client.Sys().RootGenerationStatus() status, err := client.Sys().GenerateRootStatus()
if err != nil { if err != nil {
c.Ui.Error(fmt.Sprintf("Error reading root generation status: %s", err)) c.Ui.Error(fmt.Sprintf("Error reading root generation status: %s", err))
return 1 return 1
@ -265,7 +265,7 @@ func (c *GenerateRootCommand) rootGenerationStatus(client *api.Client) int {
} }
// dumpStatus dumps the status to output // dumpStatus dumps the status to output
func (c *GenerateRootCommand) dumpStatus(status *api.RootGenerationStatusResponse) { func (c *GenerateRootCommand) dumpStatus(status *api.GenerateRootStatusResponse) {
// Dump the status // Dump the status
statString := fmt.Sprintf( statString := fmt.Sprintf(
"Nonce: %s\n"+ "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 { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -45,7 +45,7 @@ func TestGenerateRoot_Cancel(t *testing.T) {
t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
} }
config, err := core.RootGenerationConfiguration() config, err := core.GenerateRootConfiguration()
if err != nil { if err != nil {
t.Fatalf("err: %s", err) 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 { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -102,7 +102,7 @@ func TestGenerateRoot_OTP(t *testing.T) {
} }
// Generate an OTP // Generate an OTP
otpBytes, err := xor.GenerateRandBytes(16) otpBytes, err := vault.GenerateRandBytes(16)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -118,7 +118,7 @@ func TestGenerateRoot_OTP(t *testing.T) {
t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
} }
config, err := core.RootGenerationConfiguration() config, err := core.GenerateRootConfiguration()
if err != nil { if err != nil {
t.Fatalf("err: %v", err) 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()) t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
} }
config, err := core.RootGenerationConfiguration() config, err := core.GenerateRootConfiguration()
if err != nil { if err != nil {
t.Fatalf("err: %v", err) t.Fatalf("err: %v", err)
} }

View file

@ -1,9 +1,7 @@
package xor package xor
import ( import (
"crypto/rand"
"encoding/base64" "encoding/base64"
"fmt"
"testing" "testing"
) )
@ -13,27 +11,6 @@ const (
expectedB64 = "7AmkVw0p6ksamAwv19BVuA==" 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) { func TestBase64XOR(t *testing.T) {
ret, err := XORBase64(tokenB64, xorB64) ret, err := XORBase64(tokenB64, xorB64)
if err != nil { 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/health", handleSysHealth(core))
mux.Handle("/v1/sys/rotate", proxySysRequest(core)) mux.Handle("/v1/sys/rotate", proxySysRequest(core))
mux.Handle("/v1/sys/key-status", proxySysRequest(core)) mux.Handle("/v1/sys/key-status", proxySysRequest(core))
mux.Handle("/v1/sys/root-generation/attempt", handleSysRootGenerationInit(core)) mux.Handle("/v1/sys/generate-root/attempt", handleSysGenerateRootAttempt(core))
mux.Handle("/v1/sys/root-generation/update", handleSysRootGenerationUpdate(core)) mux.Handle("/v1/sys/generate-root/update", handleSysGenerateRootUpdate(core))
mux.Handle("/v1/sys/rekey/init", handleSysRekeyInit(core)) mux.Handle("/v1/sys/rekey/init", handleSysRekeyInit(core))
mux.Handle("/v1/sys/rekey/backup", proxySysRequest(core)) mux.Handle("/v1/sys/rekey/backup", proxySysRequest(core))
mux.Handle("/v1/sys/rekey/update", handleSysRekeyUpdate(core)) mux.Handle("/v1/sys/rekey/update", handleSysRekeyUpdate(core))

View file

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

View file

@ -13,13 +13,13 @@ import (
"github.com/hashicorp/vault/vault" "github.com/hashicorp/vault/vault"
) )
func TestSysRootGenerationInit_Status(t *testing.T) { func TestSysGenerateRootAttempt_Status(t *testing.T) {
core, _, token := vault.TestCoreUnsealed(t) core, _, token := vault.TestCoreUnsealed(t)
ln, addr := TestServer(t, core) ln, addr := TestServer(t, core)
defer ln.Close() defer ln.Close()
TestServerAuth(t, addr, token) 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 { if err != nil {
t.Fatalf("err: %s", err) 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) core, _, token := vault.TestCoreUnsealed(t)
ln, addr := TestServer(t, core) ln, addr := TestServer(t, core)
defer ln.Close() defer ln.Close()
TestServerAuth(t, addr, token) TestServerAuth(t, addr, token)
otpBytes, err := xor.GenerateRandBytes(16) otpBytes, err := vault.GenerateRandBytes(16)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
otp := base64.StdEncoding.EncodeToString(otpBytes) 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, "otp": otp,
}) })
testResponseStatus(t, resp, 204) 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{} var actual map[string]interface{}
expected := 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) core, _, token := vault.TestCoreUnsealed(t)
ln, addr := TestServer(t, core) ln, addr := TestServer(t, core)
defer ln.Close() defer ln.Close()
TestServerAuth(t, addr, token) 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, "pgp_key": pgpkeys.TestPubKey1,
}) })
testResponseStatus(t, resp, 204) 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{} var actual map[string]interface{}
expected := 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) core, _, token := vault.TestCoreUnsealed(t)
ln, addr := TestServer(t, core) ln, addr := TestServer(t, core)
defer ln.Close() defer ln.Close()
TestServerAuth(t, addr, token) TestServerAuth(t, addr, token)
otpBytes, err := xor.GenerateRandBytes(16) otpBytes, err := vault.GenerateRandBytes(16)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
otp := base64.StdEncoding.EncodeToString(otpBytes) 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, "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) 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 { if err != nil {
t.Fatalf("err: %s", err) 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) core, _, token := vault.TestCoreUnsealed(t)
ln, addr := TestServer(t, core) ln, addr := TestServer(t, core)
defer ln.Close() defer ln.Close()
TestServerAuth(t, addr, token) TestServerAuth(t, addr, token)
otpBytes, err := xor.GenerateRandBytes(16) otpBytes, err := vault.GenerateRandBytes(16)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
otp := base64.StdEncoding.EncodeToString(otpBytes) 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", "key": "0123",
"otp": otp, "otp": otp,
}) })
testResponseStatus(t, resp, 400) testResponseStatus(t, resp, 400)
} }
func TestSysRootGeneration_ReInitUpdate(t *testing.T) { func TestSysGenerateRoot_ReAttemptUpdate(t *testing.T) {
core, _, token := vault.TestCoreUnsealed(t) core, _, token := vault.TestCoreUnsealed(t)
ln, addr := TestServer(t, core) ln, addr := TestServer(t, core)
defer ln.Close() defer ln.Close()
TestServerAuth(t, addr, token) TestServerAuth(t, addr, token)
otpBytes, err := xor.GenerateRandBytes(16) otpBytes, err := vault.GenerateRandBytes(16)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
otp := base64.StdEncoding.EncodeToString(otpBytes) 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, "otp": otp,
}) })
testResponseStatus(t, resp, 204) 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) 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, "pgp_key": pgpkeys.TestPubKey1,
}) })
testResponseStatus(t, resp, 204) testResponseStatus(t, resp, 204)
} }
func TestSysRootGeneration_Update_OTP(t *testing.T) { func TestSysGenerateRoot_Update_OTP(t *testing.T) {
core, master, token := vault.TestCoreUnsealed(t) core, master, token := vault.TestCoreUnsealed(t)
ln, addr := TestServer(t, core) ln, addr := TestServer(t, core)
defer ln.Close() defer ln.Close()
TestServerAuth(t, addr, token) TestServerAuth(t, addr, token)
otpBytes, err := xor.GenerateRandBytes(16) otpBytes, err := vault.GenerateRandBytes(16)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
otp := base64.StdEncoding.EncodeToString(otpBytes) 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, "otp": otp,
}) })
testResponseStatus(t, resp, 204) testResponseStatus(t, resp, 204)
// We need to get the nonce first before we update // 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 { if err != nil {
t.Fatalf("err: %s", err) t.Fatalf("err: %s", err)
} }
@ -219,7 +219,7 @@ func TestSysRootGeneration_Update_OTP(t *testing.T) {
testResponseStatus(t, resp, 200) testResponseStatus(t, resp, 200)
testResponseBody(t, resp, &rootGenerationStatus) 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), "nonce": rootGenerationStatus["nonce"].(string),
"key": hex.EncodeToString(master), "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) core, master, token := vault.TestCoreUnsealed(t)
ln, addr := TestServer(t, core) ln, addr := TestServer(t, core)
defer ln.Close() defer ln.Close()
TestServerAuth(t, addr, token) 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, "pgp_key": pgpkeys.TestPubKey1,
}) })
testResponseStatus(t, resp, 204) testResponseStatus(t, resp, 204)
// We need to get the nonce first before we update // 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 { if err != nil {
t.Fatalf("err: %s", err) t.Fatalf("err: %s", err)
} }
@ -297,7 +297,7 @@ func TestSysRootGeneration_Update_PGP(t *testing.T) {
testResponseStatus(t, resp, 200) testResponseStatus(t, resp, 200)
testResponseBody(t, resp, &rootGenerationStatus) 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), "nonce": rootGenerationStatus["nonce"].(string),
"key": hex.EncodeToString(master), "key": hex.EncodeToString(master),
}) })

View file

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

View file

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

View file

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

View file

@ -2,6 +2,7 @@ package vault
import ( import (
"bytes" "bytes"
"crypto/rand"
"crypto/sha256" "crypto/sha256"
"fmt" "fmt"
"log" "log"
@ -341,3 +342,24 @@ func (n *rawHTTP) System() logical.SystemView {
func (n *rawHTTP) Cleanup() { func (n *rawHTTP) Cleanup() {
// noop // 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" layout: "http"
page_title: "HTTP API: /sys/root-generation/" page_title: "HTTP API: /sys/generate-root/"
sidebar_current: "docs-http-sys-root-generation" sidebar_current: "docs-http-sys-generate-root"
description: |- 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 ## GET
@ -21,7 +21,7 @@ description: |-
<dd>GET</dd> <dd>GET</dd>
<dt>URL</dt> <dt>URL</dt>
<dd>`/sys/root-generation/attempt`</dd> <dd>`/sys/generate-root/attempt`</dd>
<dt>Parameters</dt> <dt>Parameters</dt>
<dd> <dd>
@ -65,7 +65,7 @@ description: |-
<dd>PUT</dd> <dd>PUT</dd>
<dt>URL</dt> <dt>URL</dt>
<dd>`/sys/root-generation/attempt`</dd> <dd>`/sys/generate-root/attempt`</dd>
<dt>Parameters</dt> <dt>Parameters</dt>
<dd> <dd>
@ -118,7 +118,7 @@ description: |-
<dd>DELETE</dd> <dd>DELETE</dd>
<dt>URL</dt> <dt>URL</dt>
<dd>`/sys/root-generation/attempt`</dd> <dd>`/sys/generate-root/attempt`</dd>
<dt>Parameters</dt> <dt>Parameters</dt>
<dd>None <dd>None
@ -129,7 +129,7 @@ description: |-
</dd> </dd>
</dl> </dl>
# /sys/root-generation/update # /sys/generate-root/update
## PUT ## PUT
@ -147,7 +147,7 @@ description: |-
<dd>PUT</dd> <dd>PUT</dd>
<dt>URL</dt> <dt>URL</dt>
<dd>`/sys/root-generation/update`</dd> <dd>`/sys/generate-root/update`</dd>
<dt>Parameters</dt> <dt>Parameters</dt>
<dd> <dd>

View file

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