diff --git a/api/sys_generate_root.go b/api/sys_generate_root.go index bc185c962..8dc2095f3 100644 --- a/api/sys_generate_root.go +++ b/api/sys_generate_root.go @@ -13,7 +13,7 @@ func (c *Sys) GenerateRootStatus() (*GenerateRootStatusResponse, error) { return &result, err } -func (c *Sys) GenerateRootInit(otp, pgpKey string) error { +func (c *Sys) GenerateRootInit(otp, pgpKey string) (*GenerateRootStatusResponse, error) { body := map[string]interface{}{ "otp": otp, "pgp_key": pgpKey, @@ -21,14 +21,18 @@ func (c *Sys) GenerateRootInit(otp, pgpKey string) error { r := c.c.NewRequest("PUT", "/v1/sys/generate-root/attempt") if err := r.SetJSONBody(body); err != nil { - return err + return nil, err } resp, err := c.c.RawRequest(r) - if err == nil { - defer resp.Body.Close() + if err != nil { + return nil, err } - return err + defer resp.Body.Close() + + var result GenerateRootStatusResponse + err = resp.DecodeJSON(&result) + return &result, err } func (c *Sys) GenerateRootCancel() error { diff --git a/api/sys_rekey.go b/api/sys_rekey.go index acd62ce27..94f8a1462 100644 --- a/api/sys_rekey.go +++ b/api/sys_rekey.go @@ -13,17 +13,21 @@ func (c *Sys) RekeyStatus() (*RekeyStatusResponse, error) { return &result, err } -func (c *Sys) RekeyInit(config *RekeyInitRequest) error { +func (c *Sys) RekeyInit(config *RekeyInitRequest) (*RekeyStatusResponse, error) { r := c.c.NewRequest("PUT", "/v1/sys/rekey/init") if err := r.SetJSONBody(config); err != nil { - return err + return nil, err } resp, err := c.c.RawRequest(r) - if err == nil { - defer resp.Body.Close() + if err != nil { + return nil, err } - return err + defer resp.Body.Close() + + var result RekeyStatusResponse + err = resp.DecodeJSON(&result) + return &result, err } func (c *Sys) RekeyCancel() error { diff --git a/command/generate-root.go b/command/generate-root.go index c20cedb03..67959cd5d 100644 --- a/command/generate-root.go +++ b/command/generate-root.go @@ -140,16 +140,11 @@ func (c *GenerateRootCommand) Run(args []string) int { // Start the root generation process if not started if !rootGenerationStatus.Started { - err = client.Sys().GenerateRootInit(otp, pgpKey) + rootGenerationStatus, 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().GenerateRootStatus() - if err != nil { - c.Ui.Error(fmt.Sprintf("Error reading root generation status: %s", err)) - return 1 - } c.Nonce = rootGenerationStatus.Nonce } @@ -229,14 +224,15 @@ func (c *GenerateRootCommand) decode(encodedVal, otp 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().GenerateRootInit(otp, pgpKey) + status, err := client.Sys().GenerateRootInit(otp, pgpKey) if err != nil { c.Ui.Error(fmt.Sprintf("Error initializing root generation: %s", err)) return 1 } - // Provide the current status - return c.rootGenerationStatus(client) + c.dumpStatus(status) + + return 0 } // cancelGenerateRoot is used to abort the generation process diff --git a/command/rekey.go b/command/rekey.go index c7cb75ea2..326837fd0 100644 --- a/command/rekey.go +++ b/command/rekey.go @@ -78,7 +78,7 @@ func (c *RekeyCommand) Run(args []string) int { // Start the rekey process if not started if !rekeyStatus.Started { - err := client.Sys().RekeyInit(&api.RekeyInitRequest{ + rekeyStatus, err = client.Sys().RekeyInit(&api.RekeyInitRequest{ SecretShares: shares, SecretThreshold: threshold, PGPKeys: pgpKeys, @@ -87,11 +87,6 @@ func (c *RekeyCommand) Run(args []string) int { c.Ui.Error(fmt.Sprintf("Error initializing rekey: %s", err)) return 1 } - rekeyStatus, err = client.Sys().RekeyStatus() - if err != nil { - c.Ui.Error(fmt.Sprintf("Error reading rekey status: %s", err)) - return 1 - } c.Nonce = rekeyStatus.Nonce } @@ -182,7 +177,7 @@ func (c *RekeyCommand) initRekey(client *api.Client, pgpKeys pgpkeys.PubKeyFilesFlag, backup bool) int { // Start the rekey - err := client.Sys().RekeyInit(&api.RekeyInitRequest{ + status, err := client.Sys().RekeyInit(&api.RekeyInitRequest{ SecretShares: shares, SecretThreshold: threshold, PGPKeys: pgpKeys, @@ -214,7 +209,7 @@ be deleted at a later time with 'vault rekey -delete'. } // Provide the current status - return c.rekeyStatus(client) + return c.dumpRekeyStatus(status) } // cancelRekey is used to abort the rekey process @@ -237,6 +232,10 @@ func (c *RekeyCommand) rekeyStatus(client *api.Client) int { return 1 } + return c.dumpRekeyStatus(status) +} + +func (c *RekeyCommand) dumpRekeyStatus(status *api.RekeyStatusResponse) int { // Dump the status statString := fmt.Sprintf( "Nonce: %s\n"+ diff --git a/http/sys_generate_root.go b/http/sys_generate_root.go index 564b8e2b3..132051158 100644 --- a/http/sys_generate_root.go +++ b/http/sys_generate_root.go @@ -86,7 +86,8 @@ func handleSysGenerateRootAttemptPut(core *vault.Core, w http.ResponseWriter, r respondError(w, http.StatusBadRequest, err) return } - respondOk(w, nil) + + handleSysGenerateRootAttemptGet(core, w, r) } func handleSysGenerateRootAttemptDelete(core *vault.Core, w http.ResponseWriter, r *http.Request) { diff --git a/http/sys_generate_root_test.go b/http/sys_generate_root_test.go index 2cfa12eef..8f554bb7e 100644 --- a/http/sys_generate_root_test.go +++ b/http/sys_generate_root_test.go @@ -56,9 +56,7 @@ func TestSysGenerateRootAttempt_Setup_OTP(t *testing.T) { 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/generate-root/attempt") + testResponseStatus(t, resp, 200) var actual map[string]interface{} expected := map[string]interface{}{ @@ -75,6 +73,24 @@ func TestSysGenerateRootAttempt_Setup_OTP(t *testing.T) { if !reflect.DeepEqual(actual, expected) { t.Fatalf("\nexpected: %#v\nactual: %#v", expected, actual) } + + resp = testHttpGet(t, token, addr+"/v1/sys/generate-root/attempt") + + actual = map[string]interface{}{} + expected = map[string]interface{}{ + "started": true, + "progress": float64(0), + "required": float64(1), + "complete": false, + "encoded_root_token": "", + "pgp_fingerprint": "", + } + testResponseStatus(t, resp, 200) + testResponseBody(t, resp, &actual) + expected["nonce"] = actual["nonce"] + if !reflect.DeepEqual(actual, expected) { + t.Fatalf("\nexpected: %#v\nactual: %#v", expected, actual) + } } func TestSysGenerateRootAttempt_Setup_PGP(t *testing.T) { @@ -86,7 +102,7 @@ func TestSysGenerateRootAttempt_Setup_PGP(t *testing.T) { resp := testHttpPut(t, token, addr+"/v1/sys/generate-root/attempt", map[string]interface{}{ "pgp_key": pgpkeys.TestPubKey1, }) - testResponseStatus(t, resp, 204) + testResponseStatus(t, resp, 200) resp = testHttpGet(t, token, addr+"/v1/sys/generate-root/attempt") @@ -123,6 +139,23 @@ func TestSysGenerateRootAttempt_Cancel(t *testing.T) { "otp": otp, }) + var actual map[string]interface{} + expected := map[string]interface{}{ + "started": true, + "progress": float64(0), + "required": float64(1), + "complete": false, + "encoded_root_token": "", + "pgp_fingerprint": "", + } + testResponseStatus(t, resp, 200) + testResponseBody(t, resp, &actual) + expected["nonce"] = actual["nonce"] + if !reflect.DeepEqual(actual, expected) { + t.Fatalf("\nexpected: %#v\nactual: %#v", expected, actual) + } + initialNonce := expected["nonce"].(string) + resp = testHttpDelete(t, token, addr+"/v1/sys/generate-root/attempt") testResponseStatus(t, resp, 204) @@ -131,8 +164,8 @@ func TestSysGenerateRootAttempt_Cancel(t *testing.T) { t.Fatalf("err: %s", err) } - var actual map[string]interface{} - expected := map[string]interface{}{ + actual = map[string]interface{}{} + expected = map[string]interface{}{ "started": false, "progress": float64(0), "required": float64(1), @@ -146,6 +179,10 @@ func TestSysGenerateRootAttempt_Cancel(t *testing.T) { if !reflect.DeepEqual(actual, expected) { t.Fatalf("\nexpected: %#v\nactual: %#v", expected, actual) } + + if expected["nonce"].(string) == initialNonce { + t.Fatalf("Same nonce detected across two invocations") + } } func TestSysGenerateRoot_badKey(t *testing.T) { @@ -181,7 +218,7 @@ func TestSysGenerateRoot_ReAttemptUpdate(t *testing.T) { resp := testHttpPut(t, token, addr+"/v1/sys/generate-root/attempt", map[string]interface{}{ "otp": otp, }) - testResponseStatus(t, resp, 204) + testResponseStatus(t, resp, 200) resp = testHttpDelete(t, token, addr+"/v1/sys/generate-root/attempt") testResponseStatus(t, resp, 204) @@ -190,7 +227,7 @@ func TestSysGenerateRoot_ReAttemptUpdate(t *testing.T) { "pgp_key": pgpkeys.TestPubKey1, }) - testResponseStatus(t, resp, 204) + testResponseStatus(t, resp, 200) } func TestSysGenerateRoot_Update_OTP(t *testing.T) { @@ -208,13 +245,6 @@ func TestSysGenerateRoot_Update_OTP(t *testing.T) { 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/generate-root/attempt") - if err != nil { - t.Fatalf("err: %s", err) - } var rootGenerationStatus map[string]interface{} testResponseStatus(t, resp, 200) testResponseBody(t, resp, &rootGenerationStatus) @@ -287,7 +317,7 @@ func TestSysGenerateRoot_Update_PGP(t *testing.T) { resp := testHttpPut(t, token, addr+"/v1/sys/generate-root/attempt", map[string]interface{}{ "pgp_key": pgpkeys.TestPubKey1, }) - testResponseStatus(t, resp, 204) + testResponseStatus(t, resp, 200) // We need to get the nonce first before we update resp, err := http.Get(addr + "/v1/sys/generate-root/attempt") diff --git a/http/sys_rekey.go b/http/sys_rekey.go index 055a6a9a9..7cec749e4 100644 --- a/http/sys_rekey.go +++ b/http/sys_rekey.go @@ -100,7 +100,8 @@ func handleSysRekeyInitPut(core *vault.Core, w http.ResponseWriter, r *http.Requ respondError(w, http.StatusBadRequest, err) return } - respondOk(w, nil) + + handleSysRekeyInitGet(core, w, r) } func handleSysRekeyInitDelete(core *vault.Core, w http.ResponseWriter, r *http.Request) { diff --git a/http/sys_rekey_test.go b/http/sys_rekey_test.go index 26e5172ed..c375cc9e8 100644 --- a/http/sys_rekey_test.go +++ b/http/sys_rekey_test.go @@ -48,9 +48,7 @@ func TestSysRekeyInit_Setup(t *testing.T) { "secret_shares": 5, "secret_threshold": 3, }) - testResponseStatus(t, resp, 204) - - resp = testHttpGet(t, token, addr+"/v1/sys/rekey/init") + testResponseStatus(t, resp, 200) var actual map[string]interface{} expected := map[string]interface{}{ @@ -68,6 +66,25 @@ func TestSysRekeyInit_Setup(t *testing.T) { if !reflect.DeepEqual(actual, expected) { t.Fatalf("\nexpected: %#v\nactual: %#v", expected, actual) } + + resp = testHttpGet(t, token, addr+"/v1/sys/rekey/init") + + actual = map[string]interface{}{} + expected = map[string]interface{}{ + "started": true, + "t": float64(3), + "n": float64(5), + "progress": float64(0), + "required": float64(1), + "pgp_fingerprints": interface{}(nil), + "backup": false, + } + testResponseStatus(t, resp, 200) + testResponseBody(t, resp, &actual) + expected["nonce"] = actual["nonce"] + if !reflect.DeepEqual(actual, expected) { + t.Fatalf("\nexpected: %#v\nactual: %#v", expected, actual) + } } func TestSysRekeyInit_Cancel(t *testing.T) { @@ -80,7 +97,7 @@ func TestSysRekeyInit_Cancel(t *testing.T) { "secret_shares": 5, "secret_threshold": 3, }) - testResponseStatus(t, resp, 204) + testResponseStatus(t, resp, 200) resp = testHttpDelete(t, token, addr+"/v1/sys/rekey/init") testResponseStatus(t, resp, 204) @@ -130,13 +147,6 @@ func TestSysRekey_Update(t *testing.T) { "secret_shares": 5, "secret_threshold": 3, }) - testResponseStatus(t, resp, 204) - - // We need to get the nonce first before we update - resp, err := http.Get(addr + "/v1/sys/rekey/init") - if err != nil { - t.Fatalf("err: %s", err) - } var rekeyStatus map[string]interface{} testResponseStatus(t, resp, 200) testResponseBody(t, resp, &rekeyStatus) @@ -177,7 +187,7 @@ func TestSysRekey_ReInitUpdate(t *testing.T) { "secret_shares": 5, "secret_threshold": 3, }) - testResponseStatus(t, resp, 204) + testResponseStatus(t, resp, 200) resp = testHttpDelete(t, token, addr+"/v1/sys/rekey/init") testResponseStatus(t, resp, 204) @@ -186,7 +196,7 @@ func TestSysRekey_ReInitUpdate(t *testing.T) { "secret_shares": 5, "secret_threshold": 3, }) - testResponseStatus(t, resp, 204) + testResponseStatus(t, resp, 200) resp = testHttpPut(t, token, addr+"/v1/sys/rekey/update", map[string]interface{}{ "key": hex.EncodeToString(master),