Make backends much more consistent:

1) Use the new LeaseExtend
2) Use default values controlled by mount tuning/system defaults instead
of a random hard coded value
3) Remove grace periods
This commit is contained in:
Jeff Mitchell
2016-01-29 17:44:09 -05:00
parent c4c170555a
commit 2eb08d3bde
23 changed files with 120 additions and 99 deletions

View File

@@ -77,6 +77,8 @@ func Backend(conf *logical.BackendConfig) (*framework.Backend, error) {
b.MapAppId.Paths(),
b.MapUserId.Paths(),
),
AuthRenew: b.pathLoginRenew,
}
// Since the salt is new in 0.2, we need to handle this by migrating

View File

@@ -129,10 +129,19 @@ func (b *backend) pathLogin(
DisplayName: displayName,
Policies: policies,
Metadata: metadata,
LeaseOptions: logical.LeaseOptions{
Renewable: true,
},
},
}, nil
}
func (b *backend) pathLoginRenew(
req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
return framework.LeaseExtend(0, 0, b.System())(req, d)
}
const pathLoginSyn = `
Log in with an App ID and User ID.
`

View File

@@ -207,7 +207,7 @@ func validateConnState(roots *x509.CertPool, cs *tls.ConnectionState) ([][]*x509
func (b *backend) pathLoginRenew(
req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
// Get the cert and validate auth
// Get the cert and use its TTL
cert, err := b.Cert(req.Storage, req.Auth.Metadata["cert_name"])
if err != nil {
return nil, err
@@ -217,5 +217,5 @@ func (b *backend) pathLoginRenew(
return nil, nil
}
return framework.LeaseExtend(cert.TTL, 0, false)(req, d)
return framework.LeaseExtend(cert.TTL, 0, b.System())(req, d)
}

View File

@@ -139,8 +139,7 @@ func (b *backend) pathLogin(
DisplayName: *user.Login,
LeaseOptions: logical.LeaseOptions{
TTL: ttl,
GracePeriod: ttl / 10,
Renewable: ttl > 0,
Renewable: true,
},
},
}, nil
@@ -152,5 +151,5 @@ func (b *backend) pathLoginRenew(
if err != nil {
return nil, err
}
return framework.LeaseExtend(config.MaxTTL, 0, false)(req, d)
return framework.LeaseExtend(config.TTL, config.MaxTTL, b.System())(req, d)
}

View File

@@ -3,7 +3,6 @@ package ldap
import (
"sort"
"strings"
"time"
"github.com/hashicorp/vault/logical"
"github.com/hashicorp/vault/logical/framework"
@@ -56,6 +55,9 @@ func (b *backend) pathLogin(
"password": password,
},
DisplayName: username,
LeaseOptions: logical.LeaseOptions{
Renewable: true,
},
},
}, nil
}
@@ -77,7 +79,7 @@ func (b *backend) pathLoginRenew(
return logical.ErrorResponse("policies have changed, revoking login"), nil
}
return framework.LeaseExtend(1*time.Hour, 0, false)(req, d)
return framework.LeaseExtend(0, 0, b.System())(req, d)
}
const pathLoginSyn = `

View File

@@ -69,8 +69,7 @@ func (b *backend) pathLogin(
DisplayName: username,
LeaseOptions: logical.LeaseOptions{
TTL: user.TTL,
GracePeriod: user.TTL / 10,
Renewable: user.TTL > 0,
Renewable: true,
},
},
}, nil
@@ -78,7 +77,7 @@ func (b *backend) pathLogin(
func (b *backend) pathLoginRenew(
req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
// Get the user and validate auth
// Get the user
user, err := b.User(req.Storage, req.Auth.Metadata["username"])
if err != nil {
return nil, err
@@ -88,7 +87,7 @@ func (b *backend) pathLoginRenew(
return nil, nil
}
return framework.LeaseExtend(user.MaxTTL, 0, false)(req, d)
return framework.LeaseExtend(user.TTL, user.MaxTTL, b.System())(req, d)
}
const pathLoginSyn = `

View File

@@ -6,12 +6,13 @@ import (
"regexp"
"time"
"strings"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/iam"
"github.com/aws/aws-sdk-go/service/sts"
"github.com/hashicorp/vault/logical"
"github.com/hashicorp/vault/logical/framework"
"strings"
)
const SecretAccessKeyType = "access_keys"
@@ -35,9 +36,6 @@ func secretAccessKeys(b *backend) *framework.Secret {
},
},
DefaultDuration: 1 * time.Hour,
DefaultGracePeriod: 10 * time.Minute,
Renew: b.secretAccessKeysRenew,
Revoke: secretAccessKeysRevoke,
}
@@ -76,8 +74,7 @@ func (b *backend) secretAccessKeysAndTokenCreate(s logical.Storage,
"Error generating STS keys: %s", err)), nil
}
// Return the info!
return b.Secret(SecretAccessKeyType).Response(map[string]interface{}{
resp := b.Secret(SecretAccessKeyType).Response(map[string]interface{}{
"access_key": *tokenResp.Credentials.AccessKeyId,
"secret_key": *tokenResp.Credentials.SecretAccessKey,
"security_token": *tokenResp.Credentials.SessionToken,
@@ -85,7 +82,12 @@ func (b *backend) secretAccessKeysAndTokenCreate(s logical.Storage,
"username": username,
"policy": policy,
"is_sts": true,
}), nil
})
// Set the secret TTL to appropriately match the expiration of the token
resp.Secret.TTL = tokenResp.Credentials.Expiration.Sub(time.Now())
return resp, nil
}
func (b *backend) secretAccessKeysCreate(
@@ -159,7 +161,7 @@ func (b *backend) secretAccessKeysCreate(
}
// Return the info!
return b.Secret(SecretAccessKeyType).Response(map[string]interface{}{
resp := b.Secret(SecretAccessKeyType).Response(map[string]interface{}{
"access_key": *keyResp.AccessKey.AccessKeyId,
"secret_key": *keyResp.AccessKey.SecretAccessKey,
"security_token": nil,
@@ -167,20 +169,41 @@ func (b *backend) secretAccessKeysCreate(
"username": username,
"policy": policy,
"is_sts": false,
}), nil
})
lease, err := b.Lease(s)
if err != nil || lease == nil {
lease = &configLease{}
}
resp.Secret.TTL = lease.Lease
return resp, nil
}
func (b *backend) secretAccessKeysRenew(
req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
// STS already has a lifetime, and we don't support renewing it
isSTSRaw, ok := req.Secret.InternalData["is_sts"]
if ok {
isSTS, ok := isSTSRaw.(bool)
if ok {
if isSTS {
return nil, nil
}
}
}
lease, err := b.Lease(req.Storage)
if err != nil {
return nil, err
}
if lease == nil {
lease = &configLease{Lease: 1 * time.Hour}
lease = &configLease{}
}
f := framework.LeaseExtend(lease.Lease, lease.LeaseMax, false)
f := framework.LeaseExtend(lease.Lease, lease.LeaseMax, b.System())
return f(req, d)
}

View File

@@ -85,7 +85,6 @@ func (b *backend) pathCredsCreateRead(
"role": name,
})
resp.Secret.TTL = role.Lease
resp.Secret.GracePeriod = role.LeaseGracePeriod
return resp, nil
}

View File

@@ -58,8 +58,7 @@ template values are '{{username}}' and
"lease_grace_period": &framework.FieldSchema{
Type: framework.TypeString,
Default: "1h",
Description: `Grace period for secret renewal; defaults to
one hour`,
Description: `DEPRECATED: this has no effect`,
},
},
@@ -194,6 +193,5 @@ instance of Cassandra:
` + defaultRollbackCQL + `
"lease" and "lease_grace_period" control the lease time and the allowed grace
period past lease expiration, respectively.
"lease" the lease time; if not set the mount/system defaults are used.
`

View File

@@ -2,7 +2,6 @@ package cassandra
import (
"fmt"
"time"
"github.com/hashicorp/vault/logical"
"github.com/hashicorp/vault/logical/framework"
@@ -26,9 +25,6 @@ func secretCreds(b *backend) *framework.Secret {
},
},
DefaultDuration: 1 * time.Hour,
DefaultGracePeriod: 10 * time.Minute,
Renew: b.secretCredsRenew,
Revoke: b.secretCredsRevoke,
}
@@ -51,7 +47,7 @@ func (b *backend) secretCredsRenew(
return nil, fmt.Errorf("Unable to load role: %s", err)
}
return framework.LeaseExtend(role.Lease, 0, false)(req, d)
return framework.LeaseExtend(role.Lease, 0, b.System())(req, d)
}
func (b *backend) secretCredsRevoke(

View File

@@ -25,7 +25,7 @@ func Backend() *framework.Backend {
},
Secrets: []*framework.Secret{
secretToken(),
secretToken(&b),
},
}

View File

@@ -108,9 +108,15 @@ func pathRolesWrite(
"Error decoding policy base64: %s", err)), nil
}
}
lease, err := time.ParseDuration(d.Get("lease").(string))
if err != nil || lease == time.Duration(0) {
lease = DefaultLeaseDuration
var lease time.Duration
leaseParam := d.Get("lease").(string)
if leaseParam != "" {
lease, err = time.ParseDuration(leaseParam)
if err != nil {
return logical.ErrorResponse(fmt.Sprintf(
"error parsing given lease of %s: %s", leaseParam, err)), nil
}
}
entry, err := logical.StorageEntryJSON("policy/"+name, roleConfig{

View File

@@ -65,9 +65,10 @@ func (b *backend) pathTokenRead(
}
// Use the helper to create the secret
s := b.Secret(SecretTokenType)
s.DefaultDuration = result.Lease
return s.Response(map[string]interface{}{
s := b.Secret(SecretTokenType).Response(map[string]interface{}{
"token": token,
}, nil), nil
}, nil)
s.Secret.TTL = result.Lease
return s, nil
}

View File

@@ -1,19 +1,15 @@
package consul
import (
"time"
"github.com/hashicorp/vault/logical"
"github.com/hashicorp/vault/logical/framework"
)
const (
SecretTokenType = "token"
DefaultLeaseDuration = 1 * time.Hour
DefaultGracePeriod = 10 * time.Minute
)
func secretToken() *framework.Secret {
func secretToken(b *backend) *framework.Secret {
return &framework.Secret{
Type: SecretTokenType,
Fields: map[string]*framework.FieldSchema{
@@ -23,14 +19,17 @@ func secretToken() *framework.Secret {
},
},
DefaultDuration: DefaultLeaseDuration,
DefaultGracePeriod: DefaultGracePeriod,
Renew: framework.LeaseExtend(0, 0, true),
Renew: b.secretTokenRenew,
Revoke: secretTokenRevoke,
}
}
func (b *backend) secretTokenRenew(
req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
return framework.LeaseExtend(0, 0, b.System())(req, d)
}
func secretTokenRevoke(
req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
c, err := client(req.Storage)

View File

@@ -2,7 +2,6 @@ package mysql
import (
"fmt"
"time"
"github.com/hashicorp/go-uuid"
"github.com/hashicorp/vault/logical"
@@ -48,7 +47,7 @@ func (b *backend) pathRoleCreateRead(
return nil, err
}
if lease == nil {
lease = &configLease{Lease: 1 * time.Hour}
lease = &configLease{}
}
// Generate our username and password. MySQL limits user to 16 characters

View File

@@ -2,7 +2,6 @@ package mysql
import (
"fmt"
"time"
"github.com/hashicorp/vault/logical"
"github.com/hashicorp/vault/logical/framework"
@@ -25,9 +24,6 @@ func secretCreds(b *backend) *framework.Secret {
},
},
DefaultDuration: 1 * time.Hour,
DefaultGracePeriod: 10 * time.Minute,
Renew: b.secretCredsRenew,
Revoke: b.secretCredsRevoke,
}
@@ -41,10 +37,10 @@ func (b *backend) secretCredsRenew(
return nil, err
}
if lease == nil {
lease = &configLease{Lease: 1 * time.Hour}
lease = &configLease{}
}
f := framework.LeaseExtend(lease.Lease, lease.LeaseMax, false)
f := framework.LeaseExtend(lease.Lease, lease.LeaseMax, b.System())
return f(req, d)
}

View File

@@ -3,7 +3,6 @@ package pki
import (
"fmt"
"strings"
"time"
"github.com/hashicorp/vault/logical"
"github.com/hashicorp/vault/logical/framework"
@@ -32,9 +31,6 @@ reference`,
},
},
DefaultDuration: 168 * time.Hour,
DefaultGracePeriod: time.Duration(0),
Revoke: b.secretCredsRevoke,
}
}

View File

@@ -47,8 +47,13 @@ func (b *backend) pathRoleCreateRead(
if err != nil {
return nil, err
}
// Unlike some other backends we need a lease here (can't leave as 0 and
// let core fill it in) because Postgres also expires users as a safety
// measure, so cannot be zero
if lease == nil {
lease = &configLease{Lease: 1 * time.Hour}
lease = &configLease{
Lease: b.System().DefaultLeaseTTL(),
}
}
// Generate the username, password and expiration. PG limits user to 63 characters
@@ -69,7 +74,7 @@ func (b *backend) pathRoleCreateRead(
return nil, err
}
expiration := time.Now().UTC().
Add(lease.Lease + time.Duration((float64(lease.Lease) * 0.1))).
Add(lease.Lease).
Format("2006-01-02 15:04:05-0700")
// Get our connection

View File

@@ -2,7 +2,6 @@ package postgresql
import (
"fmt"
"time"
"github.com/hashicorp/vault/logical"
"github.com/hashicorp/vault/logical/framework"
@@ -26,9 +25,6 @@ func secretCreds(b *backend) *framework.Secret {
},
},
DefaultDuration: 1 * time.Hour,
DefaultGracePeriod: 10 * time.Minute,
Renew: b.secretCredsRenew,
Revoke: b.secretCredsRevoke,
}
@@ -55,10 +51,10 @@ func (b *backend) secretCredsRenew(
return nil, err
}
if lease == nil {
lease = &configLease{Lease: 1 * time.Hour}
lease = &configLease{}
}
f := framework.LeaseExtend(lease.Lease, lease.LeaseMax, false)
f := framework.LeaseExtend(lease.Lease, lease.LeaseMax, b.System())
resp, err := f(req, d)
if err != nil {
return nil, err
@@ -66,8 +62,7 @@ func (b *backend) secretCredsRenew(
// Make sure we increase the VALID UNTIL endpoint for this user.
if expireTime := resp.Secret.ExpirationTime(); !expireTime.IsZero() {
expiration := expireTime.Add(10 * time.Minute).
Format("2006-01-02 15:04:05-0700")
expiration := expireTime.Format("2006-01-02 15:04:05-0700")
query := fmt.Sprintf(
"ALTER ROLE %s VALID UNTIL '%s';",

View File

@@ -4,7 +4,6 @@ import (
"fmt"
"net"
"strings"
"time"
"github.com/hashicorp/go-uuid"
"github.com/hashicorp/vault/logical"
@@ -157,9 +156,6 @@ func (b *backend) pathCredsCreateWrite(
return nil, fmt.Errorf("key type unknown")
}
result.Secret.TTL = b.System().DefaultLeaseTTL()
result.Secret.GracePeriod = 2 * time.Minute
return result, nil
}

View File

@@ -2,7 +2,6 @@ package ssh
import (
"fmt"
"time"
"github.com/hashicorp/vault/logical"
"github.com/hashicorp/vault/logical/framework"
@@ -23,15 +22,14 @@ func secretDynamicKey(b *backend) *framework.Secret {
Description: "IP address of host",
},
},
DefaultDuration: 0, // this will use sysview's value
DefaultGracePeriod: 2 * time.Minute,
Renew: b.secretDynamicKeyRenew,
Revoke: b.secretDynamicKeyRevoke,
}
}
func (b *backend) secretDynamicKeyRenew(req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
f := framework.LeaseExtend(b.System().DefaultLeaseTTL(), b.System().MaxLeaseTTL(), false)
f := framework.LeaseExtend(0, 0, b.System())
return f(req, d)
}

View File

@@ -2,7 +2,6 @@ package ssh
import (
"fmt"
"time"
"github.com/hashicorp/vault/logical"
"github.com/hashicorp/vault/logical/framework"
@@ -19,8 +18,7 @@ func secretOTP(b *backend) *framework.Secret {
Description: "One time password",
},
},
DefaultDuration: 0, // this will use sysview's value
DefaultGracePeriod: 2 * time.Minute,
Revoke: b.secretOTPRevoke,
}
}

View File

@@ -80,7 +80,7 @@ func NewTokenStore(c *Core, config *logical.BackendConfig) (*TokenStore, error)
// Allow a token lease to be extended indefinitely, but each time for only
// as much as the original lease allowed for. If the lease has a 1 hour expiration,
// it can only be extended up to another hour each time this means.
AuthRenew: framework.LeaseExtend(0, 0, true),
AuthRenew: t.authRenew,
PathsSpecial: &logical.Paths{
Root: []string{
@@ -705,9 +705,7 @@ func (ts *TokenStore) handleCreateCommon(
Metadata: te.Meta,
LeaseOptions: logical.LeaseOptions{
TTL: te.TTL,
GracePeriod: te.TTL / 10,
// Tokens are renewable only if user provides lease duration
Renewable: te.TTL > 0,
Renewable: true,
},
ClientToken: te.ID,
},
@@ -914,6 +912,13 @@ func (ts *TokenStore) destroyCubbyhole(saltedID string) error {
return ts.cubbyholeBackend.revoke(salt.SaltID(ts.cubbyholeBackend.saltUUID, saltedID, salt.SHA1Hash))
}
func (ts *TokenStore) authRenew(
req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
f := framework.LeaseExtend(0, 0, ts.System())
return f(req, d)
}
const (
tokenBackendHelp = `The token credential backend is always enabled and builtin to Vault.
Client tokens are used to identify a client and to allow Vault to associate policies and ACLs