http: renew endpoints

This commit is contained in:
Mitchell Hashimoto 2015-04-13 17:21:31 -07:00
parent 463a32ba56
commit a44eb0dcd0
5 changed files with 132 additions and 45 deletions

View File

@ -26,6 +26,7 @@ func Handler(core *vault.Core) http.Handler {
mux.Handle("/v1/sys/remount", handleSysRemount(core))
mux.Handle("/v1/sys/policy", handleSysListPolicies(core))
mux.Handle("/v1/sys/policy/", handleSysPolicy(core))
mux.Handle("/v1/sys/renew/", handleSysRenew(core))
mux.Handle("/v1/sys/revoke/", handleSysRevoke(core))
mux.Handle("/v1/sys/revoke-prefix/", handleSysRevokePrefix(core))
mux.Handle("/v1/sys/auth/", handleSysAuth(core))

View File

@ -73,53 +73,58 @@ func handleLogical(core *vault.Core) http.Handler {
return
}
var httpResp interface{}
if resp != nil {
if resp.Redirect != "" {
// If we have a redirect, redirect! We use a 302 code
// because we don't actually know if its permanent.
http.Redirect(w, r, resp.Redirect, 302)
return
}
// Build the proper response
respondLogical(w, r, resp)
})
}
logicalResp := &LogicalResponse{Data: resp.Data}
if resp.Secret != nil {
logicalResp.LeaseID = resp.Secret.LeaseID
logicalResp.Renewable = resp.Secret.Renewable
logicalResp.LeaseDuration = int(resp.Secret.Lease.Seconds())
}
// If we have authentication information, then set the cookie
// and setup the result structure.
if resp.Auth != nil {
expireDuration := 365 * 24 * time.Hour
if logicalResp.LeaseDuration != 0 {
expireDuration =
time.Duration(logicalResp.LeaseDuration) * time.Second
}
http.SetCookie(w, &http.Cookie{
Name: AuthCookieName,
Value: resp.Auth.ClientToken,
Path: "/",
Expires: time.Now().UTC().Add(expireDuration),
})
logicalResp.Auth = &Auth{
ClientToken: resp.Auth.ClientToken,
Policies: resp.Auth.Policies,
Metadata: resp.Auth.Metadata,
LeaseDuration: int(resp.Auth.Lease.Seconds()),
Renewable: resp.Auth.Renewable,
}
}
httpResp = logicalResp
func respondLogical(w http.ResponseWriter, r *http.Request, resp *logical.Response) {
var httpResp interface{}
if resp != nil {
if resp.Redirect != "" {
// If we have a redirect, redirect! We use a 302 code
// because we don't actually know if its permanent.
http.Redirect(w, r, resp.Redirect, 302)
return
}
// Respond
respondOk(w, httpResp)
})
logicalResp := &LogicalResponse{Data: resp.Data}
if resp.Secret != nil {
logicalResp.LeaseID = resp.Secret.LeaseID
logicalResp.Renewable = resp.Secret.Renewable
logicalResp.LeaseDuration = int(resp.Secret.Lease.Seconds())
}
// If we have authentication information, then set the cookie
// and setup the result structure.
if resp.Auth != nil {
expireDuration := 365 * 24 * time.Hour
if logicalResp.LeaseDuration != 0 {
expireDuration =
time.Duration(logicalResp.LeaseDuration) * time.Second
}
http.SetCookie(w, &http.Cookie{
Name: AuthCookieName,
Value: resp.Auth.ClientToken,
Path: "/",
Expires: time.Now().UTC().Add(expireDuration),
})
logicalResp.Auth = &Auth{
ClientToken: resp.Auth.ClientToken,
Policies: resp.Auth.Policies,
Metadata: resp.Auth.Metadata,
LeaseDuration: int(resp.Auth.Lease.Seconds()),
Renewable: resp.Auth.Renewable,
}
}
httpResp = logicalResp
}
// Respond
respondOk(w, httpResp)
}
type LogicalResponse struct {

View File

@ -1,6 +1,7 @@
package http
import (
"io"
"net/http"
"strings"
@ -8,6 +9,49 @@ import (
"github.com/hashicorp/vault/vault"
)
func handleSysRenew(core *vault.Core) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.Method != "PUT" {
respondError(w, http.StatusMethodNotAllowed, nil)
return
}
// Determine the path...
prefix := "/v1/sys/renew/"
if !strings.HasPrefix(r.URL.Path, prefix) {
respondError(w, http.StatusNotFound, nil)
return
}
path := r.URL.Path[len(prefix):]
if path == "" {
respondError(w, http.StatusNotFound, nil)
return
}
// Parse the request if we can
var req RenewRequest
if err := parseRequest(r, &req); err != nil {
if err != io.EOF {
respondError(w, http.StatusBadRequest, err)
return
}
}
resp, ok := request(core, w, requestAuth(r, &logical.Request{
Operation: logical.WriteOperation,
Path: "sys/renew/" + path,
Data: map[string]interface{}{
"increment": req.Increment,
},
}))
if !ok {
return
}
respondLogical(w, r, resp)
})
}
func handleSysRevoke(core *vault.Core) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.Method != "PUT" {
@ -71,3 +115,7 @@ func handleSysRevokePrefix(core *vault.Core) http.Handler {
respondOk(w, nil)
})
}
type RenewRequest struct {
Increment int `json:"increment"`
}

View File

@ -1,11 +1,44 @@
package http
import (
"encoding/json"
"net/http"
"testing"
"github.com/hashicorp/vault/vault"
)
func TestSysRenew(t *testing.T) {
core, _, token := vault.TestCoreUnsealed(t)
ln, addr := TestServer(t, core)
defer ln.Close()
TestServerAuth(t, addr, token)
// write secret
resp := testHttpPut(t, addr+"/v1/secret/foo", map[string]interface{}{
"data": "bar",
"lease": "1h",
})
testResponseStatus(t, resp, 204)
// read secret
resp, err := http.Get(addr + "/v1/secret/foo")
if err != nil {
t.Fatalf("err: %s", err)
}
var result struct {
LeaseId string `json:"lease_id"`
}
dec := json.NewDecoder(resp.Body)
if err := dec.Decode(&result); err != nil {
t.Fatalf("bad: %s", err)
}
resp = testHttpPut(t, addr+"/v1/sys/renew/"+result.LeaseId, nil)
testResponseStatus(t, resp, 200)
}
func TestSysRevoke(t *testing.T) {
core, _, token := vault.TestCoreUnsealed(t)
ln, addr := TestServer(t, core)

View File

@ -93,7 +93,7 @@ func (b *PassthroughBackend) handleRead(
if ok {
leaseDuration, err := time.ParseDuration(leaseVal)
if err == nil {
resp.Secret.Renewable = false
resp.Secret.Renewable = true
resp.Secret.Lease = leaseDuration
}
}