Vault userpass: Enable renewals for login tokens
This commit is contained in:
parent
8f79e8be82
commit
4332eb9d05
|
@ -3,7 +3,6 @@ package userpass
|
|||
import (
|
||||
"crypto/subtle"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/vault/logical"
|
||||
"github.com/hashicorp/vault/logical/framework"
|
||||
|
@ -68,6 +67,11 @@ func (b *backend) pathLogin(
|
|||
"username": username,
|
||||
},
|
||||
DisplayName: username,
|
||||
LeaseOptions: logical.LeaseOptions{
|
||||
TTL: user.TTL,
|
||||
GracePeriod: user.TTL / 10,
|
||||
Renewable: user.TTL > 0,
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
@ -84,7 +88,7 @@ func (b *backend) pathLoginRenew(
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
return framework.LeaseExtend(1*time.Hour, 0, false)(req, d)
|
||||
return framework.LeaseExtend(user.MaxTTL, 0, false)(req, d)
|
||||
}
|
||||
|
||||
const pathLoginSyn = `
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
package userpass
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/vault/logical"
|
||||
"github.com/hashicorp/vault/logical/framework"
|
||||
|
@ -26,6 +28,16 @@ func pathUsers(b *backend) *framework.Path {
|
|||
Type: framework.TypeString,
|
||||
Description: "Comma-separated list of policies",
|
||||
},
|
||||
"ttl": &framework.FieldSchema{
|
||||
Type: framework.TypeString,
|
||||
Default: "",
|
||||
Description: "The lease duration which decides login expiration",
|
||||
},
|
||||
"max_ttl": &framework.FieldSchema{
|
||||
Type: framework.TypeString,
|
||||
Default: "",
|
||||
Description: "Maximum duration after which login should expire",
|
||||
},
|
||||
},
|
||||
|
||||
Callbacks: map[logical.Operation]framework.OperationFunc{
|
||||
|
@ -98,10 +110,19 @@ func (b *backend) pathUserWrite(
|
|||
return nil, err
|
||||
}
|
||||
|
||||
ttlStr := d.Get("ttl").(string)
|
||||
maxTTLStr := d.Get("max_ttl").(string)
|
||||
ttl, maxTTL, err := b.SanitizeTTL(ttlStr, maxTTLStr)
|
||||
if err != nil {
|
||||
return logical.ErrorResponse(fmt.Sprintf("err: %s", err)), nil
|
||||
}
|
||||
|
||||
// Store it
|
||||
entry, err := logical.StorageEntryJSON("user/"+name, &UserEntry{
|
||||
PasswordHash: hash,
|
||||
Policies: policies,
|
||||
TTL: ttl,
|
||||
MaxTTL: maxTTL,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -123,6 +144,12 @@ type UserEntry struct {
|
|||
PasswordHash []byte
|
||||
|
||||
Policies []string
|
||||
|
||||
// Duration after which the user will be revoked unless renewed
|
||||
TTL time.Duration
|
||||
|
||||
// Maximum duration for which user can be valid
|
||||
MaxTTL time.Duration
|
||||
}
|
||||
|
||||
const pathUserHelpSyn = `
|
||||
|
|
|
@ -174,6 +174,36 @@ func (b *Backend) System() logical.SystemView {
|
|||
return b.system
|
||||
}
|
||||
|
||||
// This method takes in the TTL and MaxTTL values provided by the user, compares
|
||||
// those with the SystemView values. If they are empty default values are set.
|
||||
// If they are set, their boundaries are validated.
|
||||
func (b *Backend) SanitizeTTL(ttlStr, maxTTLStr string) (ttl, maxTTL time.Duration, err error) {
|
||||
if len(ttlStr) == 0 {
|
||||
ttl = b.System().DefaultLeaseTTL()
|
||||
} else {
|
||||
ttl, err = time.ParseDuration(ttlStr)
|
||||
if err != nil {
|
||||
return 0, 0, fmt.Errorf("Invalid ttl: %s", err)
|
||||
}
|
||||
}
|
||||
sysMaxTTL := b.System().MaxLeaseTTL()
|
||||
if len(maxTTLStr) == 0 {
|
||||
maxTTL = sysMaxTTL
|
||||
} else {
|
||||
maxTTL, err = time.ParseDuration(maxTTLStr)
|
||||
if err != nil {
|
||||
return 0, 0, fmt.Errorf("Invalid max_ttl: %s", err)
|
||||
}
|
||||
}
|
||||
if maxTTL > sysMaxTTL {
|
||||
maxTTL = sysMaxTTL
|
||||
}
|
||||
if ttl > maxTTL {
|
||||
ttl = maxTTL
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Route looks up the path that would be used for a given path string.
|
||||
func (b *Backend) Route(path string) *Path {
|
||||
result, _ := b.route(path)
|
||||
|
|
Loading…
Reference in New Issue