Add renew-self endpoint.

Fixes #455.
This commit is contained in:
Jeff Mitchell 2015-10-07 12:49:13 -04:00
parent 3c914f7fa8
commit 4a52de13e3
3 changed files with 82 additions and 3 deletions

View File

@ -2,7 +2,12 @@
IMPROVEMENTS:
* Base64-encoded PGP keys can be used with the CLI for `init` and `rekey` operations [GH-653]
* init: Base64-encoded PGP keys can be used with the CLI for `init` and `rekey` operations [GH-653]
* core: Tokens can now renew themselves [GH-455]
BUG FIXES:
* core: Fix upgrade path for leases created in `generic` prior to 0.3 [GH-673]
## 0.3.1 (October 6, 2015)

View File

@ -131,7 +131,7 @@ func NewTokenStore(c *Core, config *logical.BackendConfig) (*TokenStore, error)
},
&framework.Path{
Pattern: "revoke-self",
Pattern: "revoke-self$",
Callbacks: map[logical.Operation]framework.OperationFunc{
logical.WriteOperation: t.handleRevokeSelf,
@ -195,6 +195,28 @@ func NewTokenStore(c *Core, config *logical.BackendConfig) (*TokenStore, error)
HelpDescription: strings.TrimSpace(tokenRevokePrefixHelp),
},
&framework.Path{
Pattern: "renew-self$",
Fields: map[string]*framework.FieldSchema{
"token": &framework.FieldSchema{
Type: framework.TypeString,
Description: "Token to renew",
},
"increment": &framework.FieldSchema{
Type: framework.TypeDurationSecond,
Description: "The desired increment in seconds to the token expiration",
},
},
Callbacks: map[logical.Operation]framework.OperationFunc{
logical.WriteOperation: t.handleRenewSelf,
},
HelpSynopsis: strings.TrimSpace(tokenRenewSelfHelp),
HelpDescription: strings.TrimSpace(tokenRenewSelfHelp),
},
&framework.Path{
Pattern: "renew/(?P<token>.+)",
@ -737,6 +759,12 @@ func (ts *TokenStore) handleLookup(
return resp, nil
}
func (ts *TokenStore) handleRenewSelf(
req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
data.Raw["token"] = req.ClientToken
return ts.handleRenew(req, data)
}
// handleRenew handles the auth/token/renew/id path for renewal of tokens.
// This is used to prevent token expiration and revocation.
func (ts *TokenStore) handleRenew(
@ -793,5 +821,6 @@ as revocation of tokens. The tokens are renewable if associated with a lease.`
tokenRevokeSelfHelp = `This endpoint will delete the token used to call it and all of its child tokens.`
tokenRevokeOrphanHelp = `This endpoint will delete the token and orphan its child tokens.`
tokenRevokePrefixHelp = `This endpoint will delete all tokens generated under a prefix with their child tokens.`
tokenRenewHelp = `This endpoint will renew the token and prevent expiration.`
tokenRenewHelp = `This endpoint will renew the given token and prevent expiration.`
tokenRenewSelfHelp = `This endpoint will renew the token used to call it and prevent expiration.`
)

View File

@ -965,6 +965,51 @@ func TestTokenStore_HandleRequest_Renew(t *testing.T) {
}
}
func TestTokenStore_HandleRequest_RenewSelf(t *testing.T) {
exp := mockExpiration(t)
ts := exp.tokenStore
// Create new token
root, err := ts.RootToken()
if err != nil {
t.Fatalf("err: %v", err)
}
// Create a new token
auth := &logical.Auth{
ClientToken: root.ID,
LeaseOptions: logical.LeaseOptions{
TTL: time.Hour,
Renewable: true,
},
}
err = exp.RegisterAuth("auth/token/root", auth)
if err != nil {
t.Fatalf("err: %v", err)
}
// Get the original expire time to compare
originalExpire := auth.ExpirationTime()
beforeRenew := time.Now().UTC()
req := logical.TestRequest(t, logical.WriteOperation, "renew-self")
req.ClientToken = auth.ClientToken
req.Data["increment"] = "3600s"
resp, err := ts.HandleRequest(req)
if err != nil {
t.Fatalf("err: %v %v", err, resp)
}
// Get the new expire time
newExpire := resp.Auth.ExpirationTime()
if newExpire.Before(originalExpire) {
t.Fatalf("should expire later: %s %s", newExpire, originalExpire)
}
if newExpire.Before(beforeRenew.Add(time.Hour)) {
t.Fatalf("should have at least an hour: %s %s", newExpire, beforeRenew)
}
}
func testMakeToken(t *testing.T, ts *TokenStore, root, client string, policy []string) {
req := logical.TestRequest(t, logical.WriteOperation, "create")
req.ClientToken = root