mirror of
https://github.com/optim-enterprises-bv/vault.git
synced 2025-11-02 19:47:54 +00:00
Core handling of TTLs (#4230)
* govet cleanup in token store * adding general ttl handling to login requests * consolidating TTL calculation to system view * deprecate LeaseExtend * deprecate LeaseExtend * set the increment to the correct value * move calculateTTL out of SystemView * remove unused value * add back clearing of lease id * implement core ttl in some backends * removing increment and issue time from lease options * adding ttl tests, fixing some compile issue * adding ttl tests * fixing some explicit max TTL logic * fixing up some tests * removing unneeded test * off by one errors... * adding back some logic for bc * adding period to return on renewal * tweaking max ttl capping slightly * use the appropriate precision for ttl calculation * deprecate proto fields instead of delete * addressing feedback * moving TTL handling for backends to core * mongo is a secret backend not auth * adding estimated ttl for backends that also manage the expiration time * set the estimate values before calling the renew request * moving calculate TTL to framework, revert removal of increment and issue time from logical * minor edits * addressing feedback * address more feedback
This commit is contained in:
@@ -20,7 +20,6 @@ func TestCopy_auth(t *testing.T) {
|
||||
expected := logical.Auth{
|
||||
LeaseOptions: logical.LeaseOptions{
|
||||
TTL: 1 * time.Hour,
|
||||
IssueTime: time.Now(),
|
||||
},
|
||||
|
||||
ClientToken: "foo",
|
||||
@@ -184,7 +183,6 @@ func TestHash(t *testing.T) {
|
||||
&logical.Auth{
|
||||
LeaseOptions: logical.LeaseOptions{
|
||||
TTL: 1 * time.Hour,
|
||||
IssueTime: now,
|
||||
},
|
||||
|
||||
ClientToken: "foo",
|
||||
@@ -192,7 +190,6 @@ func TestHash(t *testing.T) {
|
||||
&logical.Auth{
|
||||
LeaseOptions: logical.LeaseOptions{
|
||||
TTL: 1 * time.Hour,
|
||||
IssueTime: now,
|
||||
},
|
||||
|
||||
ClientToken: "hmac-sha256:08ba357e274f528065766c770a639abf6809b39ccfd37c2a3157c7f51954da0a",
|
||||
|
||||
@@ -146,7 +146,7 @@ func (b *backend) pathLoginRenew(ctx context.Context, req *logical.Request, d *f
|
||||
return nil, fmt.Errorf("policies do not match")
|
||||
}
|
||||
|
||||
return framework.LeaseExtend(0, 0, b.System())(ctx, req, d)
|
||||
return &logical.Response{Auth: req.Auth}, nil
|
||||
}
|
||||
|
||||
func (b *backend) verifyCredentials(ctx context.Context, req *logical.Request, appId, userId string) (string, *logical.Response, error) {
|
||||
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/errwrap"
|
||||
"github.com/hashicorp/vault/logical"
|
||||
@@ -107,17 +106,11 @@ func (b *backend) pathLoginRenew(ctx context.Context, req *logical.Request, data
|
||||
return nil, fmt.Errorf("role %s does not exist during renewal", roleName)
|
||||
}
|
||||
|
||||
// If a period is provided, set that as part of resp.Auth.Period and return a
|
||||
// response immediately. Let expiration manager handle renewal from there on.
|
||||
if role.Period > time.Duration(0) {
|
||||
resp := &logical.Response{
|
||||
Auth: req.Auth,
|
||||
}
|
||||
resp := &logical.Response{Auth: req.Auth}
|
||||
resp.Auth.TTL = role.TokenTTL
|
||||
resp.Auth.MaxTTL = role.TokenMaxTTL
|
||||
resp.Auth.Period = role.Period
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
return framework.LeaseExtend(role.TokenTTL, role.TokenMaxTTL, b.System())(ctx, req, data)
|
||||
}
|
||||
|
||||
const pathLoginHelpSys = "Issue a token based on the credentials supplied"
|
||||
|
||||
@@ -147,7 +147,6 @@ func generateRenewRequest(s logical.Storage, auth *logical.Auth) *logical.Reques
|
||||
renewReq.Auth.Metadata = auth.Metadata
|
||||
renewReq.Auth.LeaseOptions = auth.LeaseOptions
|
||||
renewReq.Auth.Policies = auth.Policies
|
||||
renewReq.Auth.IssueTime = time.Now()
|
||||
renewReq.Auth.Period = auth.Period
|
||||
|
||||
return renewReq
|
||||
|
||||
@@ -112,11 +112,6 @@ func (b *backend) validateCredentials(ctx context.Context, req *logical.Request,
|
||||
return nil, "", metadata, "", fmt.Errorf("failed to validate role_id"), nil
|
||||
}
|
||||
|
||||
// Calculate the TTL boundaries since this reflects the properties of the token issued
|
||||
if role.TokenTTL, role.TokenMaxTTL, err = b.SanitizeTTL(role.TokenTTL, role.TokenMaxTTL); err != nil {
|
||||
return nil, "", metadata, "", nil, err
|
||||
}
|
||||
|
||||
var secretID string
|
||||
if role.BindSecretID {
|
||||
// If 'bind_secret_id' was set on role, look for the field 'secret_id'
|
||||
|
||||
@@ -1733,7 +1733,6 @@ func generateRenewRequest(s logical.Storage, auth *logical.Auth) *logical.Reques
|
||||
renewReq.Auth.Metadata = auth.Metadata
|
||||
renewReq.Auth.LeaseOptions = auth.LeaseOptions
|
||||
renewReq.Auth.Policies = auth.Policies
|
||||
renewReq.Auth.IssueTime = time.Now()
|
||||
renewReq.Auth.Period = auth.Period
|
||||
|
||||
return renewReq
|
||||
|
||||
@@ -809,6 +809,7 @@ func (b *backend) pathLoginUpdateEc2(ctx context.Context, req *logical.Request,
|
||||
LeaseOptions: logical.LeaseOptions{
|
||||
Renewable: true,
|
||||
TTL: roleEntry.TTL,
|
||||
MaxTTL: shortestMaxTTL,
|
||||
},
|
||||
Alias: &logical.Alias{
|
||||
Name: identityDocParsed.InstanceID,
|
||||
@@ -826,16 +827,6 @@ func (b *backend) pathLoginUpdateEc2(ctx context.Context, req *logical.Request,
|
||||
resp.Auth.Metadata["nonce"] = clientNonce
|
||||
}
|
||||
|
||||
// In this case no role value was set so pull in what will be assigned by
|
||||
// Core for comparison
|
||||
if resp.Auth.TTL == 0 {
|
||||
resp.Auth.TTL = b.System().DefaultLeaseTTL()
|
||||
}
|
||||
if resp.Auth.TTL > shortestMaxTTL {
|
||||
resp.Auth.TTL = shortestMaxTTL
|
||||
resp.AddWarning(fmt.Sprintf("Effective TTL of '%s' exceeded the effective max_ttl of '%s'; TTL value is capped accordingly", resp.Auth.TTL, shortestMaxTTL))
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
@@ -1025,17 +1016,11 @@ func (b *backend) pathLoginRenewIam(ctx context.Context, req *logical.Request, d
|
||||
}
|
||||
}
|
||||
|
||||
// If a period is provided, set that as part of resp.Auth.Period and return a
|
||||
// response immediately. Let expiration manager handle renewal from there on.
|
||||
if roleEntry.Period > time.Duration(0) {
|
||||
resp := &logical.Response{
|
||||
Auth: req.Auth,
|
||||
}
|
||||
resp := &logical.Response{Auth: req.Auth}
|
||||
resp.Auth.TTL = roleEntry.TTL
|
||||
resp.Auth.MaxTTL = roleEntry.MaxTTL
|
||||
resp.Auth.Period = roleEntry.Period
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
return framework.LeaseExtend(roleEntry.TTL, roleEntry.MaxTTL, b.System())(ctx, req, data)
|
||||
}
|
||||
|
||||
func (b *backend) pathLoginRenewEc2(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
||||
@@ -1115,17 +1100,11 @@ func (b *backend) pathLoginRenewEc2(ctx context.Context, req *logical.Request, d
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// If a period is provided, set that as part of resp.Auth.Period and return a
|
||||
// response immediately. Let expiration manager handle renewal from there on.
|
||||
if roleEntry.Period > time.Duration(0) {
|
||||
resp := &logical.Response{
|
||||
Auth: req.Auth,
|
||||
}
|
||||
resp := &logical.Response{Auth: req.Auth}
|
||||
resp.Auth.TTL = roleEntry.TTL
|
||||
resp.Auth.MaxTTL = shortestMaxTTL
|
||||
resp.Auth.Period = roleEntry.Period
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
return framework.LeaseExtend(roleEntry.TTL, shortestMaxTTL, b.System())(ctx, req, data)
|
||||
}
|
||||
|
||||
func (b *backend) pathLoginUpdateIam(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
||||
|
||||
@@ -1416,7 +1416,6 @@ func Test_Renew(t *testing.T) {
|
||||
req.Auth.Metadata = resp.Auth.Metadata
|
||||
req.Auth.LeaseOptions = resp.Auth.LeaseOptions
|
||||
req.Auth.Policies = resp.Auth.Policies
|
||||
req.Auth.IssueTime = time.Now()
|
||||
req.Auth.Period = resp.Auth.Period
|
||||
|
||||
// Normal renewal
|
||||
|
||||
@@ -11,7 +11,6 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/vault/helper/certutil"
|
||||
"github.com/hashicorp/vault/helper/policyutil"
|
||||
@@ -72,11 +71,6 @@ func (b *backend) pathLogin(ctx context.Context, req *logical.Request, data *fra
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
ttl := matched.Entry.TTL
|
||||
if ttl == 0 {
|
||||
ttl = b.System().DefaultLeaseTTL()
|
||||
}
|
||||
|
||||
clientCerts := req.Connection.ConnState.PeerCertificates
|
||||
if len(clientCerts) == 0 {
|
||||
return logical.ErrorResponse("no client certificate found"), nil
|
||||
@@ -101,7 +95,8 @@ func (b *backend) pathLogin(ctx context.Context, req *logical.Request, data *fra
|
||||
},
|
||||
LeaseOptions: logical.LeaseOptions{
|
||||
Renewable: true,
|
||||
TTL: ttl,
|
||||
TTL: matched.Entry.TTL,
|
||||
MaxTTL: matched.Entry.MaxTTL,
|
||||
},
|
||||
Alias: &logical.Alias{
|
||||
Name: clientCerts[0].SerialNumber.String(),
|
||||
@@ -109,20 +104,6 @@ func (b *backend) pathLogin(ctx context.Context, req *logical.Request, data *fra
|
||||
},
|
||||
}
|
||||
|
||||
if matched.Entry.MaxTTL > time.Duration(0) {
|
||||
// Cap maxTTL to the sysview's max TTL
|
||||
maxTTL := matched.Entry.MaxTTL
|
||||
if maxTTL > b.System().MaxLeaseTTL() {
|
||||
maxTTL = b.System().MaxLeaseTTL()
|
||||
}
|
||||
|
||||
// Cap TTL to MaxTTL
|
||||
if resp.Auth.TTL > maxTTL {
|
||||
resp.AddWarning(fmt.Sprintf("Effective TTL of '%s' exceeded the effective max_ttl of '%s'; TTL value is capped accordingly", (resp.Auth.TTL / time.Second), (maxTTL / time.Second)))
|
||||
resp.Auth.TTL = maxTTL
|
||||
}
|
||||
}
|
||||
|
||||
// Generate a response
|
||||
return resp, nil
|
||||
}
|
||||
@@ -175,17 +156,11 @@ func (b *backend) pathLoginRenew(ctx context.Context, req *logical.Request, d *f
|
||||
return nil, fmt.Errorf("policies have changed, not renewing")
|
||||
}
|
||||
|
||||
// If a period is provided, set that as part of resp.Auth.Period and return a
|
||||
// response immediately. Let expiration manager handle renewal from there on.
|
||||
if cert.Period > time.Duration(0) {
|
||||
resp := &logical.Response{
|
||||
Auth: req.Auth,
|
||||
}
|
||||
resp := &logical.Response{Auth: req.Auth}
|
||||
resp.Auth.TTL = cert.TTL
|
||||
resp.Auth.MaxTTL = cert.MaxTTL
|
||||
resp.Auth.Period = cert.Period
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
return framework.LeaseExtend(cert.TTL, cert.MaxTTL, b.System())(ctx, req, d)
|
||||
}
|
||||
|
||||
func (b *backend) verifyCredentials(ctx context.Context, req *logical.Request, d *framework.FieldData) (*ParsedCert, *logical.Response, error) {
|
||||
|
||||
@@ -67,7 +67,7 @@ func (b *backend) pathLogin(ctx context.Context, req *logical.Request, data *fra
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ttl, _, err := b.SanitizeTTLStr(config.TTL.String(), config.MaxTTL.String())
|
||||
ttl, maxTTL, err := b.SanitizeTTLStr(config.TTL.String(), config.MaxTTL.String())
|
||||
if err != nil {
|
||||
return logical.ErrorResponse(fmt.Sprintf("error sanitizing TTLs: %s", err)), nil
|
||||
}
|
||||
@@ -85,6 +85,7 @@ func (b *backend) pathLogin(ctx context.Context, req *logical.Request, data *fra
|
||||
DisplayName: *verifyResp.User.Login,
|
||||
LeaseOptions: logical.LeaseOptions{
|
||||
TTL: ttl,
|
||||
MaxTTL: maxTTL,
|
||||
Renewable: true,
|
||||
},
|
||||
Alias: &logical.Alias{
|
||||
@@ -133,10 +134,9 @@ func (b *backend) pathLoginRenew(ctx context.Context, req *logical.Request, d *f
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := framework.LeaseExtend(config.TTL, config.MaxTTL, b.System())(ctx, req, d)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resp := &logical.Response{Auth: req.Auth}
|
||||
resp.Auth.TTL = config.TTL
|
||||
resp.Auth.MaxTTL = config.MaxTTL
|
||||
|
||||
// Remove old aliases
|
||||
resp.Auth.GroupAliases = nil
|
||||
|
||||
@@ -111,10 +111,7 @@ func (b *backend) pathLoginRenew(ctx context.Context, req *logical.Request, d *f
|
||||
return nil, fmt.Errorf("policies have changed, not renewing")
|
||||
}
|
||||
|
||||
resp, err = framework.LeaseExtend(0, 0, b.System())(ctx, req, d)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resp.Auth = req.Auth
|
||||
|
||||
// Remove old aliases
|
||||
resp.Auth.GroupAliases = nil
|
||||
|
||||
@@ -89,6 +89,7 @@ func (b *backend) pathLogin(ctx context.Context, req *logical.Request, d *framew
|
||||
DisplayName: username,
|
||||
LeaseOptions: logical.LeaseOptions{
|
||||
TTL: cfg.TTL,
|
||||
MaxTTL: cfg.MaxTTL,
|
||||
Renewable: true,
|
||||
},
|
||||
Alias: &logical.Alias{
|
||||
@@ -96,21 +97,6 @@ func (b *backend) pathLogin(ctx context.Context, req *logical.Request, d *framew
|
||||
},
|
||||
}
|
||||
|
||||
if resp.Auth.TTL == 0 {
|
||||
resp.Auth.TTL = b.System().DefaultLeaseTTL()
|
||||
}
|
||||
if cfg.MaxTTL > 0 {
|
||||
maxTTL := cfg.MaxTTL
|
||||
if maxTTL > b.System().MaxLeaseTTL() {
|
||||
maxTTL = b.System().MaxLeaseTTL()
|
||||
}
|
||||
|
||||
if resp.Auth.TTL > maxTTL {
|
||||
resp.Auth.TTL = maxTTL
|
||||
resp.AddWarning(fmt.Sprintf("Effective TTL of '%s' exceeded the effective max_ttl of '%s'; TTL value is capped accordingly", resp.Auth.TTL, maxTTL))
|
||||
}
|
||||
}
|
||||
|
||||
for _, groupName := range groupNames {
|
||||
if groupName == "" {
|
||||
continue
|
||||
@@ -141,10 +127,9 @@ func (b *backend) pathLoginRenew(ctx context.Context, req *logical.Request, d *f
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp, err = framework.LeaseExtend(cfg.TTL, cfg.MaxTTL, b.System())(ctx, req, d)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resp.Auth = req.Auth
|
||||
resp.Auth.TTL = cfg.TTL
|
||||
resp.Auth.MaxTTL = cfg.MaxTTL
|
||||
|
||||
// Remove old aliases
|
||||
resp.Auth.GroupAliases = nil
|
||||
|
||||
@@ -88,6 +88,7 @@ func (b *backend) pathLogin(ctx context.Context, req *logical.Request, d *framew
|
||||
}
|
||||
}
|
||||
|
||||
resp.Auth = req.Auth
|
||||
resp.Auth = &logical.Auth{
|
||||
Policies: policies,
|
||||
Metadata: map[string]string{
|
||||
@@ -126,7 +127,7 @@ func (b *backend) pathLoginRenew(ctx context.Context, req *logical.Request, d *f
|
||||
return nil, fmt.Errorf("policies have changed, not renewing")
|
||||
}
|
||||
|
||||
return framework.LeaseExtend(0, 0, b.System())(ctx, req, d)
|
||||
return &logical.Response{Auth: req.Auth}, nil
|
||||
}
|
||||
|
||||
func (b *backend) RadiusLogin(ctx context.Context, req *logical.Request, username string, password string) ([]string, *logical.Response, error) {
|
||||
|
||||
@@ -18,57 +18,6 @@ const (
|
||||
testSysMaxTTL = time.Hour * 20
|
||||
)
|
||||
|
||||
func TestBackend_TTLDurations(t *testing.T) {
|
||||
data1 := map[string]interface{}{
|
||||
"password": "password",
|
||||
"policies": "root",
|
||||
"ttl": "21h",
|
||||
"max_ttl": "11h",
|
||||
}
|
||||
data2 := map[string]interface{}{
|
||||
"password": "password",
|
||||
"policies": "root",
|
||||
"ttl": "10h",
|
||||
"max_ttl": "21h",
|
||||
}
|
||||
data3 := map[string]interface{}{
|
||||
"password": "password",
|
||||
"policies": "root",
|
||||
"ttl": "10h",
|
||||
"max_ttl": "10h",
|
||||
}
|
||||
data4 := map[string]interface{}{
|
||||
"password": "password",
|
||||
"policies": "root",
|
||||
"ttl": "11h",
|
||||
"max_ttl": "5h",
|
||||
}
|
||||
data5 := map[string]interface{}{
|
||||
"password": "password",
|
||||
}
|
||||
b, err := Factory(context.Background(), &logical.BackendConfig{
|
||||
Logger: nil,
|
||||
System: &logical.StaticSystemView{
|
||||
DefaultLeaseTTLVal: testSysTTL,
|
||||
MaxLeaseTTLVal: testSysMaxTTL,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to create backend: %s", err)
|
||||
}
|
||||
logicaltest.Test(t, logicaltest.TestCase{
|
||||
Backend: b,
|
||||
Steps: []logicaltest.TestStep{
|
||||
testUsersWrite(t, "test", data1, true),
|
||||
testUsersWrite(t, "test", data2, true),
|
||||
testUsersWrite(t, "test", data3, false),
|
||||
testUsersWrite(t, "test", data4, false),
|
||||
testLoginWrite(t, "test", data5, false),
|
||||
testLoginWrite(t, "wrong", data5, true),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func TestBackend_basic(t *testing.T) {
|
||||
b, err := Factory(context.Background(), &logical.BackendConfig{
|
||||
Logger: nil,
|
||||
|
||||
@@ -91,6 +91,7 @@ func (b *backend) pathLogin(ctx context.Context, req *logical.Request, d *framew
|
||||
DisplayName: username,
|
||||
LeaseOptions: logical.LeaseOptions{
|
||||
TTL: user.TTL,
|
||||
MaxTTL: user.MaxTTL,
|
||||
Renewable: true,
|
||||
},
|
||||
Alias: &logical.Alias{
|
||||
@@ -115,7 +116,10 @@ func (b *backend) pathLoginRenew(ctx context.Context, req *logical.Request, d *f
|
||||
return nil, fmt.Errorf("policies have changed, not renewing")
|
||||
}
|
||||
|
||||
return framework.LeaseExtend(user.TTL, user.MaxTTL, b.System())(ctx, req, d)
|
||||
resp := &logical.Response{Auth: req.Auth}
|
||||
resp.Auth.TTL = user.TTL
|
||||
resp.Auth.MaxTTL = user.MaxTTL
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
const pathLoginSyn = `
|
||||
|
||||
@@ -243,6 +243,7 @@ func (b *backend) secretAccessKeysCreate(
|
||||
}
|
||||
|
||||
resp.Secret.TTL = lease.Lease
|
||||
resp.Secret.MaxTTL = lease.LeaseMax
|
||||
|
||||
if usernameWarning != "" {
|
||||
resp.AddWarning(usernameWarning)
|
||||
@@ -271,8 +272,10 @@ func (b *backend) secretAccessKeysRenew(ctx context.Context, req *logical.Reques
|
||||
lease = &configLease{}
|
||||
}
|
||||
|
||||
f := framework.LeaseExtend(lease.Lease, lease.LeaseMax, b.System())
|
||||
return f(ctx, req, d)
|
||||
resp := &logical.Response{Secret: req.Secret}
|
||||
resp.Secret.TTL = lease.Lease
|
||||
resp.Secret.MaxTTL = lease.LeaseMax
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func secretAccessKeysRevoke(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
||||
|
||||
@@ -47,7 +47,9 @@ func (b *backend) secretCredsRenew(ctx context.Context, req *logical.Request, d
|
||||
return nil, fmt.Errorf("unable to load role: %s", err)
|
||||
}
|
||||
|
||||
return framework.LeaseExtend(role.Lease, 0, b.System())(ctx, req, d)
|
||||
resp := &logical.Response{Secret: req.Secret}
|
||||
resp.Secret.TTL = role.Lease
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (b *backend) secretCredsRevoke(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
||||
|
||||
@@ -206,7 +206,6 @@ func TestBackend_renew_revoke(t *testing.T) {
|
||||
}
|
||||
|
||||
generatedSecret := resp.Secret
|
||||
generatedSecret.IssueTime = time.Now()
|
||||
generatedSecret.TTL = 6 * time.Hour
|
||||
|
||||
var d struct {
|
||||
|
||||
@@ -28,14 +28,15 @@ func secretToken(b *backend) *framework.Secret {
|
||||
}
|
||||
|
||||
func (b *backend) secretTokenRenew(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
||||
resp := &logical.Response{Secret: req.Secret}
|
||||
roleRaw, ok := req.Secret.InternalData["role"]
|
||||
if !ok || roleRaw == nil {
|
||||
return framework.LeaseExtend(0, 0, b.System())(ctx, req, d)
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
role, ok := roleRaw.(string)
|
||||
if !ok {
|
||||
return framework.LeaseExtend(0, 0, b.System())(ctx, req, d)
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
entry, err := req.Storage.Get(ctx, "policy/"+role)
|
||||
@@ -50,8 +51,8 @@ func (b *backend) secretTokenRenew(ctx context.Context, req *logical.Request, d
|
||||
if err := entry.DecodeJSON(&result); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return framework.LeaseExtend(result.Lease, 0, b.System())(ctx, req, d)
|
||||
resp.Secret.TTL = result.Lease
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func secretTokenRevoke(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
// Code generated by protoc-gen-go.
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// source: builtin/logical/database/dbplugin/database.proto
|
||||
// DO NOT EDIT!
|
||||
|
||||
/*
|
||||
Package dbplugin is a generated protocol buffer package.
|
||||
|
||||
@@ -3,6 +3,7 @@ package database
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/vault/logical"
|
||||
"github.com/hashicorp/vault/logical/framework"
|
||||
@@ -42,12 +43,6 @@ func (b *databaseBackend) secretCredsRenew() framework.OperationFunc {
|
||||
return nil, fmt.Errorf("error during renew: could not find role with name %s", req.Secret.InternalData["role"])
|
||||
}
|
||||
|
||||
f := framework.LeaseExtend(role.DefaultTTL, role.MaxTTL, b.System())
|
||||
resp, err := f(ctx, req, data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Get the Database object
|
||||
db, err := b.GetConnection(ctx, req.Storage, role.DBName)
|
||||
if err != nil {
|
||||
@@ -58,13 +53,24 @@ func (b *databaseBackend) secretCredsRenew() framework.OperationFunc {
|
||||
defer db.RUnlock()
|
||||
|
||||
// Make sure we increase the VALID UNTIL endpoint for this user.
|
||||
if expireTime := resp.Secret.ExpirationTime(); !expireTime.IsZero() {
|
||||
ttl, _, err := framework.CalculateTTL(b.System(), req.Secret.Increment, role.DefaultTTL, 0, role.MaxTTL, 0, req.Secret.IssueTime)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if ttl > 0 {
|
||||
expireTime := time.Now().Add(ttl)
|
||||
// Adding a small buffer since the TTL will be calculated again after this call
|
||||
// to ensure the database credential does not expire before the lease
|
||||
expireTime = expireTime.Add(5 * time.Second)
|
||||
err := db.RenewUser(ctx, role.Statements, username, expireTime)
|
||||
if err != nil {
|
||||
b.CloseIfShutdown(db, err)
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
resp := &logical.Response{Secret: req.Secret}
|
||||
resp.Secret.TTL = role.DefaultTTL
|
||||
resp.Secret.MaxTTL = role.MaxTTL
|
||||
return resp, nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,8 +41,10 @@ func (b *backend) secretCredsRenew(ctx context.Context, req *logical.Request, d
|
||||
leaseConfig = &configLease{}
|
||||
}
|
||||
|
||||
f := framework.LeaseExtend(leaseConfig.TTL, leaseConfig.MaxTTL, b.System())
|
||||
return f(ctx, req, d)
|
||||
resp := &logical.Response{Secret: req.Secret}
|
||||
resp.Secret.TTL = leaseConfig.TTL
|
||||
resp.Secret.MaxTTL = leaseConfig.MaxTTL
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (b *backend) secretCredsRevoke(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
||||
|
||||
@@ -41,8 +41,10 @@ func (b *backend) secretCredsRenew(ctx context.Context, req *logical.Request, d
|
||||
leaseConfig = &configLease{}
|
||||
}
|
||||
|
||||
f := framework.LeaseExtend(leaseConfig.TTL, leaseConfig.TTLMax, b.System())
|
||||
return f(ctx, req, d)
|
||||
resp := &logical.Response{Secret: req.Secret}
|
||||
resp.Secret.TTL = leaseConfig.TTL
|
||||
resp.Secret.MaxTTL = leaseConfig.TTLMax
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (b *backend) secretCredsRevoke(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
||||
|
||||
@@ -130,11 +130,8 @@ func (b *backend) pathRoleCreateRead(ctx context.Context, req *logical.Request,
|
||||
"role": name,
|
||||
})
|
||||
|
||||
ttl := lease.Lease
|
||||
if ttl == 0 || (lease.LeaseMax > 0 && ttl > lease.LeaseMax) {
|
||||
ttl = lease.LeaseMax
|
||||
}
|
||||
resp.Secret.TTL = ttl
|
||||
resp.Secret.TTL = lease.Lease
|
||||
resp.Secret.MaxTTL = lease.LeaseMax
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
@@ -52,8 +52,10 @@ func (b *backend) secretCredsRenew(ctx context.Context, req *logical.Request, d
|
||||
lease = &configLease{}
|
||||
}
|
||||
|
||||
f := framework.LeaseExtend(lease.Lease, lease.LeaseMax, b.System())
|
||||
return f(ctx, req, d)
|
||||
resp := &logical.Response{Secret: req.Secret}
|
||||
resp.Secret.TTL = lease.Lease
|
||||
resp.Secret.MaxTTL = lease.LeaseMax
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (b *backend) secretCredsRevoke(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
||||
|
||||
@@ -202,7 +202,6 @@ func TestBackend_renew_revoke(t *testing.T) {
|
||||
}
|
||||
|
||||
generatedSecret := resp.Secret
|
||||
generatedSecret.IssueTime = time.Now()
|
||||
generatedSecret.TTL = 6 * time.Hour
|
||||
|
||||
var d struct {
|
||||
|
||||
@@ -81,6 +81,7 @@ func (b *backend) pathTokenRead(ctx context.Context, req *logical.Request, d *fr
|
||||
"accessor_id": token.AccessorID,
|
||||
})
|
||||
resp.Secret.TTL = leaseConfig.TTL
|
||||
resp.Secret.MaxTTL = leaseConfig.MaxTTL
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
@@ -36,8 +36,10 @@ func (b *backend) secretTokenRenew(ctx context.Context, req *logical.Request, d
|
||||
if lease == nil {
|
||||
lease = &configLease{}
|
||||
}
|
||||
|
||||
return framework.LeaseExtend(lease.TTL, lease.MaxTTL, b.System())(ctx, req, d)
|
||||
resp := &logical.Response{Secret: req.Secret}
|
||||
resp.Secret.TTL = lease.TTL
|
||||
resp.Secret.MaxTTL = lease.MaxTTL
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (b *backend) secretTokenRevoke(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/vault/helper/strutil"
|
||||
"github.com/hashicorp/vault/logical"
|
||||
@@ -59,14 +60,16 @@ func (b *backend) secretCredsRenew(ctx context.Context, req *logical.Request, d
|
||||
lease = &configLease{}
|
||||
}
|
||||
|
||||
f := framework.LeaseExtend(lease.Lease, lease.LeaseMax, b.System())
|
||||
resp, err := f(ctx, req, d)
|
||||
// Make sure we increase the VALID UNTIL endpoint for this user.
|
||||
ttl, _, err := framework.CalculateTTL(b.System(), req.Secret.Increment, lease.Lease, 0, lease.LeaseMax, 0, req.Secret.IssueTime)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Make sure we increase the VALID UNTIL endpoint for this user.
|
||||
if expireTime := resp.Secret.ExpirationTime(); !expireTime.IsZero() {
|
||||
if ttl > 0 {
|
||||
expireTime := time.Now().Add(ttl)
|
||||
// Adding a small buffer since the TTL will be calculated again afeter this call
|
||||
// to ensure the database credential does not expire before the lease
|
||||
expireTime = expireTime.Add(5 * time.Second)
|
||||
expiration := expireTime.Format("2006-01-02 15:04:05-0700")
|
||||
|
||||
query := fmt.Sprintf(
|
||||
@@ -83,6 +86,9 @@ func (b *backend) secretCredsRenew(ctx context.Context, req *logical.Request, d
|
||||
}
|
||||
}
|
||||
|
||||
resp := &logical.Response{Secret: req.Secret}
|
||||
resp.Secret.TTL = lease.Lease
|
||||
resp.Secret.MaxTTL = lease.LeaseMax
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -105,11 +105,8 @@ func (b *backend) pathCredsRead(ctx context.Context, req *logical.Request, d *fr
|
||||
}
|
||||
|
||||
if lease != nil {
|
||||
ttl := lease.TTL
|
||||
if ttl == 0 || (lease.MaxTTL > 0 && ttl > lease.MaxTTL) {
|
||||
ttl = lease.MaxTTL
|
||||
}
|
||||
resp.Secret.TTL = ttl
|
||||
resp.Secret.TTL = lease.TTL
|
||||
resp.Secret.MaxTTL = lease.MaxTTL
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
|
||||
@@ -40,7 +40,10 @@ func (b *backend) secretCredsRenew(ctx context.Context, req *logical.Request, d
|
||||
lease = &configLease{}
|
||||
}
|
||||
|
||||
return framework.LeaseExtend(lease.TTL, lease.MaxTTL, b.System())(ctx, req, d)
|
||||
resp := &logical.Response{Secret: req.Secret}
|
||||
resp.Secret.TTL = lease.TTL
|
||||
resp.Secret.MaxTTL = lease.MaxTTL
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// Revoke the previously issued secret
|
||||
|
||||
@@ -32,8 +32,7 @@ func secretDynamicKey(b *backend) *framework.Secret {
|
||||
}
|
||||
|
||||
func (b *backend) secretDynamicKeyRenew(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
||||
f := framework.LeaseExtend(0, 0, b.System())
|
||||
return f(ctx, req, d)
|
||||
return &logical.Response{Secret: req.Secret}, nil
|
||||
}
|
||||
|
||||
func (b *backend) secretDynamicKeyRevoke(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
||||
|
||||
@@ -70,7 +70,7 @@ func TestAuthTokenCreate(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if secret.Auth.LeaseDuration != 1800 {
|
||||
t.Errorf("expected 1800 seconds, got %q", secret.Auth.LeaseDuration)
|
||||
t.Errorf("expected 1800 seconds, got %d", secret.Auth.LeaseDuration)
|
||||
}
|
||||
|
||||
explicitMaxCreateRequest.ExplicitMaxTTL = "2h"
|
||||
|
||||
@@ -49,6 +49,10 @@ type Auth struct {
|
||||
// specified by this period.
|
||||
Period time.Duration `json:"period" mapstructure:"period" structs:"period"`
|
||||
|
||||
// ExplicitMaxTTL is the max TTL that constrains periodic tokens. For normal
|
||||
// tokens, this value is constrained by the configured max ttl.
|
||||
ExplicitMaxTTL time.Duration `json:"-" mapstructure:"-" structs:"-"`
|
||||
|
||||
// Number of allowed uses of the issued token
|
||||
NumUses int `json:"num_uses" mapstructure:"num_uses" structs:"num_uses"`
|
||||
|
||||
|
||||
@@ -291,24 +291,6 @@ func (b *Backend) SanitizeTTLStr(ttlStr, maxTTLStr string) (ttl, maxTTL time.Dur
|
||||
}
|
||||
}
|
||||
|
||||
ttl, maxTTL, err = b.SanitizeTTL(ttl, maxTTL)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// SanitizeTTL caps the boundaries of ttl and max_ttl values to the
|
||||
// backend mount's max_ttl value.
|
||||
func (b *Backend) SanitizeTTL(ttl, maxTTL time.Duration) (time.Duration, time.Duration, error) {
|
||||
sysMaxTTL := b.System().MaxLeaseTTL()
|
||||
if ttl > sysMaxTTL {
|
||||
return 0, 0, fmt.Errorf("\"ttl\" value must be less than allowed max lease TTL value '%s'", sysMaxTTL.String())
|
||||
}
|
||||
if maxTTL > sysMaxTTL {
|
||||
return 0, 0, fmt.Errorf("\"max_ttl\" value must be less than allowed max lease TTL value '%s'", sysMaxTTL.String())
|
||||
}
|
||||
if ttl > maxTTL && maxTTL != 0 {
|
||||
ttl = maxTTL
|
||||
}
|
||||
return ttl, maxTTL, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -245,37 +245,6 @@ func TestBackendHandleRequest_renew(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestBackendHandleRequest_renewExtend(t *testing.T) {
|
||||
sysView := logical.StaticSystemView{
|
||||
DefaultLeaseTTLVal: 5 * time.Minute,
|
||||
MaxLeaseTTLVal: 30 * time.Hour,
|
||||
}
|
||||
|
||||
secret := &Secret{
|
||||
Type: "foo",
|
||||
Renew: LeaseExtend(0, 0, sysView),
|
||||
DefaultDuration: 5 * time.Minute,
|
||||
}
|
||||
b := &Backend{
|
||||
Secrets: []*Secret{secret},
|
||||
}
|
||||
|
||||
req := logical.RenewRequest("/foo", secret.Response(nil, nil).Secret, nil)
|
||||
req.Secret.IssueTime = time.Now()
|
||||
req.Secret.Increment = 1 * time.Hour
|
||||
resp, err := b.HandleRequest(context.Background(), req)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
if resp == nil || resp.Secret == nil {
|
||||
t.Fatal("should have secret")
|
||||
}
|
||||
|
||||
if resp.Secret.TTL < 59*time.Minute || resp.Secret.TTL > 61*time.Minute {
|
||||
t.Fatalf("bad: %s", resp.Secret.TTL)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBackendHandleRequest_revoke(t *testing.T) {
|
||||
var called uint32
|
||||
callback := func(context.Context, *logical.Request, *FieldData) (*logical.Response, error) {
|
||||
|
||||
@@ -8,80 +8,99 @@ import (
|
||||
"github.com/hashicorp/vault/logical"
|
||||
)
|
||||
|
||||
// LeaseExtend returns an OperationFunc that can be used to simply extend the
|
||||
// lease of the auth/secret for the duration that was requested. The parameters
|
||||
// provided are used to determine the lease's new TTL value.
|
||||
//
|
||||
// backendIncrement is the backend's requested increment -- perhaps from a user
|
||||
// request, perhaps from a role/config value. If not set, uses the mount/system
|
||||
// value.
|
||||
//
|
||||
// backendMax is the backend's requested increment -- this can be more
|
||||
// restrictive than the mount/system value but not less.
|
||||
//
|
||||
// systemView is the system view from the calling backend, used to determine
|
||||
// and/or correct default/max times.
|
||||
// LeaseExtend is left for backwards compatibility for plugins. This function
|
||||
// now just passes back the data that was passed into it to be processed in core.
|
||||
// DEPRECATED
|
||||
func LeaseExtend(backendIncrement, backendMax time.Duration, systemView logical.SystemView) OperationFunc {
|
||||
return func(ctx context.Context, req *logical.Request, data *FieldData) (*logical.Response, error) {
|
||||
var leaseOpts *logical.LeaseOptions
|
||||
switch {
|
||||
case req.Auth != nil:
|
||||
leaseOpts = &req.Auth.LeaseOptions
|
||||
req.Auth.TTL = backendIncrement
|
||||
req.Auth.MaxTTL = backendMax
|
||||
return &logical.Response{Auth: req.Auth}, nil
|
||||
case req.Secret != nil:
|
||||
leaseOpts = &req.Secret.LeaseOptions
|
||||
default:
|
||||
req.Secret.TTL = backendIncrement
|
||||
req.Secret.MaxTTL = backendMax
|
||||
return &logical.Response{Secret: req.Secret}, nil
|
||||
}
|
||||
return nil, fmt.Errorf("no lease options for request")
|
||||
}
|
||||
}
|
||||
|
||||
// CalculateTTL takes all the user-specified, backend, and system inputs and calculates
|
||||
// a TTL for a lease
|
||||
func CalculateTTL(sysView logical.SystemView, increment, backendTTL, period, backendMaxTTL, explicitMaxTTL time.Duration, startTime time.Time) (ttl time.Duration, warnings []string, errors error) {
|
||||
// Truncate all times to the second since that is the lowest precision for
|
||||
// TTLs
|
||||
now := time.Now().Truncate(time.Second)
|
||||
if startTime.IsZero() {
|
||||
startTime = now
|
||||
} else {
|
||||
startTime = startTime.Truncate(time.Second)
|
||||
}
|
||||
|
||||
// Use the mount's configured max unless the backend specifies
|
||||
// something more restrictive (perhaps from a role configuration
|
||||
// parameter)
|
||||
max := systemView.MaxLeaseTTL()
|
||||
if backendMax > 0 && backendMax < max {
|
||||
max = backendMax
|
||||
maxTTL := sysView.MaxLeaseTTL()
|
||||
if backendMaxTTL > 0 && backendMaxTTL < maxTTL {
|
||||
maxTTL = backendMaxTTL
|
||||
}
|
||||
if explicitMaxTTL > 0 && explicitMaxTTL < maxTTL {
|
||||
maxTTL = explicitMaxTTL
|
||||
}
|
||||
|
||||
// Should never happen, but guard anyways
|
||||
if max < 0 {
|
||||
return nil, fmt.Errorf("max TTL is negative")
|
||||
if maxTTL <= 0 {
|
||||
return 0, nil, fmt.Errorf("max TTL must be greater than zero")
|
||||
}
|
||||
|
||||
var maxValidTime time.Time
|
||||
switch {
|
||||
case period > 0:
|
||||
// Cap the period value to the sys max_ttl value
|
||||
if period > maxTTL {
|
||||
warnings = append(warnings,
|
||||
fmt.Sprintf("period of %q exceeded the effective max_ttl of %q; period value is capped accordingly", period, maxTTL))
|
||||
period = maxTTL
|
||||
}
|
||||
ttl = period
|
||||
|
||||
if explicitMaxTTL > 0 {
|
||||
maxValidTime = startTime.Add(explicitMaxTTL)
|
||||
}
|
||||
default:
|
||||
switch {
|
||||
case increment > 0:
|
||||
ttl = increment
|
||||
case backendTTL > 0:
|
||||
ttl = backendTTL
|
||||
default:
|
||||
ttl = sysView.DefaultLeaseTTL()
|
||||
}
|
||||
|
||||
// We cannot go past this time
|
||||
maxValidTime := leaseOpts.IssueTime.Add(max)
|
||||
maxValidTime = startTime.Add(maxTTL)
|
||||
}
|
||||
|
||||
// Get the current time
|
||||
now := time.Now()
|
||||
if !maxValidTime.IsZero() {
|
||||
// Determine the max valid TTL
|
||||
maxValidTTL := maxValidTime.Sub(now)
|
||||
|
||||
// If we are past the max TTL, we shouldn't be in this function...but
|
||||
// fast path out if we are
|
||||
if maxValidTime.Before(now) {
|
||||
return nil, fmt.Errorf("past the max TTL, cannot renew")
|
||||
if maxValidTTL < 0 {
|
||||
return 0, nil, fmt.Errorf("past the max TTL, cannot renew")
|
||||
}
|
||||
|
||||
// Basic max safety checks have passed, now let's figure out our
|
||||
// increment. We'll use the user-supplied value first, then backend-provided default if possible, or the
|
||||
// mount/system default if not.
|
||||
increment := leaseOpts.Increment
|
||||
if increment <= 0 {
|
||||
if backendIncrement > 0 {
|
||||
increment = backendIncrement
|
||||
} else {
|
||||
increment = systemView.DefaultLeaseTTL()
|
||||
}
|
||||
}
|
||||
|
||||
// We are proposing a time of the current time plus the increment
|
||||
proposedExpiration := now.Add(increment)
|
||||
|
||||
// If the proposed expiration is after the maximum TTL of the lease,
|
||||
// cap the increment to whatever is left
|
||||
if maxValidTime.Before(proposedExpiration) {
|
||||
increment = maxValidTime.Sub(now)
|
||||
if maxValidTTL-ttl < 0 {
|
||||
warnings = append(warnings,
|
||||
fmt.Sprintf("TTL of %q exceeded the effective max_ttl of %q; TTL value is capped accordingly", ttl, maxValidTTL))
|
||||
ttl = maxValidTTL
|
||||
}
|
||||
}
|
||||
|
||||
// Set the lease
|
||||
leaseOpts.TTL = increment
|
||||
|
||||
return &logical.Response{Auth: req.Auth, Secret: req.Secret}, nil
|
||||
}
|
||||
return ttl, warnings, nil
|
||||
}
|
||||
|
||||
@@ -1,27 +1,26 @@
|
||||
package framework
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/vault/logical"
|
||||
)
|
||||
|
||||
func TestLeaseExtend(t *testing.T) {
|
||||
|
||||
func TestCalculateTTL(t *testing.T) {
|
||||
testSysView := logical.StaticSystemView{
|
||||
DefaultLeaseTTLVal: 5 * time.Hour,
|
||||
MaxLeaseTTLVal: 30 * time.Hour,
|
||||
}
|
||||
|
||||
now := time.Now().Round(time.Hour)
|
||||
|
||||
cases := map[string]struct {
|
||||
Increment time.Duration
|
||||
BackendDefault time.Duration
|
||||
BackendMax time.Duration
|
||||
Increment time.Duration
|
||||
Period time.Duration
|
||||
ExplicitMaxTTL time.Duration
|
||||
Result time.Duration
|
||||
Warnings int
|
||||
Error bool
|
||||
}{
|
||||
"valid request, good bounds, increment is preferred": {
|
||||
@@ -52,6 +51,7 @@ func TestLeaseExtend(t *testing.T) {
|
||||
BackendDefault: 40 * time.Hour,
|
||||
BackendMax: 45 * time.Hour,
|
||||
Result: 30 * time.Hour,
|
||||
Warnings: 1,
|
||||
},
|
||||
|
||||
"all request values are larger than the system view, so the system view limits": {
|
||||
@@ -59,6 +59,7 @@ func TestLeaseExtend(t *testing.T) {
|
||||
BackendMax: 50 * time.Hour,
|
||||
Increment: 40 * time.Hour,
|
||||
Result: 30 * time.Hour,
|
||||
Warnings: 1,
|
||||
},
|
||||
|
||||
"request within backend max": {
|
||||
@@ -73,6 +74,7 @@ func TestLeaseExtend(t *testing.T) {
|
||||
BackendMax: 4 * time.Hour,
|
||||
Increment: 5 * time.Hour,
|
||||
Result: 4 * time.Hour,
|
||||
Warnings: 1,
|
||||
},
|
||||
|
||||
"request is negative, no backend default, use sysview": {
|
||||
@@ -83,22 +85,34 @@ func TestLeaseExtend(t *testing.T) {
|
||||
"lease increment too large": {
|
||||
Increment: 40 * time.Hour,
|
||||
Result: 30 * time.Hour,
|
||||
Warnings: 1,
|
||||
},
|
||||
|
||||
"periodic, good request, period is preferred": {
|
||||
Increment: 3 * time.Hour,
|
||||
BackendDefault: 4 * time.Hour,
|
||||
BackendMax: 2 * time.Hour,
|
||||
Period: 1 * time.Hour,
|
||||
Result: 1 * time.Hour,
|
||||
},
|
||||
|
||||
"period too large, explicit max ttl is preferred": {
|
||||
Period: 2 * time.Hour,
|
||||
ExplicitMaxTTL: 1 * time.Hour,
|
||||
Result: 1 * time.Hour,
|
||||
Warnings: 1,
|
||||
},
|
||||
|
||||
"period too large, capped by backend max": {
|
||||
Period: 2 * time.Hour,
|
||||
BackendMax: 1 * time.Hour,
|
||||
Result: 1 * time.Hour,
|
||||
Warnings: 1,
|
||||
},
|
||||
}
|
||||
|
||||
for name, tc := range cases {
|
||||
req := &logical.Request{
|
||||
Auth: &logical.Auth{
|
||||
LeaseOptions: logical.LeaseOptions{
|
||||
TTL: 1 * time.Hour,
|
||||
IssueTime: now,
|
||||
Increment: tc.Increment,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
callback := LeaseExtend(tc.BackendDefault, tc.BackendMax, testSysView)
|
||||
resp, err := callback(context.Background(), req, nil)
|
||||
ttl, warnings, err := CalculateTTL(testSysView, tc.Increment, tc.BackendDefault, tc.Period, tc.BackendMax, tc.ExplicitMaxTTL, time.Time{})
|
||||
if (err != nil) != tc.Error {
|
||||
t.Fatalf("bad: %s\nerr: %s", name, err)
|
||||
}
|
||||
@@ -107,9 +121,14 @@ func TestLeaseExtend(t *testing.T) {
|
||||
}
|
||||
|
||||
// Round it to the nearest hour
|
||||
lease := now.Add(resp.Auth.TTL).Round(time.Hour).Sub(now)
|
||||
now := time.Now().Round(time.Hour)
|
||||
lease := now.Add(ttl).Round(time.Hour).Sub(now)
|
||||
if lease != tc.Result {
|
||||
t.Fatalf("bad: %s\nlease: %s", name, lease)
|
||||
}
|
||||
|
||||
if tc.Warnings != len(warnings) {
|
||||
t.Fatalf("bad: %s\nwarning count mismatch, expect %d, got %d: %#v", name, tc.Warnings, len(warnings), warnings)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,10 +7,13 @@ import (
|
||||
// LeaseOptions is an embeddable struct to capture common lease
|
||||
// settings between a Secret and Auth
|
||||
type LeaseOptions struct {
|
||||
// Lease is the duration that this secret is valid for. Vault
|
||||
// TTL is the duration that this secret is valid for. Vault
|
||||
// will automatically revoke it after the duration.
|
||||
TTL time.Duration `json:"lease"`
|
||||
|
||||
// MaxTTL is the maximum duration that this secret is valid for.
|
||||
MaxTTL time.Duration `json:"max_ttl"`
|
||||
|
||||
// Renewable, if true, means that this secret can be renewed.
|
||||
Renewable bool `json:"renewable"`
|
||||
|
||||
|
||||
@@ -581,6 +581,7 @@ type LeaseOptions struct {
|
||||
Renewable bool `sentinel:"" protobuf:"varint,2,opt,name=renewable" json:"renewable,omitempty"`
|
||||
Increment int64 `sentinel:"" protobuf:"varint,3,opt,name=increment" json:"increment,omitempty"`
|
||||
IssueTime *google_protobuf.Timestamp `sentinel:"" protobuf:"bytes,4,opt,name=issue_time,json=issueTime" json:"issue_time,omitempty"`
|
||||
MaxTTL int64 `sentinel:"" protobuf:"varint,5,opt,name=MaxTTL" json:"MaxTTL,omitempty"`
|
||||
}
|
||||
|
||||
func (m *LeaseOptions) Reset() { *m = LeaseOptions{} }
|
||||
@@ -616,6 +617,13 @@ func (m *LeaseOptions) GetIssueTime() *google_protobuf.Timestamp {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *LeaseOptions) GetMaxTTL() int64 {
|
||||
if m != nil {
|
||||
return m.MaxTTL
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type Secret struct {
|
||||
LeaseOptions *LeaseOptions `sentinel:"" protobuf:"bytes,1,opt,name=lease_options,json=leaseOptions" json:"lease_options,omitempty"`
|
||||
// InternalData is a JSON object that is stored with the secret.
|
||||
@@ -2353,137 +2361,137 @@ var _SystemView_serviceDesc = grpc.ServiceDesc{
|
||||
func init() { proto.RegisterFile("logical/plugin/pb/backend.proto", fileDescriptor0) }
|
||||
|
||||
var fileDescriptor0 = []byte{
|
||||
// 2101 bytes of a gzipped FileDescriptorProto
|
||||
// 2112 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x58, 0x5b, 0x6f, 0xdb, 0xc8,
|
||||
0x15, 0x86, 0x24, 0x4b, 0xa2, 0x8e, 0x24, 0x5f, 0x26, 0x4e, 0xca, 0x28, 0xd9, 0x5a, 0xe5, 0x22,
|
||||
0x59, 0x6d, 0xd0, 0xc8, 0x89, 0x7a, 0xcb, 0xb6, 0xd8, 0x2d, 0x5c, 0xdb, 0x9b, 0x75, 0xd7, 0xde,
|
||||
0x35, 0x68, 0xa7, 0xdb, 0xa2, 0x05, 0xb4, 0x63, 0xf2, 0x58, 0x26, 0x4c, 0x91, 0xec, 0x70, 0x68,
|
||||
0x47, 0x4f, 0xfd, 0x17, 0xed, 0x5f, 0xe9, 0x5b, 0x5f, 0x0b, 0xf4, 0xb9, 0xbf, 0xa0, 0xef, 0x7d,
|
||||
0xe8, 0x2f, 0x28, 0xe6, 0x42, 0x6a, 0x28, 0xc9, 0x4d, 0x0a, 0xb4, 0x6f, 0x73, 0x2e, 0x33, 0xe7,
|
||||
0xc2, 0x73, 0xbe, 0x33, 0x43, 0xd8, 0x09, 0xe3, 0x49, 0xe0, 0xd1, 0x70, 0x37, 0x09, 0xb3, 0x49,
|
||||
0x10, 0xed, 0x26, 0x17, 0xbb, 0x17, 0xd4, 0xbb, 0xc6, 0xc8, 0x1f, 0x26, 0x2c, 0xe6, 0x31, 0xa9,
|
||||
0x26, 0x17, 0xbd, 0x9d, 0x49, 0x1c, 0x4f, 0x42, 0xdc, 0x95, 0x9c, 0x8b, 0xec, 0x72, 0x97, 0x07,
|
||||
0x53, 0x4c, 0x39, 0x9d, 0x26, 0x4a, 0xc9, 0x69, 0x42, 0xfd, 0x70, 0x9a, 0xf0, 0x99, 0xd3, 0x87,
|
||||
0xc6, 0x17, 0x48, 0x7d, 0x64, 0xe4, 0x01, 0x34, 0xae, 0xe4, 0xca, 0xae, 0xf4, 0x6b, 0x83, 0x96,
|
||||
0xab, 0x29, 0xe7, 0xb7, 0x00, 0xa7, 0x62, 0xcf, 0x21, 0x63, 0x31, 0x23, 0x0f, 0xc1, 0x42, 0xc6,
|
||||
0xc6, 0x7c, 0x96, 0xa0, 0x5d, 0xe9, 0x57, 0x06, 0x5d, 0xb7, 0x89, 0x8c, 0x9d, 0xcf, 0x12, 0x24,
|
||||
0xdf, 0x01, 0xb1, 0x1c, 0x4f, 0xd3, 0x89, 0x5d, 0xed, 0x57, 0xc4, 0x09, 0xc8, 0xd8, 0x49, 0x3a,
|
||||
0xc9, 0xf7, 0x78, 0xb1, 0x8f, 0x76, 0xad, 0x5f, 0x19, 0xd4, 0xe4, 0x9e, 0xfd, 0xd8, 0x47, 0xe7,
|
||||
0x8f, 0x15, 0xa8, 0x9f, 0x52, 0x7e, 0x95, 0x12, 0x02, 0x6b, 0x2c, 0x8e, 0xb9, 0x36, 0x2e, 0xd7,
|
||||
0x64, 0x00, 0x1b, 0x59, 0x44, 0x33, 0x7e, 0x85, 0x11, 0x0f, 0x3c, 0xca, 0xd1, 0xb7, 0xab, 0x52,
|
||||
0xbc, 0xc8, 0x26, 0x1f, 0x42, 0x37, 0x8c, 0x3d, 0x1a, 0x8e, 0x53, 0x1e, 0x33, 0x3a, 0x11, 0x76,
|
||||
0x84, 0x5e, 0x47, 0x32, 0xcf, 0x14, 0x8f, 0x3c, 0x83, 0xad, 0x14, 0x69, 0x38, 0xbe, 0x65, 0x34,
|
||||
0x29, 0x14, 0xd7, 0xd4, 0x81, 0x42, 0xf0, 0x0d, 0xa3, 0x89, 0xd6, 0x75, 0xfe, 0xd2, 0x80, 0xa6,
|
||||
0x8b, 0xbf, 0xcf, 0x30, 0xe5, 0x64, 0x1d, 0xaa, 0x81, 0x2f, 0xa3, 0x6d, 0xb9, 0xd5, 0xc0, 0x27,
|
||||
0x43, 0x20, 0x2e, 0x26, 0xa1, 0x30, 0x1d, 0xc4, 0xd1, 0x7e, 0x98, 0xa5, 0x1c, 0x99, 0x8e, 0x79,
|
||||
0x85, 0x84, 0x3c, 0x86, 0x56, 0x9c, 0x20, 0x93, 0x3c, 0x99, 0x80, 0x96, 0x3b, 0x67, 0x88, 0xc0,
|
||||
0x13, 0xca, 0xaf, 0xec, 0x35, 0x29, 0x90, 0x6b, 0xc1, 0xf3, 0x29, 0xa7, 0x76, 0x5d, 0xf1, 0xc4,
|
||||
0x9a, 0x38, 0xd0, 0x48, 0xd1, 0x63, 0xc8, 0xed, 0x46, 0xbf, 0x32, 0x68, 0x8f, 0x60, 0x98, 0x5c,
|
||||
0x0c, 0xcf, 0x24, 0xc7, 0xd5, 0x12, 0xf2, 0x18, 0xd6, 0x44, 0x5e, 0xec, 0xa6, 0xd4, 0xb0, 0x84,
|
||||
0xc6, 0x5e, 0xc6, 0xaf, 0x5c, 0xc9, 0x25, 0x23, 0x68, 0xaa, 0x6f, 0x9a, 0xda, 0x56, 0xbf, 0x36,
|
||||
0x68, 0x8f, 0x6c, 0xa1, 0xa0, 0xa3, 0x1c, 0xaa, 0x32, 0x48, 0x0f, 0x23, 0xce, 0x66, 0x6e, 0xae,
|
||||
0x48, 0xbe, 0x07, 0x1d, 0x2f, 0x0c, 0x30, 0xe2, 0x63, 0x1e, 0x5f, 0x63, 0x64, 0xb7, 0xa4, 0x47,
|
||||
0x6d, 0xc5, 0x3b, 0x17, 0x2c, 0x32, 0x82, 0xfb, 0xa6, 0xca, 0x98, 0x7a, 0x1e, 0xa6, 0x69, 0xcc,
|
||||
0x6c, 0x90, 0xba, 0xf7, 0x0c, 0xdd, 0x3d, 0x2d, 0x12, 0xc7, 0xfa, 0x41, 0x9a, 0x84, 0x74, 0x36,
|
||||
0x8e, 0xe8, 0x14, 0xed, 0xb6, 0x3a, 0x56, 0xf3, 0xbe, 0xa2, 0x53, 0x24, 0x3b, 0xd0, 0x9e, 0xc6,
|
||||
0x59, 0xc4, 0xc7, 0x49, 0x1c, 0x44, 0xdc, 0xee, 0x48, 0x0d, 0x90, 0xac, 0x53, 0xc1, 0x21, 0x1f,
|
||||
0x80, 0xa2, 0x54, 0x31, 0x76, 0x55, 0x5e, 0x25, 0x47, 0x96, 0xe3, 0x13, 0x58, 0x57, 0xe2, 0xc2,
|
||||
0x9f, 0x75, 0xa9, 0xd2, 0x95, 0xdc, 0xc2, 0x93, 0x17, 0xd0, 0x92, 0xf5, 0x10, 0x44, 0x97, 0xb1,
|
||||
0xbd, 0x21, 0xf3, 0x76, 0xcf, 0x48, 0x8b, 0xa8, 0x89, 0xa3, 0xe8, 0x32, 0x76, 0xad, 0x5b, 0xbd,
|
||||
0x22, 0x9f, 0xc2, 0xa3, 0x52, 0xbc, 0x0c, 0xa7, 0x34, 0x88, 0x82, 0x68, 0x32, 0xce, 0x52, 0x4c,
|
||||
0xed, 0x4d, 0x59, 0xe1, 0xb6, 0x11, 0xb5, 0x9b, 0x2b, 0xbc, 0x49, 0x31, 0x25, 0x8f, 0xa0, 0x25,
|
||||
0xea, 0x96, 0xcf, 0xc6, 0x81, 0x6f, 0x6f, 0x49, 0x97, 0x2c, 0xc5, 0x38, 0xf2, 0xc9, 0x47, 0xb0,
|
||||
0x91, 0xc4, 0x61, 0xe0, 0xcd, 0xc6, 0xf1, 0x0d, 0x32, 0x16, 0xf8, 0x68, 0x93, 0x7e, 0x65, 0x60,
|
||||
0xb9, 0xeb, 0x8a, 0xfd, 0xb5, 0xe6, 0xae, 0x6a, 0x8d, 0x7b, 0x52, 0x71, 0xa9, 0x35, 0x86, 0x00,
|
||||
0x5e, 0x1c, 0x45, 0xe8, 0xc9, 0xf2, 0xdb, 0x96, 0x11, 0xae, 0x8b, 0x08, 0xf7, 0x0b, 0xae, 0x6b,
|
||||
0x68, 0xf4, 0x3e, 0x87, 0x8e, 0x59, 0x0a, 0x64, 0x13, 0x6a, 0xd7, 0x38, 0xd3, 0xe5, 0x2f, 0x96,
|
||||
0xa4, 0x0f, 0xf5, 0x1b, 0x1a, 0x66, 0x28, 0x4b, 0x5e, 0x17, 0xa2, 0xda, 0xe2, 0x2a, 0xc1, 0x4f,
|
||||
0xab, 0xaf, 0x2a, 0x0e, 0x85, 0xfa, 0x5e, 0x18, 0xd0, 0x74, 0xe1, 0x3b, 0x55, 0xde, 0xfd, 0x9d,
|
||||
0xaa, 0xab, 0xbe, 0x13, 0x81, 0x35, 0x59, 0x29, 0xaa, 0x7f, 0xe4, 0xda, 0xf9, 0x57, 0x0d, 0xd6,
|
||||
0x44, 0x7d, 0x93, 0x1f, 0x41, 0x37, 0x44, 0x9a, 0xe2, 0x38, 0x4e, 0x44, 0x0c, 0xa9, 0xb4, 0xd2,
|
||||
0x1e, 0x6d, 0x0a, 0xcf, 0x8e, 0x85, 0xe0, 0x6b, 0xc5, 0x77, 0x3b, 0xa1, 0x41, 0x09, 0xd4, 0x08,
|
||||
0x22, 0x8e, 0x2c, 0xa2, 0xe1, 0x58, 0xf6, 0x9b, 0xb2, 0xdc, 0xc9, 0x99, 0x07, 0xa2, 0xef, 0x16,
|
||||
0x4b, 0xb5, 0xb6, 0x5c, 0xaa, 0x3d, 0xb0, 0xe4, 0xe7, 0x09, 0x30, 0xd5, 0x78, 0x52, 0xd0, 0x64,
|
||||
0x04, 0xd6, 0x14, 0x39, 0xd5, 0xed, 0x2c, 0xba, 0xee, 0x41, 0xde, 0x96, 0xc3, 0x13, 0x2d, 0x50,
|
||||
0x3d, 0x57, 0xe8, 0x2d, 0x35, 0x5d, 0x63, 0xb9, 0xe9, 0x7a, 0x60, 0x15, 0xf9, 0x6a, 0xaa, 0x22,
|
||||
0xca, 0x69, 0x81, 0xe4, 0x09, 0xb2, 0x20, 0xf6, 0x6d, 0x4b, 0xd6, 0xa2, 0xa6, 0x04, 0x0e, 0x47,
|
||||
0xd9, 0x54, 0x55, 0x69, 0x4b, 0xe1, 0x70, 0x94, 0x4d, 0x97, 0x8b, 0x12, 0x16, 0x8a, 0x72, 0x07,
|
||||
0xea, 0x54, 0x7c, 0x49, 0xd9, 0xa5, 0xed, 0x51, 0x4b, 0xfa, 0x2f, 0x18, 0xae, 0xe2, 0x93, 0x21,
|
||||
0x74, 0x27, 0x2c, 0xce, 0x92, 0xb1, 0x24, 0x31, 0xb5, 0x3b, 0x32, 0x50, 0x43, 0xb1, 0x23, 0xe5,
|
||||
0x7b, 0x4a, 0xdc, 0xfb, 0x19, 0x74, 0x4b, 0xa1, 0xaf, 0xa8, 0xb1, 0x6d, 0xb3, 0xc6, 0x5a, 0x66,
|
||||
0x5d, 0xfd, 0xa9, 0x02, 0x1d, 0xf3, 0x9b, 0x8a, 0xcd, 0xe7, 0xe7, 0xc7, 0x72, 0x73, 0xcd, 0x15,
|
||||
0x4b, 0x01, 0xb8, 0x0c, 0x23, 0xbc, 0xa5, 0x17, 0xa1, 0x3a, 0xc0, 0x72, 0xe7, 0x0c, 0x21, 0x0d,
|
||||
0x22, 0x8f, 0xe1, 0x14, 0x23, 0xae, 0xe7, 0xd1, 0x9c, 0x41, 0x3e, 0x01, 0x08, 0xd2, 0x34, 0xc3,
|
||||
0xb1, 0x18, 0x99, 0x12, 0x94, 0xdb, 0xa3, 0xde, 0x50, 0xcd, 0xd3, 0x61, 0x3e, 0x4f, 0x87, 0xe7,
|
||||
0xf9, 0x3c, 0x75, 0x5b, 0x52, 0x5b, 0xd0, 0xce, 0x1f, 0xa0, 0xa1, 0xf0, 0xf8, 0xff, 0x5a, 0x8f,
|
||||
0x0f, 0xc1, 0x52, 0x67, 0x07, 0xbe, 0xae, 0xc5, 0xa6, 0xa4, 0x8f, 0x7c, 0xe7, 0x6f, 0x15, 0xb0,
|
||||
0x5c, 0x4c, 0x93, 0x38, 0x4a, 0xd1, 0x98, 0x17, 0x95, 0x77, 0xce, 0x8b, 0xea, 0xca, 0x79, 0x91,
|
||||
0x4f, 0xa1, 0x9a, 0x31, 0x85, 0x7a, 0x60, 0x31, 0xf4, 0x03, 0x86, 0x1e, 0xd7, 0x13, 0xab, 0xa0,
|
||||
0x85, 0xec, 0x96, 0x32, 0x01, 0x74, 0xa9, 0x2c, 0xf5, 0x96, 0x5b, 0xd0, 0xe4, 0xa5, 0x09, 0xb3,
|
||||
0x6a, 0x80, 0x6d, 0x2b, 0x98, 0x55, 0xee, 0x2e, 0xe3, 0xac, 0xf3, 0xd7, 0x2a, 0x6c, 0x2e, 0x8a,
|
||||
0x57, 0x7c, 0xec, 0x6d, 0xa8, 0xab, 0x2e, 0xd1, 0x95, 0xc2, 0x97, 0xfa, 0xa3, 0xb6, 0xd0, 0x1f,
|
||||
0x3f, 0x87, 0xae, 0xc7, 0x50, 0x4e, 0xdf, 0xf7, 0xfd, 0xca, 0x9d, 0x7c, 0x83, 0x60, 0x91, 0x8f,
|
||||
0x61, 0x53, 0x78, 0x99, 0xa0, 0x3f, 0x07, 0x2d, 0x35, 0xaa, 0x37, 0x34, 0xbf, 0x80, 0xad, 0x67,
|
||||
0xb0, 0x95, 0xab, 0xce, 0x1b, 0xac, 0x51, 0xd2, 0x3d, 0xcc, 0xfb, 0xec, 0x01, 0x34, 0x2e, 0x63,
|
||||
0x36, 0xa5, 0x5c, 0x77, 0xb4, 0xa6, 0x44, 0x59, 0x14, 0xfe, 0xca, 0xab, 0x82, 0xa5, 0xca, 0x22,
|
||||
0x67, 0x8a, 0x0b, 0x94, 0xe8, 0xe0, 0xe2, 0x72, 0x23, 0xbb, 0xdb, 0x72, 0xad, 0xfc, 0x52, 0xe3,
|
||||
0xfc, 0x1a, 0x36, 0x16, 0xe6, 0xd9, 0x8a, 0x44, 0xce, 0xcd, 0x57, 0x4b, 0xe6, 0x4b, 0x27, 0xd7,
|
||||
0x16, 0x4e, 0xfe, 0x0d, 0x6c, 0x7d, 0x41, 0x23, 0x3f, 0x44, 0x7d, 0xfe, 0x1e, 0x9b, 0x48, 0xc4,
|
||||
0xd7, 0xd7, 0xab, 0xb1, 0xbe, 0x38, 0x75, 0xdd, 0x96, 0xe6, 0x1c, 0xf9, 0xe4, 0x09, 0x34, 0x99,
|
||||
0xd2, 0xd6, 0x85, 0xd7, 0x36, 0x06, 0xae, 0x9b, 0xcb, 0x9c, 0x6f, 0x81, 0x94, 0x8e, 0x16, 0x37,
|
||||
0xab, 0x19, 0x19, 0x88, 0x02, 0x54, 0x45, 0xa1, 0x0b, 0xbb, 0x63, 0xd6, 0x91, 0x5b, 0x48, 0x49,
|
||||
0x1f, 0x6a, 0xc8, 0x98, 0x36, 0x21, 0x27, 0xde, 0xfc, 0x1e, 0xeb, 0x0a, 0x91, 0xf3, 0x43, 0xd8,
|
||||
0x3a, 0x4b, 0xd0, 0x0b, 0x68, 0x28, 0xef, 0xa0, 0xca, 0xc0, 0x0e, 0xd4, 0x45, 0x92, 0xf3, 0x9e,
|
||||
0x95, 0x20, 0xa6, 0xc4, 0x8a, 0xef, 0x7c, 0x0b, 0xb6, 0xf2, 0xeb, 0xf0, 0x6d, 0x90, 0x72, 0x8c,
|
||||
0x3c, 0xdc, 0xbf, 0x42, 0xef, 0xfa, 0x7f, 0x18, 0xf9, 0x0d, 0x3c, 0x5c, 0x65, 0x21, 0xf7, 0xaf,
|
||||
0xed, 0x09, 0x6a, 0x7c, 0x19, 0x67, 0x91, 0xb2, 0x61, 0xb9, 0x20, 0x59, 0x9f, 0x0b, 0x8e, 0xf8,
|
||||
0x8e, 0x28, 0xf6, 0xa5, 0x1a, 0xfa, 0x34, 0x95, 0xe7, 0xa3, 0x76, 0x77, 0x3e, 0xfe, 0x5c, 0x81,
|
||||
0xd6, 0x19, 0xf2, 0x2c, 0x91, 0xb1, 0x3c, 0x82, 0xd6, 0x05, 0x8b, 0xaf, 0x91, 0xcd, 0x43, 0xb1,
|
||||
0x14, 0xe3, 0xc8, 0x27, 0x2f, 0xa1, 0xb1, 0x1f, 0x47, 0x97, 0xc1, 0x44, 0xde, 0xc8, 0xdb, 0xa3,
|
||||
0x87, 0x0a, 0x5d, 0xf4, 0xde, 0xa1, 0x92, 0xa9, 0xb9, 0xa6, 0x15, 0x49, 0x1f, 0xda, 0xfa, 0xa5,
|
||||
0xf2, 0xe6, 0xcd, 0xd1, 0x41, 0x3e, 0x47, 0x0d, 0x56, 0xef, 0x13, 0x68, 0x1b, 0x1b, 0xff, 0xab,
|
||||
0xa9, 0xf0, 0x5d, 0x00, 0x69, 0x5d, 0xe5, 0x68, 0x53, 0x85, 0xaa, 0x77, 0x8a, 0xd0, 0x76, 0xa0,
|
||||
0x25, 0x6e, 0x1b, 0x4a, 0x4c, 0x60, 0xcd, 0x78, 0xc0, 0xc8, 0xb5, 0xf3, 0x04, 0xb6, 0x8e, 0xa2,
|
||||
0x1b, 0x1a, 0x06, 0x3e, 0xe5, 0xf8, 0x25, 0xce, 0x64, 0x0a, 0x96, 0x3c, 0x70, 0xce, 0xa0, 0xa3,
|
||||
0x9f, 0x08, 0xef, 0xe5, 0x63, 0x47, 0xfb, 0xf8, 0x9f, 0x9b, 0xe8, 0x63, 0xd8, 0xd0, 0x87, 0x1e,
|
||||
0x07, 0xba, 0x85, 0xc4, 0x0c, 0x67, 0x78, 0x19, 0xbc, 0xd5, 0x47, 0x6b, 0xca, 0x79, 0x05, 0x9b,
|
||||
0x86, 0x6a, 0x11, 0xce, 0x35, 0xce, 0xd2, 0xfc, 0xe9, 0x24, 0xd6, 0x79, 0x06, 0xaa, 0xf3, 0x0c,
|
||||
0x38, 0xb0, 0xae, 0x77, 0xbe, 0x46, 0x7e, 0x47, 0x74, 0x5f, 0x16, 0x8e, 0xbc, 0x46, 0x7d, 0xf8,
|
||||
0x53, 0xa8, 0xa3, 0x88, 0xd4, 0x1c, 0x61, 0x66, 0x06, 0x5c, 0x25, 0x5e, 0x61, 0xf0, 0x55, 0x61,
|
||||
0xf0, 0x34, 0x53, 0x06, 0xdf, 0xf3, 0x2c, 0xe7, 0xc3, 0xc2, 0x8d, 0xd3, 0x8c, 0xdf, 0xf5, 0x45,
|
||||
0x9f, 0xc0, 0x96, 0x56, 0x3a, 0xc0, 0x10, 0x39, 0xde, 0x11, 0xd2, 0x53, 0x20, 0x25, 0xb5, 0xbb,
|
||||
0x8e, 0x7b, 0x0c, 0xd6, 0xf9, 0xf9, 0x71, 0x21, 0x2d, 0x63, 0xa3, 0xf3, 0x29, 0x6c, 0x9d, 0x65,
|
||||
0x7e, 0x7c, 0xca, 0x82, 0x9b, 0x20, 0xc4, 0x89, 0x32, 0x96, 0xbf, 0xdc, 0x2a, 0xc6, 0xcb, 0x6d,
|
||||
0xe5, 0x34, 0x72, 0x06, 0x40, 0x4a, 0xdb, 0x8b, 0xef, 0x96, 0x66, 0x7e, 0xac, 0x5b, 0x58, 0xae,
|
||||
0x9d, 0x01, 0x74, 0xce, 0xa9, 0x98, 0xf7, 0xbe, 0xd2, 0xb1, 0xa1, 0xc9, 0x15, 0xad, 0xd5, 0x72,
|
||||
0xd2, 0x19, 0xc1, 0xf6, 0x3e, 0xf5, 0xae, 0x82, 0x68, 0x72, 0x10, 0xa4, 0xe2, 0x62, 0xa3, 0x77,
|
||||
0xf4, 0xc0, 0xf2, 0x35, 0x43, 0x6f, 0x29, 0x68, 0xe7, 0x39, 0xdc, 0x37, 0xde, 0xa7, 0x67, 0x9c,
|
||||
0xe6, 0xf9, 0xd8, 0x86, 0x7a, 0x2a, 0x28, 0xb9, 0xa3, 0xee, 0x2a, 0xc2, 0xf9, 0x0a, 0xb6, 0xcd,
|
||||
0x01, 0x2c, 0xae, 0x1f, 0x79, 0xe0, 0xf2, 0x62, 0x50, 0x31, 0x2e, 0x06, 0x3a, 0x67, 0xd5, 0xf9,
|
||||
0x3c, 0xd9, 0x84, 0xda, 0x2f, 0xbf, 0x39, 0xd7, 0xc5, 0x2e, 0x96, 0xce, 0xef, 0x84, 0xf9, 0xf2,
|
||||
0x79, 0xca, 0x7c, 0xe9, 0x76, 0x50, 0x79, 0x9f, 0xdb, 0xc1, 0x8a, 0x7a, 0x7b, 0x0e, 0x5b, 0x27,
|
||||
0x61, 0xec, 0x5d, 0x1f, 0x46, 0x46, 0x36, 0x6c, 0x68, 0x62, 0x64, 0x26, 0x23, 0x27, 0x9d, 0x8f,
|
||||
0x60, 0xe3, 0x38, 0xf6, 0x68, 0x78, 0x22, 0x9e, 0x19, 0x45, 0x16, 0xe4, 0x0f, 0x03, 0xad, 0xaa,
|
||||
0x08, 0xe7, 0x39, 0xc0, 0xfc, 0xa9, 0x24, 0xe0, 0x97, 0xe1, 0x34, 0xe6, 0x38, 0xa6, 0xbe, 0x9f,
|
||||
0x57, 0x10, 0x28, 0xd6, 0x9e, 0xef, 0xb3, 0xd1, 0x3f, 0xab, 0xd0, 0xfc, 0x85, 0x02, 0x35, 0xf2,
|
||||
0x19, 0x74, 0x4b, 0x23, 0x8c, 0xdc, 0x97, 0x6f, 0xa5, 0xc5, 0x81, 0xd9, 0x7b, 0xb0, 0xc4, 0x56,
|
||||
0x0e, 0xbd, 0x80, 0x8e, 0x39, 0xa0, 0x88, 0x1c, 0x46, 0xf2, 0xc7, 0x4d, 0x4f, 0x9e, 0xb4, 0x3c,
|
||||
0xbd, 0xce, 0x60, 0x7b, 0xd5, 0xe8, 0x20, 0x8f, 0xe7, 0x16, 0x96, 0xc7, 0x56, 0xef, 0x83, 0xbb,
|
||||
0xa4, 0xf9, 0xc8, 0x69, 0xee, 0x87, 0x48, 0xa3, 0x2c, 0x31, 0x3d, 0x98, 0x2f, 0xc9, 0x4b, 0xe8,
|
||||
0x96, 0xc0, 0x53, 0xc5, 0xb9, 0x84, 0xa7, 0xe6, 0x96, 0xa7, 0x50, 0x97, 0x80, 0x4d, 0xba, 0xa5,
|
||||
0xc9, 0xd1, 0x5b, 0x2f, 0x48, 0x65, 0xbb, 0x0f, 0x6b, 0xf2, 0x99, 0x68, 0x18, 0x96, 0x3b, 0x0a,
|
||||
0x34, 0x1f, 0xfd, 0xbd, 0x02, 0xcd, 0xfc, 0x17, 0xcf, 0x4b, 0x58, 0x13, 0xb8, 0x48, 0xee, 0x19,
|
||||
0xd0, 0x92, 0x63, 0x6a, 0x6f, 0x7b, 0x81, 0xa9, 0x0c, 0x0c, 0xa1, 0xf6, 0x1a, 0x39, 0x21, 0x86,
|
||||
0x50, 0x03, 0x64, 0xef, 0x5e, 0x99, 0x57, 0xe8, 0x9f, 0x66, 0x65, 0x7d, 0x8d, 0x6f, 0x25, 0xfd,
|
||||
0x02, 0xb9, 0x7e, 0x02, 0x0d, 0x85, 0x3c, 0x2a, 0x29, 0x4b, 0x98, 0xa5, 0x3e, 0xfe, 0x32, 0x46,
|
||||
0x8d, 0xfe, 0x51, 0x03, 0x38, 0x9b, 0xa5, 0x1c, 0xa7, 0xbf, 0x0a, 0xf0, 0x96, 0x3c, 0x83, 0x8d,
|
||||
0x03, 0xbc, 0xa4, 0x59, 0xc8, 0xe5, 0x0b, 0x42, 0x74, 0x98, 0x91, 0x13, 0x79, 0x09, 0x2a, 0x00,
|
||||
0xec, 0x29, 0xb4, 0x4f, 0xe8, 0xdb, 0x77, 0xeb, 0x7d, 0x06, 0xdd, 0x12, 0x2e, 0x69, 0x17, 0x17,
|
||||
0x91, 0x4e, 0xbb, 0xb8, 0x8c, 0x60, 0x4f, 0xa1, 0xa9, 0xd1, 0xca, 0xb4, 0x21, 0x71, 0xbd, 0x84,
|
||||
0x62, 0x3f, 0x86, 0x8d, 0x05, 0xac, 0x32, 0xf5, 0xe5, 0x6f, 0xa8, 0x95, 0x58, 0xf6, 0x4a, 0xbc,
|
||||
0x00, 0xca, 0x78, 0x65, 0x6e, 0x7c, 0xa8, 0x30, 0x62, 0x15, 0xa0, 0xbd, 0x2e, 0xbf, 0x1d, 0xe4,
|
||||
0xcb, 0xc9, 0x5e, 0x84, 0x94, 0x1c, 0xd0, 0xf2, 0x83, 0x56, 0x41, 0xd3, 0x0b, 0xe8, 0x98, 0xa8,
|
||||
0xb2, 0xd4, 0x82, 0xcb, 0x90, 0xf3, 0x7d, 0x80, 0x39, 0xb0, 0x98, 0xfa, 0xb2, 0x3c, 0x16, 0x30,
|
||||
0xe7, 0xa2, 0x21, 0x5f, 0x1b, 0x3f, 0xf8, 0x77, 0x00, 0x00, 0x00, 0xff, 0xff, 0x4e, 0x53, 0x71,
|
||||
0xaf, 0xd8, 0x15, 0x00, 0x00,
|
||||
0x47, 0x4f, 0xfd, 0x17, 0xfd, 0x1b, 0x7d, 0xed, 0x5b, 0x5f, 0x0b, 0xf4, 0xb9, 0xbf, 0xa0, 0xef,
|
||||
0x7d, 0xe8, 0x2f, 0x28, 0xe6, 0x42, 0x6a, 0x28, 0xc9, 0x4d, 0x0a, 0xb4, 0x6f, 0x73, 0x2e, 0x33,
|
||||
0xe7, 0xc2, 0x73, 0xbe, 0x33, 0x43, 0xd8, 0x09, 0xe3, 0x49, 0xe0, 0xd1, 0x70, 0x37, 0x09, 0xb3,
|
||||
0x49, 0x10, 0xed, 0x26, 0x17, 0xbb, 0x17, 0xd4, 0xbb, 0xc6, 0xc8, 0x1f, 0x26, 0x2c, 0xe6, 0x31,
|
||||
0xa9, 0x26, 0x17, 0xbd, 0x9d, 0x49, 0x1c, 0x4f, 0x42, 0xdc, 0x95, 0x9c, 0x8b, 0xec, 0x72, 0x97,
|
||||
0x07, 0x53, 0x4c, 0x39, 0x9d, 0x26, 0x4a, 0xc9, 0x69, 0x42, 0xfd, 0x70, 0x9a, 0xf0, 0x99, 0xd3,
|
||||
0x87, 0xc6, 0x17, 0x48, 0x7d, 0x64, 0xe4, 0x01, 0x34, 0xae, 0xe4, 0xca, 0xae, 0xf4, 0x6b, 0x83,
|
||||
0x96, 0xab, 0x29, 0xe7, 0xb7, 0x00, 0xa7, 0x62, 0xcf, 0x21, 0x63, 0x31, 0x23, 0x0f, 0xc1, 0x42,
|
||||
0xc6, 0xc6, 0x7c, 0x96, 0xa0, 0x5d, 0xe9, 0x57, 0x06, 0x5d, 0xb7, 0x89, 0x8c, 0x9d, 0xcf, 0x12,
|
||||
0x24, 0xdf, 0x01, 0xb1, 0x1c, 0x4f, 0xd3, 0x89, 0x5d, 0xed, 0x57, 0xc4, 0x09, 0xc8, 0xd8, 0x49,
|
||||
0x3a, 0xc9, 0xf7, 0x78, 0xb1, 0x8f, 0x76, 0xad, 0x5f, 0x19, 0xd4, 0xe4, 0x9e, 0xfd, 0xd8, 0x47,
|
||||
0xe7, 0x8f, 0x15, 0xa8, 0x9f, 0x52, 0x7e, 0x95, 0x12, 0x02, 0x6b, 0x2c, 0x8e, 0xb9, 0x36, 0x2e,
|
||||
0xd7, 0x64, 0x00, 0x1b, 0x59, 0x44, 0x33, 0x7e, 0x85, 0x11, 0x0f, 0x3c, 0xca, 0xd1, 0xb7, 0xab,
|
||||
0x52, 0xbc, 0xc8, 0x26, 0x1f, 0x42, 0x37, 0x8c, 0x3d, 0x1a, 0x8e, 0x53, 0x1e, 0x33, 0x3a, 0x11,
|
||||
0x76, 0x84, 0x5e, 0x47, 0x32, 0xcf, 0x14, 0x8f, 0x3c, 0x83, 0xad, 0x14, 0x69, 0x38, 0xbe, 0x65,
|
||||
0x34, 0x29, 0x14, 0xd7, 0xd4, 0x81, 0x42, 0xf0, 0x0d, 0xa3, 0x89, 0xd6, 0x75, 0xfe, 0xd2, 0x80,
|
||||
0xa6, 0x8b, 0xbf, 0xcf, 0x30, 0xe5, 0x64, 0x1d, 0xaa, 0x81, 0x2f, 0xa3, 0x6d, 0xb9, 0xd5, 0xc0,
|
||||
0x27, 0x43, 0x20, 0x2e, 0x26, 0xa1, 0x30, 0x1d, 0xc4, 0xd1, 0x7e, 0x98, 0xa5, 0x1c, 0x99, 0x8e,
|
||||
0x79, 0x85, 0x84, 0x3c, 0x86, 0x56, 0x9c, 0x20, 0x93, 0x3c, 0x99, 0x80, 0x96, 0x3b, 0x67, 0x88,
|
||||
0xc0, 0x13, 0xca, 0xaf, 0xec, 0x35, 0x29, 0x90, 0x6b, 0xc1, 0xf3, 0x29, 0xa7, 0x76, 0x5d, 0xf1,
|
||||
0xc4, 0x9a, 0x38, 0xd0, 0x48, 0xd1, 0x63, 0xc8, 0xed, 0x46, 0xbf, 0x32, 0x68, 0x8f, 0x60, 0x98,
|
||||
0x5c, 0x0c, 0xcf, 0x24, 0xc7, 0xd5, 0x12, 0xf2, 0x18, 0xd6, 0x44, 0x5e, 0xec, 0xa6, 0xd4, 0xb0,
|
||||
0x84, 0xc6, 0x5e, 0xc6, 0xaf, 0x5c, 0xc9, 0x25, 0x23, 0x68, 0xaa, 0x6f, 0x9a, 0xda, 0x56, 0xbf,
|
||||
0x36, 0x68, 0x8f, 0x6c, 0xa1, 0xa0, 0xa3, 0x1c, 0xaa, 0x32, 0x48, 0x0f, 0x23, 0xce, 0x66, 0x6e,
|
||||
0xae, 0x48, 0xbe, 0x07, 0x1d, 0x2f, 0x0c, 0x30, 0xe2, 0x63, 0x1e, 0x5f, 0x63, 0x64, 0xb7, 0xa4,
|
||||
0x47, 0x6d, 0xc5, 0x3b, 0x17, 0x2c, 0x32, 0x82, 0xfb, 0xa6, 0xca, 0x98, 0x7a, 0x1e, 0xa6, 0x69,
|
||||
0xcc, 0x6c, 0x90, 0xba, 0xf7, 0x0c, 0xdd, 0x3d, 0x2d, 0x12, 0xc7, 0xfa, 0x41, 0x9a, 0x84, 0x74,
|
||||
0x36, 0x8e, 0xe8, 0x14, 0xed, 0xb6, 0x3a, 0x56, 0xf3, 0xbe, 0xa2, 0x53, 0x24, 0x3b, 0xd0, 0x9e,
|
||||
0xc6, 0x59, 0xc4, 0xc7, 0x49, 0x1c, 0x44, 0xdc, 0xee, 0x48, 0x0d, 0x90, 0xac, 0x53, 0xc1, 0x21,
|
||||
0x1f, 0x80, 0xa2, 0x54, 0x31, 0x76, 0x55, 0x5e, 0x25, 0x47, 0x96, 0xe3, 0x13, 0x58, 0x57, 0xe2,
|
||||
0xc2, 0x9f, 0x75, 0xa9, 0xd2, 0x95, 0xdc, 0xc2, 0x93, 0x17, 0xd0, 0x92, 0xf5, 0x10, 0x44, 0x97,
|
||||
0xb1, 0xbd, 0x21, 0xf3, 0x76, 0xcf, 0x48, 0x8b, 0xa8, 0x89, 0xa3, 0xe8, 0x32, 0x76, 0xad, 0x5b,
|
||||
0xbd, 0x22, 0x9f, 0xc2, 0xa3, 0x52, 0xbc, 0x0c, 0xa7, 0x34, 0x88, 0x82, 0x68, 0x32, 0xce, 0x52,
|
||||
0x4c, 0xed, 0x4d, 0x59, 0xe1, 0xb6, 0x11, 0xb5, 0x9b, 0x2b, 0xbc, 0x49, 0x31, 0x25, 0x8f, 0xa0,
|
||||
0x25, 0xea, 0x96, 0xcf, 0xc6, 0x81, 0x6f, 0x6f, 0x49, 0x97, 0x2c, 0xc5, 0x38, 0xf2, 0xc9, 0x47,
|
||||
0xb0, 0x91, 0xc4, 0x61, 0xe0, 0xcd, 0xc6, 0xf1, 0x0d, 0x32, 0x16, 0xf8, 0x68, 0x93, 0x7e, 0x65,
|
||||
0x60, 0xb9, 0xeb, 0x8a, 0xfd, 0xb5, 0xe6, 0xae, 0x6a, 0x8d, 0x7b, 0x52, 0x71, 0xa9, 0x35, 0x86,
|
||||
0x00, 0x5e, 0x1c, 0x45, 0xe8, 0xc9, 0xf2, 0xdb, 0x96, 0x11, 0xae, 0x8b, 0x08, 0xf7, 0x0b, 0xae,
|
||||
0x6b, 0x68, 0xf4, 0x3e, 0x87, 0x8e, 0x59, 0x0a, 0x64, 0x13, 0x6a, 0xd7, 0x38, 0xd3, 0xe5, 0x2f,
|
||||
0x96, 0xa4, 0x0f, 0xf5, 0x1b, 0x1a, 0x66, 0x28, 0x4b, 0x5e, 0x17, 0xa2, 0xda, 0xe2, 0x2a, 0xc1,
|
||||
0x4f, 0xab, 0xaf, 0x2a, 0x0e, 0x85, 0xfa, 0x5e, 0x18, 0xd0, 0x74, 0xe1, 0x3b, 0x55, 0xde, 0xfd,
|
||||
0x9d, 0xaa, 0xab, 0xbe, 0x13, 0x81, 0x35, 0x59, 0x29, 0xaa, 0x7f, 0xe4, 0xda, 0xf9, 0x57, 0x0d,
|
||||
0xd6, 0x44, 0x7d, 0x93, 0x1f, 0x41, 0x37, 0x44, 0x9a, 0xe2, 0x38, 0x4e, 0x44, 0x0c, 0xa9, 0xb4,
|
||||
0xd2, 0x1e, 0x6d, 0x0a, 0xcf, 0x8e, 0x85, 0xe0, 0x6b, 0xc5, 0x77, 0x3b, 0xa1, 0x41, 0x09, 0xd4,
|
||||
0x08, 0x22, 0x8e, 0x2c, 0xa2, 0xe1, 0x58, 0xf6, 0x9b, 0xb2, 0xdc, 0xc9, 0x99, 0x07, 0xa2, 0xef,
|
||||
0x16, 0x4b, 0xb5, 0xb6, 0x5c, 0xaa, 0x3d, 0xb0, 0xe4, 0xe7, 0x09, 0x30, 0xd5, 0x78, 0x52, 0xd0,
|
||||
0x64, 0x04, 0xd6, 0x14, 0x39, 0xd5, 0xed, 0x2c, 0xba, 0xee, 0x41, 0xde, 0x96, 0xc3, 0x13, 0x2d,
|
||||
0x50, 0x3d, 0x57, 0xe8, 0x2d, 0x35, 0x5d, 0x63, 0xb9, 0xe9, 0x7a, 0x60, 0x15, 0xf9, 0x6a, 0xaa,
|
||||
0x22, 0xca, 0x69, 0x81, 0xe4, 0x09, 0xb2, 0x20, 0xf6, 0x6d, 0x4b, 0xd6, 0xa2, 0xa6, 0x04, 0x0e,
|
||||
0x47, 0xd9, 0x54, 0x55, 0x69, 0x4b, 0xe1, 0x70, 0x94, 0x4d, 0x97, 0x8b, 0x12, 0x16, 0x8a, 0x72,
|
||||
0x07, 0xea, 0x54, 0x7c, 0x49, 0xd9, 0xa5, 0xed, 0x51, 0x4b, 0xfa, 0x2f, 0x18, 0xae, 0xe2, 0x93,
|
||||
0x21, 0x74, 0x27, 0x2c, 0xce, 0x92, 0xb1, 0x24, 0x31, 0xb5, 0x3b, 0x32, 0x50, 0x43, 0xb1, 0x23,
|
||||
0xe5, 0x7b, 0x4a, 0xdc, 0xfb, 0x19, 0x74, 0x4b, 0xa1, 0xaf, 0xa8, 0xb1, 0x6d, 0xb3, 0xc6, 0x5a,
|
||||
0x66, 0x5d, 0xfd, 0xa9, 0x02, 0x1d, 0xf3, 0x9b, 0x8a, 0xcd, 0xe7, 0xe7, 0xc7, 0x72, 0x73, 0xcd,
|
||||
0x15, 0x4b, 0x01, 0xb8, 0x0c, 0x23, 0xbc, 0xa5, 0x17, 0xa1, 0x3a, 0xc0, 0x72, 0xe7, 0x0c, 0x21,
|
||||
0x0d, 0x22, 0x8f, 0xe1, 0x14, 0x23, 0xae, 0xe7, 0xd1, 0x9c, 0x41, 0x3e, 0x01, 0x08, 0xd2, 0x34,
|
||||
0xc3, 0xb1, 0x18, 0x99, 0x12, 0x94, 0xdb, 0xa3, 0xde, 0x50, 0xcd, 0xd3, 0x61, 0x3e, 0x4f, 0x87,
|
||||
0xe7, 0xf9, 0x3c, 0x75, 0x5b, 0x52, 0x5b, 0xd0, 0x22, 0xef, 0x27, 0xf4, 0xad, 0xf0, 0xa5, 0xae,
|
||||
0xf2, 0xae, 0x28, 0xe7, 0x0f, 0xd0, 0x50, 0x38, 0xfd, 0x7f, 0xad, 0xd3, 0x87, 0x60, 0xa9, 0xb3,
|
||||
0x03, 0x5f, 0xd7, 0x68, 0x53, 0xd2, 0x47, 0xbe, 0xf3, 0xb7, 0x0a, 0x58, 0x2e, 0xa6, 0x49, 0x1c,
|
||||
0xa5, 0x68, 0xcc, 0x91, 0xca, 0x3b, 0xe7, 0x48, 0x75, 0xe5, 0x1c, 0xc9, 0xa7, 0x53, 0xcd, 0x98,
|
||||
0x4e, 0x3d, 0xb0, 0x18, 0xfa, 0x01, 0x43, 0x8f, 0xeb, 0x49, 0x56, 0xd0, 0x42, 0x76, 0x4b, 0x99,
|
||||
0x00, 0xc0, 0x54, 0xb6, 0x40, 0xcb, 0x2d, 0x68, 0xf2, 0xd2, 0x84, 0x5f, 0x35, 0xd8, 0xb6, 0x15,
|
||||
0xfc, 0x2a, 0x77, 0x97, 0xf1, 0xd7, 0xf9, 0x6b, 0x15, 0x36, 0x17, 0xc5, 0x2b, 0x8a, 0x60, 0x1b,
|
||||
0xea, 0xaa, 0x7b, 0x74, 0x05, 0xf1, 0xa5, 0xbe, 0xa9, 0x2d, 0xf4, 0xcd, 0xcf, 0xa1, 0xeb, 0x31,
|
||||
0x94, 0x53, 0xf9, 0x7d, 0xbf, 0x7e, 0x27, 0xdf, 0x20, 0x0b, 0xe0, 0x63, 0xd8, 0x14, 0x5e, 0x26,
|
||||
0xe8, 0xcf, 0xc1, 0x4c, 0x8d, 0xf0, 0x0d, 0xcd, 0x2f, 0xe0, 0xec, 0x19, 0x6c, 0xe5, 0xaa, 0xf3,
|
||||
0xc6, 0x6b, 0x94, 0x74, 0x0f, 0xf3, 0xfe, 0x7b, 0x00, 0x8d, 0xcb, 0x98, 0x4d, 0x29, 0xd7, 0x9d,
|
||||
0xae, 0x29, 0x51, 0x16, 0x85, 0xbf, 0xf2, 0x0a, 0x61, 0xa9, 0xb2, 0xc8, 0x99, 0xe2, 0x62, 0x25,
|
||||
0x3a, 0xbb, 0xb8, 0xf4, 0xc8, 0xae, 0xb7, 0x5c, 0x2b, 0xbf, 0xec, 0x38, 0xbf, 0x86, 0x8d, 0x85,
|
||||
0x39, 0xb7, 0x22, 0x91, 0x73, 0xf3, 0xd5, 0x92, 0xf9, 0xd2, 0xc9, 0xb5, 0x85, 0x93, 0x7f, 0x03,
|
||||
0x5b, 0x5f, 0xd0, 0xc8, 0x0f, 0x51, 0x9f, 0xbf, 0xc7, 0x26, 0x72, 0x12, 0xe8, 0x6b, 0xd7, 0x58,
|
||||
0x5f, 0xa8, 0xba, 0x6e, 0x4b, 0x73, 0x8e, 0x7c, 0xf2, 0x04, 0x9a, 0x4c, 0x69, 0xeb, 0xc2, 0x6b,
|
||||
0x1b, 0x83, 0xd8, 0xcd, 0x65, 0xce, 0xb7, 0x40, 0x4a, 0x47, 0x8b, 0x1b, 0xd7, 0x8c, 0x0c, 0x44,
|
||||
0x01, 0xaa, 0xa2, 0xd0, 0x85, 0xdd, 0x31, 0xeb, 0xc8, 0x2d, 0xa4, 0xa4, 0x0f, 0x35, 0x64, 0x4c,
|
||||
0x9b, 0x90, 0x93, 0x70, 0x7e, 0xbf, 0x75, 0x85, 0xc8, 0xf9, 0x21, 0x6c, 0x9d, 0x25, 0xe8, 0x05,
|
||||
0x34, 0x94, 0x77, 0x53, 0x65, 0x60, 0x07, 0xea, 0x22, 0xc9, 0x79, 0xcf, 0x4a, 0x70, 0x53, 0x62,
|
||||
0xc5, 0x77, 0xbe, 0x05, 0x5b, 0xf9, 0x75, 0xf8, 0x36, 0x48, 0x39, 0x46, 0x1e, 0xee, 0x5f, 0xa1,
|
||||
0x77, 0xfd, 0x3f, 0x8c, 0xfc, 0x06, 0x1e, 0xae, 0xb2, 0x90, 0xfb, 0xd7, 0xf6, 0x04, 0x35, 0xbe,
|
||||
0x8c, 0xb3, 0x48, 0xd9, 0xb0, 0x5c, 0x90, 0xac, 0xcf, 0x05, 0x47, 0x7c, 0x47, 0x14, 0xfb, 0x52,
|
||||
0x0d, 0x89, 0x9a, 0xca, 0xf3, 0x51, 0xbb, 0x3b, 0x1f, 0x7f, 0xae, 0x40, 0xeb, 0x0c, 0x79, 0x96,
|
||||
0xc8, 0x58, 0x1e, 0x41, 0xeb, 0x82, 0xc5, 0xd7, 0xc8, 0xe6, 0xa1, 0x58, 0x8a, 0x71, 0xe4, 0x93,
|
||||
0x97, 0xd0, 0xd8, 0x8f, 0xa3, 0xcb, 0x60, 0x22, 0x6f, 0xea, 0xed, 0xd1, 0x43, 0x85, 0x2e, 0x7a,
|
||||
0xef, 0x50, 0xc9, 0xd4, 0xbc, 0xd3, 0x8a, 0xa4, 0x0f, 0x6d, 0xfd, 0x82, 0x79, 0xf3, 0xe6, 0xe8,
|
||||
0x20, 0x9f, 0xaf, 0x06, 0xab, 0xf7, 0x09, 0xb4, 0x8d, 0x8d, 0xff, 0xd5, 0xb4, 0xf8, 0x2e, 0x80,
|
||||
0xb4, 0xae, 0x72, 0xb4, 0xa9, 0x42, 0xd5, 0x3b, 0x45, 0x68, 0x3b, 0xd0, 0x12, 0xb7, 0x10, 0x25,
|
||||
0x26, 0xb0, 0x66, 0x3c, 0x6c, 0xe4, 0xda, 0x79, 0x02, 0x5b, 0x47, 0xd1, 0x0d, 0x0d, 0x03, 0x9f,
|
||||
0x72, 0xfc, 0x12, 0x67, 0x32, 0x05, 0x4b, 0x1e, 0x38, 0x67, 0xd0, 0xd1, 0x4f, 0x87, 0xf7, 0xf2,
|
||||
0xb1, 0xa3, 0x7d, 0xfc, 0xcf, 0x4d, 0xf4, 0x31, 0x6c, 0xe8, 0x43, 0x8f, 0x03, 0xdd, 0x42, 0x62,
|
||||
0xb6, 0x33, 0xbc, 0x0c, 0xde, 0xea, 0xa3, 0x35, 0xe5, 0xbc, 0x82, 0x4d, 0x43, 0xb5, 0x08, 0xe7,
|
||||
0x1a, 0x67, 0x69, 0xfe, 0xa4, 0x12, 0xeb, 0x3c, 0x03, 0xd5, 0x79, 0x06, 0x1c, 0x58, 0xd7, 0x3b,
|
||||
0x5f, 0x23, 0xbf, 0x23, 0xba, 0x2f, 0x0b, 0x47, 0x5e, 0xa3, 0x3e, 0xfc, 0x29, 0xd4, 0x51, 0x44,
|
||||
0x6a, 0x8e, 0x30, 0x33, 0x03, 0xae, 0x12, 0xaf, 0x30, 0xf8, 0xaa, 0x30, 0x78, 0x9a, 0x29, 0x83,
|
||||
0xef, 0x79, 0x96, 0xf3, 0x61, 0xe1, 0xc6, 0x69, 0xc6, 0xef, 0xfa, 0xa2, 0x4f, 0x60, 0x4b, 0x2b,
|
||||
0x1d, 0x60, 0x88, 0x1c, 0xef, 0x08, 0xe9, 0x29, 0x90, 0x92, 0xda, 0x5d, 0xc7, 0x3d, 0x06, 0xeb,
|
||||
0xfc, 0xfc, 0xb8, 0x90, 0x96, 0xb1, 0xd1, 0xf9, 0x14, 0xb6, 0xce, 0x32, 0x3f, 0x3e, 0x65, 0xc1,
|
||||
0x4d, 0x10, 0xe2, 0x44, 0x19, 0xcb, 0x5f, 0x74, 0x15, 0xe3, 0x45, 0xb7, 0x72, 0x1a, 0x39, 0x03,
|
||||
0x20, 0xa5, 0xed, 0xc5, 0x77, 0x4b, 0x33, 0x3f, 0xd6, 0x2d, 0x2c, 0xd7, 0xce, 0x00, 0x3a, 0xe7,
|
||||
0x54, 0xcc, 0x7b, 0x5f, 0xe9, 0xd8, 0xd0, 0xe4, 0x8a, 0xd6, 0x6a, 0x39, 0xe9, 0x8c, 0x60, 0x7b,
|
||||
0x9f, 0x7a, 0x57, 0x41, 0x34, 0x39, 0x08, 0x52, 0x71, 0xe1, 0xd1, 0x3b, 0x7a, 0x60, 0xf9, 0x9a,
|
||||
0xa1, 0xb7, 0x14, 0xb4, 0xf3, 0x1c, 0xee, 0x1b, 0xef, 0xd6, 0x33, 0x4e, 0xf3, 0x7c, 0x6c, 0x43,
|
||||
0x3d, 0x15, 0x94, 0xdc, 0x51, 0x77, 0x15, 0xe1, 0x7c, 0x05, 0xdb, 0xe6, 0x00, 0x16, 0xd7, 0x8f,
|
||||
0x3c, 0x70, 0x79, 0x31, 0xa8, 0x18, 0x17, 0x03, 0x9d, 0xb3, 0xea, 0x7c, 0x9e, 0x6c, 0x42, 0xed,
|
||||
0x97, 0xdf, 0x9c, 0xeb, 0x62, 0x17, 0x4b, 0xe7, 0x77, 0xc2, 0x7c, 0xf9, 0x3c, 0x65, 0xbe, 0x74,
|
||||
0x3b, 0xa8, 0xbc, 0xcf, 0xed, 0x60, 0x45, 0xbd, 0x3d, 0x87, 0xad, 0x93, 0x30, 0xf6, 0xae, 0x0f,
|
||||
0x23, 0x23, 0x1b, 0x36, 0x34, 0x31, 0x32, 0x93, 0x91, 0x93, 0xce, 0x47, 0xb0, 0x71, 0x1c, 0x7b,
|
||||
0x34, 0x3c, 0x11, 0xcf, 0x8f, 0x22, 0x0b, 0xf2, 0x47, 0x82, 0x56, 0x55, 0x84, 0xf3, 0x1c, 0x60,
|
||||
0xfe, 0x84, 0x12, 0xf0, 0xcb, 0x70, 0x1a, 0x73, 0x1c, 0x53, 0xdf, 0xcf, 0x2b, 0x08, 0x14, 0x6b,
|
||||
0xcf, 0xf7, 0xd9, 0xe8, 0x9f, 0x55, 0x68, 0xfe, 0x42, 0x81, 0x1a, 0xf9, 0x0c, 0xba, 0xa5, 0x11,
|
||||
0x46, 0xee, 0xcb, 0x37, 0xd4, 0xe2, 0xc0, 0xec, 0x3d, 0x58, 0x62, 0x2b, 0x87, 0x5e, 0x40, 0xc7,
|
||||
0x1c, 0x50, 0x44, 0x0e, 0x23, 0xf9, 0x43, 0xa7, 0x27, 0x4f, 0x5a, 0x9e, 0x5e, 0x67, 0xb0, 0xbd,
|
||||
0x6a, 0x74, 0x90, 0xc7, 0x73, 0x0b, 0xcb, 0x63, 0xab, 0xf7, 0xc1, 0x5d, 0xd2, 0x7c, 0xe4, 0x34,
|
||||
0xf7, 0x43, 0xa4, 0x51, 0x96, 0x98, 0x1e, 0xcc, 0x97, 0xe4, 0x25, 0x74, 0x4b, 0xe0, 0xa9, 0xe2,
|
||||
0x5c, 0xc2, 0x53, 0x73, 0xcb, 0x53, 0xa8, 0x4b, 0xc0, 0x26, 0xdd, 0xd2, 0xe4, 0xe8, 0xad, 0x17,
|
||||
0xa4, 0xb2, 0xdd, 0x87, 0x35, 0xf9, 0x7c, 0x34, 0x0c, 0xcb, 0x1d, 0x05, 0x9a, 0x8f, 0xfe, 0x5e,
|
||||
0x81, 0x66, 0xfe, 0xeb, 0xe7, 0x25, 0xac, 0x09, 0x5c, 0x24, 0xf7, 0x0c, 0x68, 0xc9, 0x31, 0xb5,
|
||||
0xb7, 0xbd, 0xc0, 0x54, 0x06, 0x86, 0x50, 0x7b, 0x8d, 0x9c, 0x10, 0x43, 0xa8, 0x01, 0xb2, 0x77,
|
||||
0xaf, 0xcc, 0x2b, 0xf4, 0x4f, 0xb3, 0xb2, 0xbe, 0xc6, 0xb7, 0x92, 0x7e, 0x81, 0x5c, 0x3f, 0x81,
|
||||
0x86, 0x42, 0x1e, 0x95, 0x94, 0x25, 0xcc, 0x52, 0x1f, 0x7f, 0x19, 0xa3, 0x46, 0xff, 0xa8, 0x01,
|
||||
0x9c, 0xcd, 0x52, 0x8e, 0xd3, 0x5f, 0x05, 0x78, 0x4b, 0x9e, 0xc1, 0xc6, 0x01, 0x5e, 0xd2, 0x2c,
|
||||
0xe4, 0xf2, 0x05, 0x21, 0x3a, 0xcc, 0xc8, 0x89, 0xbc, 0x04, 0x15, 0x00, 0xf6, 0x14, 0xda, 0x27,
|
||||
0xf4, 0xed, 0xbb, 0xf5, 0x3e, 0x83, 0x6e, 0x09, 0x97, 0xb4, 0x8b, 0x8b, 0x48, 0xa7, 0x5d, 0x5c,
|
||||
0x46, 0xb0, 0xa7, 0xd0, 0xd4, 0x68, 0x65, 0xda, 0x90, 0xb8, 0x5e, 0x42, 0xb1, 0x1f, 0xc3, 0xc6,
|
||||
0x02, 0x56, 0x99, 0xfa, 0xf2, 0xf7, 0xd4, 0x4a, 0x2c, 0x7b, 0x25, 0x5e, 0x00, 0x65, 0xbc, 0x32,
|
||||
0x37, 0x3e, 0x54, 0x18, 0xb1, 0x0a, 0xd0, 0x5e, 0x97, 0xdf, 0x0e, 0xf2, 0xe5, 0x64, 0x2f, 0x42,
|
||||
0x4a, 0x0e, 0x68, 0xf9, 0x41, 0xab, 0xa0, 0xe9, 0x05, 0x74, 0x4c, 0x54, 0x59, 0x6a, 0xc1, 0x65,
|
||||
0xc8, 0xf9, 0x3e, 0xc0, 0x1c, 0x58, 0x4c, 0x7d, 0x59, 0x1e, 0x0b, 0x98, 0x73, 0xd1, 0x90, 0xaf,
|
||||
0x8d, 0x1f, 0xfc, 0x3b, 0x00, 0x00, 0xff, 0xff, 0x3f, 0x7b, 0x3e, 0xd0, 0xf0, 0x15, 0x00, 0x00,
|
||||
}
|
||||
|
||||
@@ -212,6 +212,8 @@ message LeaseOptions {
|
||||
int64 increment = 3;
|
||||
|
||||
google.protobuf.Timestamp issue_time = 4;
|
||||
|
||||
int64 MaxTTL = 5;
|
||||
}
|
||||
|
||||
message Secret {
|
||||
|
||||
@@ -136,6 +136,7 @@ func ProtoLeaseOptionsToLogicalLeaseOptions(l *LeaseOptions) (logical.LeaseOptio
|
||||
Renewable: l.Renewable,
|
||||
Increment: time.Duration(l.Increment),
|
||||
IssueTime: t,
|
||||
MaxTTL: time.Duration(l.MaxTTL),
|
||||
}, err
|
||||
}
|
||||
|
||||
@@ -150,6 +151,7 @@ func LogicalLeaseOptionsToProtoLeaseOptions(l logical.LeaseOptions) (*LeaseOptio
|
||||
Renewable: l.Renewable,
|
||||
Increment: int64(l.Increment),
|
||||
IssueTime: t,
|
||||
MaxTTL: int64(l.MaxTTL),
|
||||
}, err
|
||||
}
|
||||
|
||||
|
||||
@@ -92,6 +92,7 @@ func TestTranslation_Request(t *testing.T) {
|
||||
Secret: &logical.Secret{
|
||||
LeaseOptions: logical.LeaseOptions{
|
||||
TTL: time.Second,
|
||||
MaxTTL: time.Second,
|
||||
Renewable: true,
|
||||
Increment: time.Second,
|
||||
IssueTime: time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC),
|
||||
@@ -104,6 +105,7 @@ func TestTranslation_Request(t *testing.T) {
|
||||
Auth: &logical.Auth{
|
||||
LeaseOptions: logical.LeaseOptions{
|
||||
TTL: time.Second,
|
||||
MaxTTL: time.Second,
|
||||
Renewable: true,
|
||||
Increment: time.Second,
|
||||
IssueTime: time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC),
|
||||
@@ -192,6 +194,7 @@ func TestTranslation_Response(t *testing.T) {
|
||||
Secret: &logical.Secret{
|
||||
LeaseOptions: logical.LeaseOptions{
|
||||
TTL: time.Second,
|
||||
MaxTTL: time.Second,
|
||||
Renewable: true,
|
||||
Increment: time.Second,
|
||||
IssueTime: time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC),
|
||||
@@ -204,6 +207,7 @@ func TestTranslation_Response(t *testing.T) {
|
||||
Auth: &logical.Auth{
|
||||
LeaseOptions: logical.LeaseOptions{
|
||||
TTL: time.Second,
|
||||
MaxTTL: time.Second,
|
||||
Renewable: true,
|
||||
Increment: time.Second,
|
||||
IssueTime: time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC),
|
||||
|
||||
@@ -381,7 +381,7 @@ func TestCore_HandleRequest_Lease_MaxLength(t *testing.T) {
|
||||
t.Fatalf("bad: %#v", resp)
|
||||
}
|
||||
if resp.Secret.TTL != c.maxLeaseTTL {
|
||||
t.Fatalf("bad: %#v", resp.Secret)
|
||||
t.Fatalf("bad: %#v, %d", resp.Secret, c.maxLeaseTTL)
|
||||
}
|
||||
if resp.Secret.LeaseID == "" {
|
||||
t.Fatalf("bad: %#v", resp.Secret)
|
||||
@@ -422,7 +422,7 @@ func TestCore_HandleRequest_Lease_DefaultLength(t *testing.T) {
|
||||
t.Fatalf("bad: %#v", resp)
|
||||
}
|
||||
if resp.Secret.TTL != c.defaultLeaseTTL {
|
||||
t.Fatalf("bad: %#v", resp.Secret)
|
||||
t.Fatalf("bad: %#v, %d", resp.Secret, c.defaultLeaseTTL)
|
||||
}
|
||||
if resp.Secret.LeaseID == "" {
|
||||
t.Fatalf("bad: %#v", resp.Secret)
|
||||
|
||||
@@ -6,7 +6,6 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/errwrap"
|
||||
|
||||
"github.com/hashicorp/vault/helper/consts"
|
||||
"github.com/hashicorp/vault/helper/pluginutil"
|
||||
"github.com/hashicorp/vault/helper/wrapping"
|
||||
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
"github.com/hashicorp/vault/helper/jsonutil"
|
||||
"github.com/hashicorp/vault/helper/locksutil"
|
||||
"github.com/hashicorp/vault/logical"
|
||||
"github.com/hashicorp/vault/logical/framework"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -640,21 +641,36 @@ func (m *ExpirationManager) Renew(leaseID string, increment time.Duration) (*log
|
||||
return logical.ErrorResponse("lease does not correspond to a secret"), nil
|
||||
}
|
||||
|
||||
sysView := m.router.MatchingSystemView(le.Path)
|
||||
if sysView == nil {
|
||||
return nil, fmt.Errorf("expiration: unable to retrieve system view from router")
|
||||
}
|
||||
|
||||
// Attempt to renew the entry
|
||||
resp, err := m.renewEntry(le, increment)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Fast-path if there is no lease
|
||||
if resp == nil || resp.Secret == nil || !resp.Secret.LeaseEnabled() {
|
||||
return resp, nil
|
||||
if resp == nil {
|
||||
return nil, nil
|
||||
}
|
||||
if resp.IsError() {
|
||||
return &logical.Response{
|
||||
Data: resp.Data,
|
||||
}, nil
|
||||
}
|
||||
if resp.Secret == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Validate the lease
|
||||
if err := resp.Secret.Validate(); err != nil {
|
||||
ttl, warnings, err := framework.CalculateTTL(sysView, increment, resp.Secret.TTL, 0, resp.Secret.MaxTTL, 0, le.IssueTime)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, warning := range warnings {
|
||||
resp.AddWarning(warning)
|
||||
}
|
||||
resp.Secret.TTL = ttl
|
||||
|
||||
// Attach the LeaseID
|
||||
resp.Secret.LeaseID = leaseID
|
||||
@@ -744,21 +760,16 @@ func (m *ExpirationManager) RenewToken(req *logical.Request, source string, toke
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if resp == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
if resp.IsError() {
|
||||
return &logical.Response{
|
||||
Data: resp.Data,
|
||||
}, nil
|
||||
}
|
||||
|
||||
if resp.Auth == nil || !resp.Auth.LeaseEnabled() {
|
||||
return &logical.Response{
|
||||
Auth: resp.Auth,
|
||||
}, nil
|
||||
if resp.Auth == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
sysView := m.router.MatchingSystemView(le.Path)
|
||||
@@ -766,29 +777,18 @@ func (m *ExpirationManager) RenewToken(req *logical.Request, source string, toke
|
||||
return nil, fmt.Errorf("expiration: unable to retrieve system view from router")
|
||||
}
|
||||
|
||||
ttl, warnings, err := framework.CalculateTTL(sysView, increment, resp.Auth.TTL, resp.Auth.Period, resp.Auth.MaxTTL, resp.Auth.ExplicitMaxTTL, le.IssueTime)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
retResp := &logical.Response{}
|
||||
switch {
|
||||
case resp.Auth.Period > time.Duration(0):
|
||||
// If it resp.Period is non-zero, use that as the TTL and override backend's
|
||||
// call on TTL modification, such as a TTL value determined by
|
||||
// framework.LeaseExtend call against the request. Also, cap period value to
|
||||
// the sys/mount max value.
|
||||
if resp.Auth.Period > sysView.MaxLeaseTTL() {
|
||||
retResp.AddWarning(fmt.Sprintf("Period of %d seconds is greater than current mount/system default of %d seconds, value will be truncated.", int64(resp.Auth.TTL.Seconds()), int64(sysView.MaxLeaseTTL().Seconds())))
|
||||
resp.Auth.Period = sysView.MaxLeaseTTL()
|
||||
}
|
||||
resp.Auth.TTL = resp.Auth.Period
|
||||
case resp.Auth.TTL > time.Duration(0):
|
||||
// Cap TTL value to the sys/mount max value
|
||||
if resp.Auth.TTL > sysView.MaxLeaseTTL() {
|
||||
retResp.AddWarning(fmt.Sprintf("TTL of %d seconds is greater than current mount/system default of %d seconds, value will be truncated.", int64(resp.Auth.TTL.Seconds()), int64(sysView.MaxLeaseTTL().Seconds())))
|
||||
resp.Auth.TTL = sysView.MaxLeaseTTL()
|
||||
}
|
||||
for _, warning := range warnings {
|
||||
retResp.AddWarning(warning)
|
||||
}
|
||||
resp.Auth.TTL = ttl
|
||||
|
||||
// Attach the ClientToken
|
||||
resp.Auth.ClientToken = token
|
||||
resp.Auth.Increment = 0
|
||||
|
||||
// Update the lease entry
|
||||
le.Auth = resp.Auth
|
||||
@@ -902,12 +902,6 @@ func (m *ExpirationManager) RegisterAuth(source string, auth *logical.Auth) erro
|
||||
return err
|
||||
}
|
||||
|
||||
// If it resp.Period is non-zero, override the TTL value determined
|
||||
// by the backend.
|
||||
if auth.Period > time.Duration(0) {
|
||||
auth.TTL = auth.Period
|
||||
}
|
||||
|
||||
// Create a lease entry
|
||||
le := leaseEntry{
|
||||
LeaseID: path.Join(source, saltedID),
|
||||
@@ -1069,7 +1063,6 @@ func (m *ExpirationManager) renewEntry(le *leaseEntry, increment time.Duration)
|
||||
secret.IssueTime = le.IssueTime
|
||||
secret.Increment = increment
|
||||
secret.LeaseID = ""
|
||||
|
||||
req := logical.RenewRequest(le.Path, &secret, le.Data)
|
||||
resp, err := m.router.Route(m.quitContext, req)
|
||||
if err != nil || (resp != nil && resp.IsError()) {
|
||||
|
||||
@@ -796,8 +796,14 @@ func TestExpiration_RenewToken(t *testing.T) {
|
||||
|
||||
func TestExpiration_RenewToken_period(t *testing.T) {
|
||||
exp := mockExpiration(t)
|
||||
root, err := exp.tokenStore.rootToken(context.Background())
|
||||
if err != nil {
|
||||
root := &TokenEntry{
|
||||
Policies: []string{"root"},
|
||||
Path: "auth/token/root",
|
||||
DisplayName: "root",
|
||||
CreationTime: time.Now().Unix(),
|
||||
Period: time.Minute,
|
||||
}
|
||||
if err := exp.tokenStore.create(context.Background(), root); err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
|
||||
@@ -810,7 +816,7 @@ func TestExpiration_RenewToken_period(t *testing.T) {
|
||||
},
|
||||
Period: time.Minute,
|
||||
}
|
||||
err = exp.RegisterAuth("auth/token/login", auth)
|
||||
err := exp.RegisterAuth("auth/token/login", auth)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
@@ -869,7 +875,6 @@ func TestExpiration_RenewToken_period_backend(t *testing.T) {
|
||||
LeaseOptions: logical.LeaseOptions{
|
||||
TTL: 10 * time.Second,
|
||||
Renewable: true,
|
||||
IssueTime: time.Now(),
|
||||
},
|
||||
Period: 5 * time.Second,
|
||||
}
|
||||
@@ -888,8 +893,8 @@ func TestExpiration_RenewToken_period_backend(t *testing.T) {
|
||||
if resp == nil {
|
||||
t.Fatal("expected a response")
|
||||
}
|
||||
if resp.Auth.TTL > 5*time.Second {
|
||||
t.Fatalf("expected TTL to be less than or equal to period, got: %s", resp.Auth.TTL)
|
||||
if resp.Auth.TTL == 0 || resp.Auth.TTL > 5*time.Second {
|
||||
t.Fatalf("expected TTL to be greater than zero and less than or equal to period, got: %s", resp.Auth.TTL)
|
||||
}
|
||||
|
||||
// Wait another 3 seconds. If period works correctly, this should not fail
|
||||
@@ -1293,7 +1298,7 @@ func TestExpiration_renewEntry(t *testing.T) {
|
||||
ExpireTime: time.Now(),
|
||||
}
|
||||
|
||||
resp, err := exp.renewEntry(le, time.Second)
|
||||
resp, err := exp.renewEntry(le)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
@@ -1312,12 +1317,6 @@ func TestExpiration_renewEntry(t *testing.T) {
|
||||
if !reflect.DeepEqual(req.Data, le.Data) {
|
||||
t.Fatalf("Bad: %v", req)
|
||||
}
|
||||
if req.Secret.Increment != time.Second {
|
||||
t.Fatalf("Bad: %v", req)
|
||||
}
|
||||
if req.Secret.IssueTime.IsZero() {
|
||||
t.Fatalf("Bad: %v", req)
|
||||
}
|
||||
}
|
||||
|
||||
func TestExpiration_renewAuthEntry(t *testing.T) {
|
||||
@@ -1360,7 +1359,7 @@ func TestExpiration_renewAuthEntry(t *testing.T) {
|
||||
ExpireTime: time.Now().Add(time.Minute),
|
||||
}
|
||||
|
||||
resp, err := exp.renewAuthEntry(&logical.Request{}, le, time.Second)
|
||||
resp, err := exp.renewAuthEntry(&logical.Request{}, le)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
@@ -1379,12 +1378,6 @@ func TestExpiration_renewAuthEntry(t *testing.T) {
|
||||
if req.Path != "login" {
|
||||
t.Fatalf("Bad: %v", req)
|
||||
}
|
||||
if req.Auth.Increment != time.Second {
|
||||
t.Fatalf("Bad: %v", req)
|
||||
}
|
||||
if req.Auth.IssueTime.IsZero() {
|
||||
t.Fatalf("Bad: %v", req)
|
||||
}
|
||||
if req.Auth.InternalData["MySecret"] != "secret" {
|
||||
t.Fatalf("Bad: %v", req)
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ import (
|
||||
"github.com/hashicorp/vault/helper/strutil"
|
||||
"github.com/hashicorp/vault/helper/wrapping"
|
||||
"github.com/hashicorp/vault/logical"
|
||||
"github.com/hashicorp/vault/logical/framework"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -290,25 +291,6 @@ func (c *Core) handleRequest(ctx context.Context, req *logical.Request) (retResp
|
||||
// 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") &&
|
||||
!strings.HasPrefix(req.Path, "sys/leases/renew") {
|
||||
// Get the SystemView for the mount
|
||||
sysView := c.router.MatchingSystemView(req.Path)
|
||||
if sysView == nil {
|
||||
c.logger.Error("unable to retrieve system view from router")
|
||||
retErr = multierror.Append(retErr, ErrInternalError)
|
||||
return nil, auth, retErr
|
||||
}
|
||||
|
||||
// Apply the default lease if none given
|
||||
if resp.Secret.TTL == 0 {
|
||||
resp.Secret.TTL = sysView.DefaultLeaseTTL()
|
||||
}
|
||||
|
||||
// Limit the lease duration
|
||||
maxTTL := sysView.MaxLeaseTTL()
|
||||
if resp.Secret.TTL > maxTTL {
|
||||
resp.Secret.TTL = maxTTL
|
||||
}
|
||||
|
||||
// KV mounts should return the TTL but not register
|
||||
// for a lease as this provides a massive slowdown
|
||||
registerLease := true
|
||||
@@ -351,6 +333,21 @@ func (c *Core) handleRequest(ctx context.Context, req *logical.Request) (retResp
|
||||
}
|
||||
|
||||
if registerLease {
|
||||
sysView := c.router.MatchingSystemView(req.Path)
|
||||
if sysView == nil {
|
||||
c.logger.Error("core: unable to look up sys view for login path", "request_path", req.Path)
|
||||
return nil, nil, ErrInternalError
|
||||
}
|
||||
|
||||
ttl, warnings, err := framework.CalculateTTL(sysView, 0, resp.Secret.TTL, 0, resp.Secret.MaxTTL, 0, time.Time{})
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
for _, warning := range warnings {
|
||||
resp.AddWarning(warning)
|
||||
}
|
||||
resp.Secret.TTL = ttl
|
||||
|
||||
leaseID, err := c.expiration.Register(req, resp)
|
||||
if err != nil {
|
||||
c.logger.Error("failed to register lease", "request_path", req.Path, "error", err)
|
||||
@@ -549,27 +546,12 @@ func (c *Core) handleLoginRequest(ctx context.Context, req *logical.Request) (re
|
||||
return nil, nil, ErrInternalError
|
||||
}
|
||||
|
||||
// Start off with the sys default value, and update according to period/TTL
|
||||
// from resp.Auth
|
||||
tokenTTL := sysView.DefaultLeaseTTL()
|
||||
|
||||
switch {
|
||||
case auth.Period > time.Duration(0):
|
||||
// Cap the period value to the sys max_ttl value. The auth backend should
|
||||
// have checked for it on its login path, but we check here again for
|
||||
// sanity.
|
||||
if auth.Period > sysView.MaxLeaseTTL() {
|
||||
auth.Period = sysView.MaxLeaseTTL()
|
||||
tokenTTL, warnings, err := framework.CalculateTTL(sysView, 0, auth.TTL, auth.Period, auth.MaxTTL, auth.ExplicitMaxTTL, time.Time{})
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
tokenTTL = auth.Period
|
||||
case auth.TTL > time.Duration(0):
|
||||
// Cap the TTL value. The auth backend should have checked for it on its
|
||||
// login path (e.g. a call to b.SanitizeTTL), but we check here again for
|
||||
// sanity.
|
||||
if auth.TTL > sysView.MaxLeaseTTL() {
|
||||
auth.TTL = sysView.MaxLeaseTTL()
|
||||
}
|
||||
tokenTTL = auth.TTL
|
||||
for _, warning := range warnings {
|
||||
resp.AddWarning(warning)
|
||||
}
|
||||
|
||||
// Generate a token
|
||||
|
||||
@@ -766,11 +766,11 @@ func (ts *TokenStore) create(ctx context.Context, entry *TokenEntry) error {
|
||||
entry.ID = entryUUID
|
||||
}
|
||||
|
||||
saltedId, err := ts.SaltID(ctx, entry.ID)
|
||||
saltedID, err := ts.SaltID(ctx, entry.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
exist, _ := ts.lookupSalted(ctx, saltedId, true)
|
||||
exist, _ := ts.lookupSalted(ctx, saltedID, true)
|
||||
if exist != nil {
|
||||
return fmt.Errorf("cannot create a token with a duplicate ID")
|
||||
}
|
||||
@@ -795,7 +795,7 @@ func (ts *TokenStore) store(ctx context.Context, entry *TokenEntry) error {
|
||||
// storeCommon handles the actual storage of an entry, possibly generating
|
||||
// secondary indexes
|
||||
func (ts *TokenStore) storeCommon(ctx context.Context, entry *TokenEntry, writeSecondary bool) error {
|
||||
saltedId, err := ts.SaltID(ctx, entry.ID)
|
||||
saltedID, err := ts.SaltID(ctx, entry.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -826,7 +826,7 @@ func (ts *TokenStore) storeCommon(ctx context.Context, entry *TokenEntry, writeS
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
path := parentPrefix + parentSaltedID + "/" + saltedId
|
||||
path := parentPrefix + parentSaltedID + "/" + saltedID
|
||||
le := &logical.StorageEntry{Key: path}
|
||||
if err := ts.view.Put(ctx, le); err != nil {
|
||||
return fmt.Errorf("failed to persist entry: %v", err)
|
||||
@@ -835,7 +835,7 @@ func (ts *TokenStore) storeCommon(ctx context.Context, entry *TokenEntry, writeS
|
||||
}
|
||||
|
||||
// Write the primary ID
|
||||
path := lookupPrefix + saltedId
|
||||
path := lookupPrefix + saltedID
|
||||
le := &logical.StorageEntry{Key: path, Value: enc}
|
||||
if len(entry.Policies) == 1 && entry.Policies[0] == "root" {
|
||||
le.SealWrap = true
|
||||
@@ -1060,11 +1060,11 @@ func (ts *TokenStore) Revoke(ctx context.Context, id string) error {
|
||||
|
||||
// revokeSalted is used to invalidate a given salted token,
|
||||
// any child tokens will be orphaned.
|
||||
func (ts *TokenStore) revokeSalted(ctx context.Context, saltedId string) (ret error) {
|
||||
func (ts *TokenStore) revokeSalted(ctx context.Context, saltedID string) (ret error) {
|
||||
// Protect the entry lookup/writing with locks. The rub here is that we
|
||||
// don't know the ID until we look it up once, so first we look it up, then
|
||||
// do a locked lookup.
|
||||
entry, err := ts.lookupSalted(ctx, saltedId, true)
|
||||
entry, err := ts.lookupSalted(ctx, saltedID, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -1076,7 +1076,7 @@ func (ts *TokenStore) revokeSalted(ctx context.Context, saltedId string) (ret er
|
||||
lock.Lock()
|
||||
|
||||
// Lookup the token first
|
||||
entry, err = ts.lookupSalted(ctx, saltedId, true)
|
||||
entry, err = ts.lookupSalted(ctx, saltedID, true)
|
||||
if err != nil {
|
||||
lock.Unlock()
|
||||
return err
|
||||
@@ -1116,7 +1116,7 @@ func (ts *TokenStore) revokeSalted(ctx context.Context, saltedId string) (ret er
|
||||
|
||||
// Lookup the token again to make sure something else didn't
|
||||
// revoke in the interim
|
||||
entry, err := ts.lookupSalted(ctx, saltedId, true)
|
||||
entry, err := ts.lookupSalted(ctx, saltedID, true)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -1132,7 +1132,7 @@ func (ts *TokenStore) revokeSalted(ctx context.Context, saltedId string) (ret er
|
||||
|
||||
// Destroy the token's cubby. This should go first as it's a
|
||||
// security-sensitive item.
|
||||
err = ts.cubbyholeDestroyer(ctx, ts, saltedId)
|
||||
err = ts.cubbyholeDestroyer(ctx, ts, saltedID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -1150,7 +1150,7 @@ func (ts *TokenStore) revokeSalted(ctx context.Context, saltedId string) (ret er
|
||||
return err
|
||||
}
|
||||
|
||||
path := parentPrefix + parentSaltedID + "/" + saltedId
|
||||
path := parentPrefix + parentSaltedID + "/" + saltedID
|
||||
if err = ts.view.Delete(ctx, path); err != nil {
|
||||
return fmt.Errorf("failed to delete entry: %v", err)
|
||||
}
|
||||
@@ -1177,7 +1177,7 @@ func (ts *TokenStore) revokeSalted(ctx context.Context, saltedId string) (ret er
|
||||
// explicit call to orphan the child tokens (the delete occurs at the leaf
|
||||
// node and uses parent prefix, not entry.Parent, to build the tree for
|
||||
// traversal).
|
||||
parentPath := parentPrefix + saltedId + "/"
|
||||
parentPath := parentPrefix + saltedID + "/"
|
||||
children, err := ts.view.List(ctx, parentPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to scan for children: %v", err)
|
||||
@@ -1203,7 +1203,7 @@ func (ts *TokenStore) revokeSalted(ctx context.Context, saltedId string) (ret er
|
||||
}
|
||||
|
||||
// Now that the entry is not usable for any revocation tasks, nuke it
|
||||
path := lookupPrefix + saltedId
|
||||
path := lookupPrefix + saltedID
|
||||
if err = ts.view.Delete(ctx, path); err != nil {
|
||||
return fmt.Errorf("failed to delete entry: %v", err)
|
||||
}
|
||||
@@ -1221,25 +1221,22 @@ func (ts *TokenStore) RevokeTree(ctx context.Context, id string) error {
|
||||
}
|
||||
|
||||
// Get the salted ID
|
||||
saltedId, err := ts.SaltID(ctx, id)
|
||||
saltedID, err := ts.SaltID(ctx, id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Nuke the entire tree recursively
|
||||
if err := ts.revokeTreeSalted(ctx, saltedId); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
return ts.revokeTreeSalted(ctx, saltedID)
|
||||
}
|
||||
|
||||
// revokeTreeSalted is used to invalidate a given token and all
|
||||
// child tokens using a saltedID.
|
||||
// Updated to be non-recursive and revoke child tokens
|
||||
// before parent tokens(DFS).
|
||||
func (ts *TokenStore) revokeTreeSalted(ctx context.Context, saltedId string) error {
|
||||
func (ts *TokenStore) revokeTreeSalted(ctx context.Context, saltedID string) error {
|
||||
var dfs []string
|
||||
dfs = append(dfs, saltedId)
|
||||
dfs = append(dfs, saltedID)
|
||||
|
||||
for l := len(dfs); l > 0; l = len(dfs) {
|
||||
id := dfs[0]
|
||||
@@ -1467,13 +1464,13 @@ func (ts *TokenStore) handleTidy(ctx context.Context, req *logical.Request, data
|
||||
|
||||
// Look up tainted variants so we only find entries that truly don't
|
||||
// exist
|
||||
saltedId, err := ts.SaltID(ctx, accessorEntry.TokenID)
|
||||
saltedID, err := ts.SaltID(ctx, accessorEntry.TokenID)
|
||||
if err != nil {
|
||||
tidyErrors = multierror.Append(tidyErrors, fmt.Errorf("failed to read salt id: %v", err))
|
||||
lock.RUnlock()
|
||||
continue
|
||||
}
|
||||
te, err := ts.lookupSalted(ctx, saltedId, true)
|
||||
te, err := ts.lookupSalted(ctx, saltedID, true)
|
||||
if err != nil {
|
||||
tidyErrors = multierror.Append(tidyErrors, fmt.Errorf("failed to lookup tainted ID: %v", err))
|
||||
lock.RUnlock()
|
||||
@@ -1486,7 +1483,7 @@ func (ts *TokenStore) handleTidy(ctx context.Context, req *logical.Request, data
|
||||
// more and conclude that accessor, leases, and secondary index entries
|
||||
// for this token should not exist as well.
|
||||
if te == nil {
|
||||
ts.logger.Info("deleting token with nil entry", "salted_token", saltedId)
|
||||
ts.logger.Info("deleting token with nil entry", "salted_token", saltedID)
|
||||
|
||||
// RevokeByToken expects a '*TokenEntry'. For the
|
||||
// purposes of tidying, it is sufficient if the token
|
||||
@@ -1884,6 +1881,7 @@ func (ts *TokenStore) handleCreateCommon(ctx context.Context, req *logical.Reque
|
||||
te.EntityID = parent.EntityID
|
||||
}
|
||||
|
||||
var explicitMaxTTLToUse time.Duration
|
||||
if data.ExplicitMaxTTL != "" {
|
||||
dur, err := parseutil.ParseDurationSecond(data.ExplicitMaxTTL)
|
||||
if err != nil {
|
||||
@@ -1893,6 +1891,7 @@ func (ts *TokenStore) handleCreateCommon(ctx context.Context, req *logical.Reque
|
||||
return logical.ErrorResponse("explicit_max_ttl must be positive"), logical.ErrInvalidRequest
|
||||
}
|
||||
te.ExplicitMaxTTL = dur
|
||||
explicitMaxTTLToUse = dur
|
||||
}
|
||||
|
||||
var periodToUse time.Duration
|
||||
@@ -1942,13 +1941,13 @@ func (ts *TokenStore) handleCreateCommon(ctx context.Context, req *logical.Reque
|
||||
if role != nil {
|
||||
if role.ExplicitMaxTTL != 0 {
|
||||
switch {
|
||||
case te.ExplicitMaxTTL == 0:
|
||||
te.ExplicitMaxTTL = role.ExplicitMaxTTL
|
||||
case explicitMaxTTLToUse == 0:
|
||||
explicitMaxTTLToUse = role.ExplicitMaxTTL
|
||||
default:
|
||||
if role.ExplicitMaxTTL < te.ExplicitMaxTTL {
|
||||
te.ExplicitMaxTTL = role.ExplicitMaxTTL
|
||||
if role.ExplicitMaxTTL < explicitMaxTTLToUse {
|
||||
explicitMaxTTLToUse = role.ExplicitMaxTTL
|
||||
}
|
||||
resp.AddWarning(fmt.Sprintf("Explicit max TTL specified both during creation call and in role; using the lesser value of %d seconds", int64(te.ExplicitMaxTTL.Seconds())))
|
||||
resp.AddWarning(fmt.Sprintf("Explicit max TTL specified both during creation call and in role; using the lesser value of %d seconds", int64(explicitMaxTTLToUse.Seconds())))
|
||||
}
|
||||
}
|
||||
if role.Period != 0 {
|
||||
@@ -1966,49 +1965,21 @@ func (ts *TokenStore) handleCreateCommon(ctx context.Context, req *logical.Reque
|
||||
|
||||
sysView := ts.System()
|
||||
|
||||
if periodToUse > 0 {
|
||||
// Cap period value to the sys/mount max value; this matches behavior
|
||||
// in expiration manager for renewals
|
||||
if periodToUse > sysView.MaxLeaseTTL() {
|
||||
resp.AddWarning(fmt.Sprintf("Period of %d seconds is greater than current mount/system default of %d seconds, value will be truncated.", int64(periodToUse.Seconds()), int64(sysView.MaxLeaseTTL().Seconds())))
|
||||
periodToUse = sysView.MaxLeaseTTL()
|
||||
// Only calculate a TTL if you are A) periodic, B) have a TTL, C) do not have a TTL and are not a root token
|
||||
if periodToUse > 0 || te.TTL > 0 || (te.TTL == 0 && !strutil.StrListContains(te.Policies, "root")) {
|
||||
ttl, warnings, err := framework.CalculateTTL(sysView, 0, te.TTL, periodToUse, 0, explicitMaxTTLToUse, time.Unix(te.CreationTime, 0))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
te.TTL = periodToUse
|
||||
} else {
|
||||
// Set the default lease if not provided, root tokens are exempt
|
||||
if te.TTL == 0 && !strutil.StrListContains(te.Policies, "root") {
|
||||
te.TTL = sysView.DefaultLeaseTTL()
|
||||
for _, warning := range warnings {
|
||||
resp.AddWarning(warning)
|
||||
}
|
||||
te.TTL = ttl
|
||||
}
|
||||
|
||||
// Limit the lease duration
|
||||
if te.TTL > sysView.MaxLeaseTTL() && sysView.MaxLeaseTTL() != 0 {
|
||||
te.TTL = sysView.MaxLeaseTTL()
|
||||
}
|
||||
}
|
||||
|
||||
// Run some bounding checks if the explicit max TTL is set; we do not check
|
||||
// period as it's defined to escape the max TTL
|
||||
if te.ExplicitMaxTTL > 0 {
|
||||
// Limit the lease duration, except for periodic tokens -- in that case the explicit max limits the period, which itself can escape normal max
|
||||
if sysView.MaxLeaseTTL() != 0 && te.ExplicitMaxTTL > sysView.MaxLeaseTTL() && periodToUse == 0 {
|
||||
resp.AddWarning(fmt.Sprintf(
|
||||
"Explicit max TTL of %d seconds is greater than system/mount allowed value; value is being capped to %d seconds",
|
||||
int64(te.ExplicitMaxTTL.Seconds()), int64(sysView.MaxLeaseTTL().Seconds())))
|
||||
te.ExplicitMaxTTL = sysView.MaxLeaseTTL()
|
||||
}
|
||||
|
||||
if te.TTL == 0 {
|
||||
// This won't be the case if it's periodic -- it will be set above
|
||||
te.TTL = te.ExplicitMaxTTL
|
||||
} else {
|
||||
// Limit even in the periodic case
|
||||
if te.TTL > te.ExplicitMaxTTL {
|
||||
resp.AddWarning(fmt.Sprintf(
|
||||
"Requested TTL of %d seconds higher than explicit max TTL; value being capped to %d seconds",
|
||||
int64(te.TTL.Seconds()), int64(te.ExplicitMaxTTL.Seconds())))
|
||||
te.TTL = te.ExplicitMaxTTL
|
||||
}
|
||||
}
|
||||
// Root tokens are still bound by explicit max TTL
|
||||
if te.TTL == 0 && explicitMaxTTLToUse > 0 {
|
||||
te.TTL = explicitMaxTTLToUse
|
||||
}
|
||||
|
||||
// Don't advertise non-expiring root tokens as renewable, as attempts to renew them are denied
|
||||
@@ -2037,6 +2008,8 @@ func (ts *TokenStore) handleCreateCommon(ctx context.Context, req *logical.Reque
|
||||
ClientToken: te.ID,
|
||||
Accessor: te.Accessor,
|
||||
EntityID: te.EntityID,
|
||||
Period: periodToUse,
|
||||
ExplicitMaxTTL: explicitMaxTTLToUse,
|
||||
}
|
||||
|
||||
if ts.policyLookupFunc != nil {
|
||||
@@ -2166,11 +2139,11 @@ func (ts *TokenStore) handleLookup(ctx context.Context, req *logical.Request, da
|
||||
defer lock.RUnlock()
|
||||
|
||||
// Lookup the token
|
||||
saltedId, err := ts.SaltID(ctx, id)
|
||||
saltedID, err := ts.SaltID(ctx, id)
|
||||
if err != nil {
|
||||
return logical.ErrorResponse(err.Error()), logical.ErrInvalidRequest
|
||||
}
|
||||
out, err := ts.lookupSalted(ctx, saltedId, true)
|
||||
out, err := ts.lookupSalted(ctx, saltedID, true)
|
||||
if err != nil {
|
||||
return logical.ErrorResponse(err.Error()), logical.ErrInvalidRequest
|
||||
}
|
||||
@@ -2301,68 +2274,23 @@ func (ts *TokenStore) authRenew(ctx context.Context, req *logical.Request, d *fr
|
||||
return nil, fmt.Errorf("no token entry found during lookup")
|
||||
}
|
||||
|
||||
f := framework.LeaseExtend(req.Auth.Increment, te.ExplicitMaxTTL, ts.System())
|
||||
|
||||
// If (te/role).Period is not zero, this is a periodic token. The TTL for a
|
||||
// periodic token is always the same (the period value). It is not subject
|
||||
// to normal maximum TTL checks that would come from calling LeaseExtend,
|
||||
// so we fast path it.
|
||||
//
|
||||
// The one wrinkle here is if the token has an explicit max TTL. If both
|
||||
// are set, we treat it as a regular token and use the periodic value as
|
||||
// the increment.
|
||||
|
||||
// No role? Use normal LeaseExtend semantics, taking into account
|
||||
// TokenEntry properties
|
||||
if te.Role == "" {
|
||||
//Explicit max TTL overrides the period, if both are set
|
||||
if te.Period != 0 {
|
||||
if te.ExplicitMaxTTL == 0 {
|
||||
req.Auth.TTL = te.Period
|
||||
req.Auth.Period = te.Period
|
||||
req.Auth.ExplicitMaxTTL = te.ExplicitMaxTTL
|
||||
return &logical.Response{Auth: req.Auth}, nil
|
||||
} else {
|
||||
maxTime := time.Unix(te.CreationTime, 0).Add(te.ExplicitMaxTTL)
|
||||
if time.Now().Add(te.Period).After(maxTime) {
|
||||
req.Auth.TTL = maxTime.Sub(time.Now())
|
||||
} else {
|
||||
req.Auth.TTL = te.Period
|
||||
}
|
||||
return &logical.Response{Auth: req.Auth}, nil
|
||||
}
|
||||
}
|
||||
return f(ctx, req, d)
|
||||
}
|
||||
|
||||
role, err := ts.tokenStoreRole(ctx, te.Role)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error looking up role %s: %s", te.Role, err)
|
||||
}
|
||||
|
||||
if role == nil {
|
||||
return nil, fmt.Errorf("original token role (%s) could not be found, not renewing", te.Role)
|
||||
}
|
||||
|
||||
// Same deal here, but using the role period
|
||||
if role.Period != 0 {
|
||||
periodToUse := role.Period
|
||||
if te.Period > 0 && te.Period < role.Period {
|
||||
periodToUse = te.Period
|
||||
}
|
||||
if te.ExplicitMaxTTL == 0 {
|
||||
req.Auth.TTL = periodToUse
|
||||
req.Auth.Period = role.Period
|
||||
req.Auth.ExplicitMaxTTL = role.ExplicitMaxTTL
|
||||
return &logical.Response{Auth: req.Auth}, nil
|
||||
} else {
|
||||
maxTime := time.Unix(te.CreationTime, 0).Add(te.ExplicitMaxTTL)
|
||||
if time.Now().Add(periodToUse).After(maxTime) {
|
||||
req.Auth.TTL = maxTime.Sub(time.Now())
|
||||
} else {
|
||||
req.Auth.TTL = periodToUse
|
||||
}
|
||||
return &logical.Response{Auth: req.Auth}, nil
|
||||
}
|
||||
}
|
||||
|
||||
return f(ctx, req, d)
|
||||
}
|
||||
|
||||
func (ts *TokenStore) tokenStoreRole(ctx context.Context, name string) (*tsRoleEntry, error) {
|
||||
|
||||
@@ -59,11 +59,11 @@ func TestTokenStore_TokenEntryUpgrade(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
saltedId, err := ts.SaltID(context.Background(), entry.ID)
|
||||
saltedID, err := ts.SaltID(context.Background(), entry.ID)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
path := lookupPrefix + saltedId
|
||||
path := lookupPrefix + saltedID
|
||||
le := &logical.StorageEntry{
|
||||
Key: path,
|
||||
Value: enc,
|
||||
@@ -2381,7 +2381,7 @@ func TestTokenStore_RolePeriod(t *testing.T) {
|
||||
}
|
||||
ttl = resp.Data["ttl"].(int64)
|
||||
if ttl > 8 {
|
||||
t.Fatalf("TTL too large")
|
||||
t.Fatalf("TTL too large: %d", ttl)
|
||||
}
|
||||
|
||||
// Renewing should not have the increment increase since we've hit the
|
||||
@@ -2596,9 +2596,10 @@ func TestTokenStore_RoleExplicitMaxTTL(t *testing.T) {
|
||||
if ttl > 10 {
|
||||
t.Fatalf("TTL too big")
|
||||
}
|
||||
// explicit max ttl is stored in the role so not returned here
|
||||
maxTTL := resp.Data["explicit_max_ttl"].(int64)
|
||||
if maxTTL != 10 {
|
||||
t.Fatalf("expected 6 for explicit max TTL, got %d", maxTTL)
|
||||
if maxTTL != 0 {
|
||||
t.Fatalf("expected 0 for explicit max TTL, got %d", maxTTL)
|
||||
}
|
||||
|
||||
// Let the TTL go down a bit to ~7 seconds (8 against explicit max)
|
||||
@@ -2622,7 +2623,7 @@ func TestTokenStore_RoleExplicitMaxTTL(t *testing.T) {
|
||||
}
|
||||
ttl = resp.Data["ttl"].(int64)
|
||||
if ttl > 8 {
|
||||
t.Fatalf("TTL too big")
|
||||
t.Fatalf("TTL too big: %d", ttl)
|
||||
}
|
||||
|
||||
// Let the TTL go down a bit more to ~5 seconds (6 against explicit max)
|
||||
@@ -2755,7 +2756,92 @@ func TestTokenStore_Periodic(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// Do the same with an explicit max TTL
|
||||
// Now we create a token against the role and also set the te value
|
||||
// directly. We should use the smaller of the two and be able to renew;
|
||||
// increment should be ignored as well.
|
||||
{
|
||||
req.ClientToken = root
|
||||
req.Operation = logical.UpdateOperation
|
||||
req.Path = "auth/token/create/test"
|
||||
req.Data = map[string]interface{}{
|
||||
"period": 5,
|
||||
}
|
||||
resp, err = core.HandleRequest(req)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v %v", err, resp)
|
||||
}
|
||||
if resp == nil {
|
||||
t.Fatal("response was nil")
|
||||
}
|
||||
if resp.Auth == nil {
|
||||
t.Fatalf(fmt.Sprintf("response auth was nil, resp is %#v", *resp))
|
||||
}
|
||||
if resp.Auth.ClientToken == "" {
|
||||
t.Fatalf("bad: %#v", resp)
|
||||
}
|
||||
|
||||
req.ClientToken = resp.Auth.ClientToken
|
||||
req.Operation = logical.ReadOperation
|
||||
req.Path = "auth/token/lookup-self"
|
||||
resp, err = core.HandleRequest(req)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
ttl := resp.Data["ttl"].(int64)
|
||||
if ttl < 4 || ttl > 5 {
|
||||
t.Fatalf("TTL bad (expected %d, got %d)", 4, ttl)
|
||||
}
|
||||
|
||||
// Let the TTL go down a bit
|
||||
time.Sleep(2 * time.Second)
|
||||
|
||||
req.Operation = logical.UpdateOperation
|
||||
req.Path = "auth/token/renew-self"
|
||||
req.Data = map[string]interface{}{
|
||||
"increment": 1,
|
||||
}
|
||||
resp, err = core.HandleRequest(req)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v %v", err, resp)
|
||||
}
|
||||
|
||||
req.Operation = logical.ReadOperation
|
||||
req.Path = "auth/token/lookup-self"
|
||||
resp, err = core.HandleRequest(req)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
ttl = resp.Data["ttl"].(int64)
|
||||
if ttl > 5 {
|
||||
t.Fatalf("TTL bad (expected less than %d, got %d)", 5, ttl)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestTokenStore_Periodic_ExplicitMax(t *testing.T) {
|
||||
core, _, _, root := TestCoreWithTokenStore(t)
|
||||
|
||||
core.defaultLeaseTTL = 10 * time.Second
|
||||
core.maxLeaseTTL = 10 * time.Second
|
||||
|
||||
// Note: these requests are sent to Core since Core handles registration
|
||||
// with the expiration manager and we need the storage to be consistent
|
||||
|
||||
req := logical.TestRequest(t, logical.UpdateOperation, "auth/token/roles/test")
|
||||
req.ClientToken = root
|
||||
req.Data = map[string]interface{}{
|
||||
"period": 5,
|
||||
}
|
||||
|
||||
resp, err := core.HandleRequest(req)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v %v", err, resp)
|
||||
}
|
||||
if resp != nil {
|
||||
t.Fatalf("expected a nil response")
|
||||
}
|
||||
|
||||
// First make one directly and verify on renew it uses the period.
|
||||
{
|
||||
req.ClientToken = root
|
||||
req.Operation = logical.UpdateOperation
|
||||
@@ -2818,65 +2904,6 @@ func TestTokenStore_Periodic(t *testing.T) {
|
||||
// Now we create a token against the role and also set the te value
|
||||
// directly. We should use the smaller of the two and be able to renew;
|
||||
// increment should be ignored as well.
|
||||
{
|
||||
req.ClientToken = root
|
||||
req.Operation = logical.UpdateOperation
|
||||
req.Path = "auth/token/create/test"
|
||||
req.Data = map[string]interface{}{
|
||||
"period": 5,
|
||||
}
|
||||
resp, err = core.HandleRequest(req)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v %v", err, resp)
|
||||
}
|
||||
if resp == nil {
|
||||
t.Fatal("response was nil")
|
||||
}
|
||||
if resp.Auth == nil {
|
||||
t.Fatalf(fmt.Sprintf("response auth was nil, resp is %#v", *resp))
|
||||
}
|
||||
if resp.Auth.ClientToken == "" {
|
||||
t.Fatalf("bad: %#v", resp)
|
||||
}
|
||||
|
||||
req.ClientToken = resp.Auth.ClientToken
|
||||
req.Operation = logical.ReadOperation
|
||||
req.Path = "auth/token/lookup-self"
|
||||
resp, err = core.HandleRequest(req)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
ttl := resp.Data["ttl"].(int64)
|
||||
if ttl < 4 || ttl > 5 {
|
||||
t.Fatalf("TTL bad (expected %d, got %d)", 4, ttl)
|
||||
}
|
||||
|
||||
// Let the TTL go down a bit
|
||||
time.Sleep(2 * time.Second)
|
||||
|
||||
req.Operation = logical.UpdateOperation
|
||||
req.Path = "auth/token/renew-self"
|
||||
req.Data = map[string]interface{}{
|
||||
"increment": 1,
|
||||
}
|
||||
resp, err = core.HandleRequest(req)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v %v", err, resp)
|
||||
}
|
||||
|
||||
req.Operation = logical.ReadOperation
|
||||
req.Path = "auth/token/lookup-self"
|
||||
resp, err = core.HandleRequest(req)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
ttl = resp.Data["ttl"].(int64)
|
||||
if ttl > 5 {
|
||||
t.Fatalf("TTL bad (expected less than %d, got %d)", 5, ttl)
|
||||
}
|
||||
}
|
||||
|
||||
// Now do the same, also using an explicit max in the role
|
||||
{
|
||||
req.Path = "auth/token/roles/test"
|
||||
req.ClientToken = root
|
||||
|
||||
Reference in New Issue
Block a user