diff --git a/api/sys_auth.go b/api/sys_auth.go index 7b8674bb8bb9..937b0eafb4b9 100644 --- a/api/sys_auth.go +++ b/api/sys_auth.go @@ -91,7 +91,9 @@ type EnableAuthOptions struct { } type AuthConfigInput struct { - PluginName string `json:"plugin_name,omitempty" structs:"plugin_name,omitempty" mapstructure:"plugin_name"` + DefaultLeaseTTL string `json:"default_lease_ttl" structs:"default_lease_ttl" mapstructure:"default_lease_ttl"` + MaxLeaseTTL string `json:"max_lease_ttl" structs:"max_lease_ttl" mapstructure:"max_lease_ttl"` + PluginName string `json:"plugin_name,omitempty" structs:"plugin_name,omitempty" mapstructure:"plugin_name"` } type AuthMount struct { diff --git a/command/auth_enable.go b/command/auth_enable.go index 1cc8dbc1a7df..328524eb81cb 100644 --- a/command/auth_enable.go +++ b/command/auth_enable.go @@ -3,6 +3,7 @@ package command import ( "fmt" "strings" + "time" "github.com/hashicorp/vault/api" "github.com/mitchellh/cli" @@ -15,11 +16,13 @@ var _ cli.CommandAutocomplete = (*AuthEnableCommand)(nil) type AuthEnableCommand struct { *BaseCommand - flagDescription string - flagPath string - flagPluginName string - flagLocal bool - flagSealWrap bool + flagDescription string + flagPath string + flagDefaultLeaseTTL time.Duration + flagMaxLeaseTTL time.Duration + flagPluginName string + flagLocal bool + flagSealWrap bool } func (c *AuthEnableCommand) Synopsis() string { @@ -75,6 +78,24 @@ func (c *AuthEnableCommand) Flags() *FlagSets { "\"/auth/\".", }) + f.DurationVar(&DurationVar{ + Name: "default-lease-ttl", + Target: &c.flagDefaultLeaseTTL, + Completion: complete.PredictAnything, + Usage: "The default lease TTL for this auth method. If unspecified, " + + "this defaults to the Vault server's globally configured default lease " + + "TTL.", + }) + + f.DurationVar(&DurationVar{ + Name: "max-lease-ttl", + Target: &c.flagMaxLeaseTTL, + Completion: complete.PredictAnything, + Usage: "The maximum lease TTL for this auth method. If unspecified, " + + "this defaults to the Vault server's globally configured maximum lease " + + "TTL.", + }) + f.StringVar(&StringVar{ Name: "plugin-name", Target: &c.flagPluginName, @@ -155,7 +176,9 @@ func (c *AuthEnableCommand) Run(args []string) int { Local: c.flagLocal, SealWrap: c.flagSealWrap, Config: api.AuthConfigInput{ - PluginName: c.flagPluginName, + DefaultLeaseTTL: c.flagDefaultLeaseTTL.String(), + MaxLeaseTTL: c.flagMaxLeaseTTL.String(), + PluginName: c.flagPluginName, }, }); err != nil { c.UI.Error(fmt.Sprintf("Error enabling %s auth: %s", authType, err)) diff --git a/vault/logical_system.go b/vault/logical_system.go index 2f4cd725005d..f6ce8e4dbe06 100644 --- a/vault/logical_system.go +++ b/vault/logical_system.go @@ -1961,6 +1961,44 @@ func (b *SystemBackend) handleEnableAuth(ctx context.Context, req *logical.Reque } } + switch apiConfig.DefaultLeaseTTL { + case "": + case "system": + default: + tmpDef, err := parseutil.ParseDurationSecond(apiConfig.DefaultLeaseTTL) + if err != nil { + return logical.ErrorResponse(fmt.Sprintf( + "unable to parse default TTL of %s: %s", apiConfig.DefaultLeaseTTL, err)), + logical.ErrInvalidRequest + } + config.DefaultLeaseTTL = tmpDef + } + + switch apiConfig.MaxLeaseTTL { + case "": + case "system": + default: + tmpMax, err := parseutil.ParseDurationSecond(apiConfig.MaxLeaseTTL) + if err != nil { + return logical.ErrorResponse(fmt.Sprintf( + "unable to parse max TTL of %s: %s", apiConfig.MaxLeaseTTL, err)), + logical.ErrInvalidRequest + } + config.MaxLeaseTTL = tmpMax + } + + if config.MaxLeaseTTL != 0 && config.DefaultLeaseTTL > config.MaxLeaseTTL { + return logical.ErrorResponse( + "given default lease TTL greater than given max lease TTL"), + logical.ErrInvalidRequest + } + + if config.DefaultLeaseTTL > b.Core.maxLeaseTTL && config.MaxLeaseTTL == 0 { + return logical.ErrorResponse(fmt.Sprintf( + "given default lease TTL greater than system max lease TTL of %d", int(b.Core.maxLeaseTTL.Seconds()))), + logical.ErrInvalidRequest + } + // Only set plugin name if mount is of type plugin, with apiConfig.PluginName // option taking precedence. if logicalType == "plugin" { diff --git a/vault/logical_system_test.go b/vault/logical_system_test.go index 75ceedc42cab..9c0785263796 100644 --- a/vault/logical_system_test.go +++ b/vault/logical_system_test.go @@ -180,6 +180,10 @@ func TestSystemBackend_mount(t *testing.T) { req := logical.TestRequest(t, logical.UpdateOperation, "mounts/prod/secret/") req.Data["type"] = "kv" + req.Data["config"] = map[string]interface{}{ + "default_lease_ttl": "35m", + "max_lease_ttl": "45m", + } req.Data["local"] = true req.Data["seal_wrap"] = true @@ -257,8 +261,8 @@ func TestSystemBackend_mount(t *testing.T) { "type": "kv", "accessor": resp.Data["prod/secret/"].(map[string]interface{})["accessor"], "config": map[string]interface{}{ - "default_lease_ttl": resp.Data["identity/"].(map[string]interface{})["config"].(map[string]interface{})["default_lease_ttl"].(int64), - "max_lease_ttl": resp.Data["identity/"].(map[string]interface{})["config"].(map[string]interface{})["max_lease_ttl"].(int64), + "default_lease_ttl": int64(2100), + "max_lease_ttl": int64(2700), "plugin_name": "", "force_no_cache": false, }, @@ -1244,6 +1248,10 @@ func TestSystemBackend_enableAuth(t *testing.T) { req := logical.TestRequest(t, logical.UpdateOperation, "auth/foo") req.Data["type"] = "noop" + req.Data["config"] = map[string]interface{}{ + "default_lease_ttl": "35m", + "max_lease_ttl": "45m", + } req.Data["local"] = true req.Data["seal_wrap"] = true @@ -1270,8 +1278,8 @@ func TestSystemBackend_enableAuth(t *testing.T) { "description": "", "accessor": resp.Data["foo/"].(map[string]interface{})["accessor"], "config": map[string]interface{}{ - "default_lease_ttl": int64(0), - "max_lease_ttl": int64(0), + "default_lease_ttl": int64(2100), + "max_lease_ttl": int64(2700), }, "local": true, "seal_wrap": true,