diff --git a/command/renew_test.go b/command/renew_test.go index d43e516d8fc0..219166222085 100644 --- a/command/renew_test.go +++ b/command/renew_test.go @@ -90,6 +90,27 @@ func TestRenewBothWays(t *testing.T) { t.Fatal("bad lease duration") } + // Test another + r = client.NewRequest("PUT", "/v1/sys/leases/renew") + body = map[string]interface{}{ + "lease_id": secret.LeaseID, + } + if err := r.SetJSONBody(body); err != nil { + t.Fatal(err) + } + resp, err = client.RawRequest(r) + if err != nil { + t.Fatal(err) + } + defer resp.Body.Close() + secret, err = api.ParseSecret(resp.Body) + if err != nil { + t.Fatal(err) + } + if secret.LeaseDuration != 60 { + t.Fatal("bad lease duration") + } + // Test the other r = client.NewRequest("PUT", "/v1/sys/renew/"+secret.LeaseID) resp, err = client.RawRequest(r) @@ -104,4 +125,19 @@ func TestRenewBothWays(t *testing.T) { if secret.LeaseDuration != 60 { t.Fatalf("bad lease duration; secret is %#v\n", *secret) } + + // Test another + r = client.NewRequest("PUT", "/v1/sys/leases/renew/"+secret.LeaseID) + resp, err = client.RawRequest(r) + if err != nil { + t.Fatal(err) + } + defer resp.Body.Close() + secret, err = api.ParseSecret(resp.Body) + if err != nil { + t.Fatal(err) + } + if secret.LeaseDuration != 60 { + t.Fatalf("bad lease duration; secret is %#v\n", *secret) + } } diff --git a/http/handler.go b/http/handler.go index bc5914acafa0..3d2a1d8a6805 100644 --- a/http/handler.go +++ b/http/handler.go @@ -50,6 +50,8 @@ func Handler(core *vault.Core) http.Handler { mux.Handle("/v1/sys/unseal", handleSysUnseal(core)) mux.Handle("/v1/sys/renew", handleRequestForwarding(core, handleLogical(core, false, nil))) mux.Handle("/v1/sys/renew/", handleRequestForwarding(core, handleLogical(core, false, nil))) + mux.Handle("/v1/sys/leases/renew", handleRequestForwarding(core, handleLogical(core, false, nil))) + mux.Handle("/v1/sys/leases/renew/", handleRequestForwarding(core, handleLogical(core, false, nil))) mux.Handle("/v1/sys/leader", handleSysLeader(core)) mux.Handle("/v1/sys/health", handleSysHealth(core)) mux.Handle("/v1/sys/generate-root/attempt", handleRequestForwarding(core, handleSysGenerateRootAttempt(core))) diff --git a/http/sys_lease_test.go b/http/sys_lease_test.go index 6b7bc34983f2..de1dc6c84e2d 100644 --- a/http/sys_lease_test.go +++ b/http/sys_lease_test.go @@ -23,14 +23,33 @@ func TestSysRenew(t *testing.T) { // read secret resp = testHttpGet(t, token, addr+"/v1/secret/foo") var result struct { - LeaseId string `json:"lease_id"` + LeaseID string `json:"lease_id"` } if err := jsonutil.DecodeJSONFromReader(resp.Body, &result); err != nil { t.Fatalf("bad: %s", err) } - resp = testHttpPut(t, token, addr+"/v1/sys/renew/"+result.LeaseId, nil) + var renewResult struct { + LeaseID string `json:"lease_id"` + Data map[string]interface{} `json:"data"` + } + resp = testHttpPut(t, token, addr+"/v1/sys/renew/"+result.LeaseID, nil) testResponseStatus(t, resp, 200) + if err := jsonutil.DecodeJSONFromReader(resp.Body, &renewResult); err != nil { + t.Fatal(err) + } + if result.LeaseID != renewResult.LeaseID { + t.Fatal("lease id changed in renew request") + } + + resp = testHttpPut(t, token, addr+"/v1/sys/leases/renew/"+result.LeaseID, nil) + testResponseStatus(t, resp, 200) + if err := jsonutil.DecodeJSONFromReader(resp.Body, &renewResult); err != nil { + t.Fatal(err) + } + if result.LeaseID != renewResult.LeaseID { + t.Fatal("lease id changed in renew request") + } } func TestSysRevoke(t *testing.T) { diff --git a/vault/core_test.go b/vault/core_test.go index ced18cdf70bb..2d54cff24b93 100644 --- a/vault/core_test.go +++ b/vault/core_test.go @@ -1793,6 +1793,19 @@ func TestCore_RenewSameLease(t *testing.T) { if resp.Secret.LeaseID != original { t.Fatalf("lease id changed: %s %s", original, resp.Secret.LeaseID) } + + // Renew the lease (alternate path) + req = logical.TestRequest(t, logical.UpdateOperation, "sys/leases/renew/"+resp.Secret.LeaseID) + req.ClientToken = root + resp, err = c.HandleRequest(req) + if err != nil { + t.Fatalf("err: %v", err) + } + + // Verify the lease did not change + if resp.Secret.LeaseID != original { + t.Fatalf("lease id changed: %s %s", original, resp.Secret.LeaseID) + } } // Renew of a token should not create a new lease @@ -1937,7 +1950,7 @@ path "secret/*" { } // Renew the lease - req = logical.TestRequest(t, logical.UpdateOperation, "sys/renew") + req = logical.TestRequest(t, logical.UpdateOperation, "sys/leases/renew") req.Data = map[string]interface{}{ "lease_id": resp.Secret.LeaseID, } diff --git a/vault/request_handling.go b/vault/request_handling.go index 8f198e9c9acd..a55cf4fc3be3 100644 --- a/vault/request_handling.go +++ b/vault/request_handling.go @@ -226,7 +226,8 @@ func (c *Core) handleRequest(req *logical.Request) (retResp *logical.Response, r // If there is a secret, we must register it with the expiration manager. // We exclude renewal of a lease, since it does not need to be re-registered - if resp != nil && resp.Secret != nil && !strings.HasPrefix(req.Path, "sys/renew") { + if resp != nil && resp.Secret != nil && !strings.HasPrefix(req.Path, "sys/renew") && + !strings.HasPrefix(req.Path, "sys/leases/renew") { // Get the SystemView for the mount sysView := c.router.MatchingSystemView(req.Path) if sysView == nil {