http: renew endpoints
This commit is contained in:
parent
463a32ba56
commit
a44eb0dcd0
|
@ -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))
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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"`
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue