diff --git a/api/sys_auth.go b/api/sys_auth.go index 9e26da39b..6521b9ee0 100644 --- a/api/sys_auth.go +++ b/api/sys_auth.go @@ -82,12 +82,13 @@ func (c *Sys) DisableAuth(path string) error { // documentation. Please refer to that documentation for more details. type EnableAuthOptions struct { - Type string `json:"type" structs:"type"` - Description string `json:"description" structs:"description"` - Config AuthConfigInput `json:"config" structs:"config"` - Local bool `json:"local" structs:"local"` - PluginName string `json:"plugin_name,omitempty" structs:"plugin_name,omitempty"` - SealWrap bool `json:"seal_wrap" structs:"seal_wrap" mapstructure:"seal_wrap"` + Type string `json:"type" structs:"type"` + Description string `json:"description" structs:"description"` + Config AuthConfigInput `json:"config" structs:"config"` + Local bool `json:"local" structs:"local"` + PluginName string `json:"plugin_name,omitempty" structs:"plugin_name,omitempty"` + SealWrap bool `json:"seal_wrap" structs:"seal_wrap" mapstructure:"seal_wrap"` + Options map[string]string `json:"options" structs:"options" mapstructure:"options"` } type AuthConfigInput struct { @@ -100,12 +101,13 @@ type AuthConfigInput struct { } type AuthMount struct { - Type string `json:"type" structs:"type" mapstructure:"type"` - Description string `json:"description" structs:"description" mapstructure:"description"` - Accessor string `json:"accessor" structs:"accessor" mapstructure:"accessor"` - Config AuthConfigOutput `json:"config" structs:"config" mapstructure:"config"` - Local bool `json:"local" structs:"local" mapstructure:"local"` - SealWrap bool `json:"seal_wrap" structs:"seal_wrap" mapstructure:"seal_wrap"` + Type string `json:"type" structs:"type" mapstructure:"type"` + Description string `json:"description" structs:"description" mapstructure:"description"` + Accessor string `json:"accessor" structs:"accessor" mapstructure:"accessor"` + Config AuthConfigOutput `json:"config" structs:"config" mapstructure:"config"` + Local bool `json:"local" structs:"local" mapstructure:"local"` + SealWrap bool `json:"seal_wrap" structs:"seal_wrap" mapstructure:"seal_wrap"` + Options map[string]string `json:"options" structs:"options" mapstructure:"options"` } type AuthConfigOutput struct { diff --git a/api/sys_mounts.go b/api/sys_mounts.go index 3efcc3b21..bcb9637a6 100644 --- a/api/sys_mounts.go +++ b/api/sys_mounts.go @@ -120,22 +120,24 @@ func (c *Sys) MountConfig(path string) (*MountConfigOutput, error) { } type MountInput struct { - Type string `json:"type" structs:"type"` - Description string `json:"description" structs:"description"` - Config MountConfigInput `json:"config" structs:"config"` - Local bool `json:"local" structs:"local"` - PluginName string `json:"plugin_name,omitempty" structs:"plugin_name"` - SealWrap bool `json:"seal_wrap" structs:"seal_wrap" mapstructure:"seal_wrap"` + Type string `json:"type" structs:"type"` + Description string `json:"description" structs:"description"` + Config MountConfigInput `json:"config" structs:"config"` + Options map[string]string `json:"options" structs:"options"` + Local bool `json:"local" structs:"local"` + PluginName string `json:"plugin_name,omitempty" structs:"plugin_name"` + SealWrap bool `json:"seal_wrap" structs:"seal_wrap" mapstructure:"seal_wrap"` } type MountConfigInput struct { - 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"` - ForceNoCache bool `json:"force_no_cache" structs:"force_no_cache" mapstructure:"force_no_cache"` - PluginName string `json:"plugin_name,omitempty" structs:"plugin_name,omitempty" mapstructure:"plugin_name"` - AuditNonHMACRequestKeys []string `json:"audit_non_hmac_request_keys,omitempty" structs:"audit_non_hmac_request_keys" mapstructure:"audit_non_hmac_request_keys"` - AuditNonHMACResponseKeys []string `json:"audit_non_hmac_response_keys,omitempty" structs:"audit_non_hmac_response_keys" mapstructure:"audit_non_hmac_response_keys"` - ListingVisibility string `json:"listing_visibility,omitempty" structs:"listing_visibility" mapstructure:"listing_visibility"` + Options map[string]string `json:"options" structs:"options" mapstructure:"options"` + 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"` + ForceNoCache bool `json:"force_no_cache" structs:"force_no_cache" mapstructure:"force_no_cache"` + PluginName string `json:"plugin_name,omitempty" structs:"plugin_name,omitempty" mapstructure:"plugin_name"` + AuditNonHMACRequestKeys []string `json:"audit_non_hmac_request_keys,omitempty" structs:"audit_non_hmac_request_keys" mapstructure:"audit_non_hmac_request_keys"` + AuditNonHMACResponseKeys []string `json:"audit_non_hmac_response_keys,omitempty" structs:"audit_non_hmac_response_keys" mapstructure:"audit_non_hmac_response_keys"` + ListingVisibility string `json:"listing_visibility,omitempty" structs:"listing_visibility" mapstructure:"listing_visibility"` } type MountOutput struct { @@ -143,16 +145,18 @@ type MountOutput struct { Description string `json:"description" structs:"description"` Accessor string `json:"accessor" structs:"accessor"` Config MountConfigOutput `json:"config" structs:"config"` + Options map[string]string `json:"options" structs:"options"` Local bool `json:"local" structs:"local"` SealWrap bool `json:"seal_wrap" structs:"seal_wrap" mapstructure:"seal_wrap"` } type MountConfigOutput struct { - DefaultLeaseTTL int `json:"default_lease_ttl" structs:"default_lease_ttl" mapstructure:"default_lease_ttl"` - MaxLeaseTTL int `json:"max_lease_ttl" structs:"max_lease_ttl" mapstructure:"max_lease_ttl"` - ForceNoCache bool `json:"force_no_cache" structs:"force_no_cache" mapstructure:"force_no_cache"` - PluginName string `json:"plugin_name,omitempty" structs:"plugin_name,omitempty" mapstructure:"plugin_name"` - AuditNonHMACRequestKeys []string `json:"audit_non_hmac_request_keys,omitempty" structs:"audit_non_hmac_request_keys" mapstructure:"audit_non_hmac_request_keys"` - AuditNonHMACResponseKeys []string `json:"audit_non_hmac_response_keys,omitempty" structs:"audit_non_hmac_response_keys" mapstructure:"audit_non_hmac_response_keys"` - ListingVisibility string `json:"listing_visibility,omitempty" structs:"listing_visibility" mapstructure:"listing_visibility"` + Options map[string]string `json:"options" structs:"options" mapstructure:"options"` + DefaultLeaseTTL int `json:"default_lease_ttl" structs:"default_lease_ttl" mapstructure:"default_lease_ttl"` + MaxLeaseTTL int `json:"max_lease_ttl" structs:"max_lease_ttl" mapstructure:"max_lease_ttl"` + ForceNoCache bool `json:"force_no_cache" structs:"force_no_cache" mapstructure:"force_no_cache"` + PluginName string `json:"plugin_name,omitempty" structs:"plugin_name,omitempty" mapstructure:"plugin_name"` + AuditNonHMACRequestKeys []string `json:"audit_non_hmac_request_keys,omitempty" structs:"audit_non_hmac_request_keys" mapstructure:"audit_non_hmac_request_keys"` + AuditNonHMACResponseKeys []string `json:"audit_non_hmac_response_keys,omitempty" structs:"audit_non_hmac_response_keys" mapstructure:"audit_non_hmac_response_keys"` + ListingVisibility string `json:"listing_visibility,omitempty" structs:"listing_visibility" mapstructure:"listing_visibility"` } diff --git a/command/auth_enable.go b/command/auth_enable.go index 0f556275b..48235933b 100644 --- a/command/auth_enable.go +++ b/command/auth_enable.go @@ -25,6 +25,7 @@ type AuthEnableCommand struct { flagAuditNonHMACResponseKeys []string flagListingVisibility string flagPluginName string + flagOptions map[string]string flagLocal bool flagSealWrap bool } @@ -128,6 +129,14 @@ func (c *AuthEnableCommand) Flags() *FlagSets { "exist in the Vault server's plugin catalog.", }) + f.StringMapVar(&StringMapVar{ + Name: "options", + Target: &c.flagOptions, + Completion: complete.PredictAnything, + Usage: "Key-value pair provided as key=value for the mount options. " + + "This can be specified multiple times", + }) + f.BoolVar(&BoolVar{ Name: "local", Target: &c.flagLocal, @@ -204,6 +213,7 @@ func (c *AuthEnableCommand) Run(args []string) int { MaxLeaseTTL: c.flagMaxLeaseTTL.String(), PluginName: c.flagPluginName, }, + Options: c.flagOptions, } // Set these values only if they are provided in the CLI diff --git a/command/auth_tune.go b/command/auth_tune.go index 2a96e1808..d0fa6ced2 100644 --- a/command/auth_tune.go +++ b/command/auth_tune.go @@ -17,6 +17,7 @@ var _ cli.CommandAutocomplete = (*AuthTuneCommand)(nil) type AuthTuneCommand struct { *BaseCommand + flagOptions map[string]string flagDefaultLeaseTTL time.Duration flagMaxLeaseTTL time.Duration flagAuditNonHMACRequestKeys []string @@ -50,6 +51,14 @@ func (c *AuthTuneCommand) Flags() *FlagSets { f := set.NewFlagSet("Command Options") + f.StringMapVar(&StringMapVar{ + Name: "options", + Target: &c.flagOptions, + Completion: complete.PredictAnything, + Usage: "Key-value pair provided as key=value for the mount options." + + "This can be specified multiple times", + }) + f.DurationVar(&DurationVar{ Name: "default-lease-ttl", Target: &c.flagDefaultLeaseTTL, @@ -128,6 +137,7 @@ func (c *AuthTuneCommand) Run(args []string) int { } mountConfigInput := api.MountConfigInput{ + Options: c.flagOptions, DefaultLeaseTTL: ttlToAPI(c.flagDefaultLeaseTTL), MaxLeaseTTL: ttlToAPI(c.flagMaxLeaseTTL), } diff --git a/command/secrets_enable.go b/command/secrets_enable.go index ab0ba8dea..95478380e 100644 --- a/command/secrets_enable.go +++ b/command/secrets_enable.go @@ -26,6 +26,7 @@ type SecretsEnableCommand struct { flagListingVisibility string flagForceNoCache bool flagPluginName string + flagOptions map[string]string flagLocal bool flagSealWrap bool } @@ -145,6 +146,14 @@ func (c *SecretsEnableCommand) Flags() *FlagSets { "exist in Vault's plugin catalog.", }) + f.StringMapVar(&StringMapVar{ + Name: "options", + Target: &c.flagOptions, + Completion: complete.PredictAnything, + Usage: "Key-value pair provided as key=value for the mount options." + + "This can be specified multiple times", + }) + f.BoolVar(&BoolVar{ Name: "local", Target: &c.flagLocal, @@ -224,6 +233,7 @@ func (c *SecretsEnableCommand) Run(args []string) int { ForceNoCache: c.flagForceNoCache, PluginName: c.flagPluginName, }, + Options: c.flagOptions, } // Set these values only if they are provided in the CLI diff --git a/command/secrets_tune.go b/command/secrets_tune.go index 5e96ad113..5e97d78b8 100644 --- a/command/secrets_tune.go +++ b/command/secrets_tune.go @@ -17,6 +17,7 @@ var _ cli.CommandAutocomplete = (*SecretsTuneCommand)(nil) type SecretsTuneCommand struct { *BaseCommand + flagOptions map[string]string flagDefaultLeaseTTL time.Duration flagMaxLeaseTTL time.Duration flagAuditNonHMACRequestKeys []string @@ -50,6 +51,14 @@ func (c *SecretsTuneCommand) Flags() *FlagSets { f := set.NewFlagSet("Command Options") + f.StringMapVar(&StringMapVar{ + Name: "options", + Target: &c.flagOptions, + Completion: complete.PredictAnything, + Usage: "Key-value pair provided as key=value for the mount options." + + "This can be specified multiple times", + }) + f.DurationVar(&DurationVar{ Name: "default-lease-ttl", Target: &c.flagDefaultLeaseTTL, @@ -131,6 +140,7 @@ func (c *SecretsTuneCommand) Run(args []string) int { mountPath := ensureTrailingSlash(sanitizePath(args[0])) mountConfigInput := api.MountConfigInput{ + Options: c.flagOptions, DefaultLeaseTTL: ttlToAPI(c.flagDefaultLeaseTTL), MaxLeaseTTL: ttlToAPI(c.flagMaxLeaseTTL), } diff --git a/helper/consts/consts.go b/helper/consts/consts.go index eee59d9c9..6c9558aa6 100644 --- a/helper/consts/consts.go +++ b/helper/consts/consts.go @@ -4,4 +4,6 @@ const ( // ExpirationRestoreWorkerCount specifies the number of workers to use while // restoring leases into the expiration manager ExpirationRestoreWorkerCount = 64 + + VaultKVCLIClientHeader = "X-Vault-Kv-Client" ) diff --git a/http/handler_test.go b/http/handler_test.go index 86265d7ea..73e506d4b 100644 --- a/http/handler_test.go +++ b/http/handler_test.go @@ -168,6 +168,7 @@ func TestSysMounts_headerAuth(t *testing.T) { }, "local": false, "seal_wrap": false, + "options": map[string]interface{}{"versioned": "true"}, }, "sys/": map[string]interface{}{ "description": "system endpoints used for control, policy and debugging", @@ -180,6 +181,7 @@ func TestSysMounts_headerAuth(t *testing.T) { }, "local": false, "seal_wrap": false, + "options": interface{}(nil), }, "cubbyhole/": map[string]interface{}{ "description": "per-token private secret storage", @@ -192,6 +194,7 @@ func TestSysMounts_headerAuth(t *testing.T) { }, "local": true, "seal_wrap": false, + "options": interface{}(nil), }, "identity/": map[string]interface{}{ "description": "identity store", @@ -204,6 +207,7 @@ func TestSysMounts_headerAuth(t *testing.T) { }, "local": false, "seal_wrap": false, + "options": interface{}(nil), }, }, "secret/": map[string]interface{}{ @@ -217,6 +221,7 @@ func TestSysMounts_headerAuth(t *testing.T) { }, "local": false, "seal_wrap": false, + "options": map[string]interface{}{"versioned": "true"}, }, "sys/": map[string]interface{}{ "description": "system endpoints used for control, policy and debugging", @@ -229,6 +234,7 @@ func TestSysMounts_headerAuth(t *testing.T) { }, "local": false, "seal_wrap": false, + "options": interface{}(nil), }, "cubbyhole/": map[string]interface{}{ "description": "per-token private secret storage", @@ -241,6 +247,7 @@ func TestSysMounts_headerAuth(t *testing.T) { }, "local": true, "seal_wrap": false, + "options": interface{}(nil), }, "identity/": map[string]interface{}{ "description": "identity store", @@ -253,6 +260,7 @@ func TestSysMounts_headerAuth(t *testing.T) { }, "local": false, "seal_wrap": false, + "options": interface{}(nil), }, } testResponseStatus(t, resp, 200) diff --git a/http/sys_auth_test.go b/http/sys_auth_test.go index 46c6d3653..01e135b59 100644 --- a/http/sys_auth_test.go +++ b/http/sys_auth_test.go @@ -35,6 +35,7 @@ func TestSysAuth(t *testing.T) { }, "local": false, "seal_wrap": false, + "options": interface{}(nil), }, }, "token/": map[string]interface{}{ @@ -47,6 +48,7 @@ func TestSysAuth(t *testing.T) { }, "local": false, "seal_wrap": false, + "options": interface{}(nil), }, } testResponseStatus(t, resp, 200) @@ -99,6 +101,7 @@ func TestSysEnableAuth(t *testing.T) { }, "local": false, "seal_wrap": false, + "options": map[string]interface{}{}, }, "token/": map[string]interface{}{ "description": "token based credentials", @@ -110,6 +113,7 @@ func TestSysEnableAuth(t *testing.T) { }, "local": false, "seal_wrap": false, + "options": interface{}(nil), }, }, "foo/": map[string]interface{}{ @@ -122,6 +126,7 @@ func TestSysEnableAuth(t *testing.T) { }, "local": false, "seal_wrap": false, + "options": map[string]interface{}{}, }, "token/": map[string]interface{}{ "description": "token based credentials", @@ -133,6 +138,7 @@ func TestSysEnableAuth(t *testing.T) { }, "local": false, "seal_wrap": false, + "options": interface{}(nil), }, } testResponseStatus(t, resp, 200) @@ -188,6 +194,7 @@ func TestSysDisableAuth(t *testing.T) { "type": "token", "local": false, "seal_wrap": false, + "options": interface{}(nil), }, }, "token/": map[string]interface{}{ @@ -200,6 +207,7 @@ func TestSysDisableAuth(t *testing.T) { "type": "token", "local": false, "seal_wrap": false, + "options": interface{}(nil), }, } testResponseStatus(t, resp, 200) diff --git a/http/sys_mount_test.go b/http/sys_mount_test.go index bcf472228..caa636707 100644 --- a/http/sys_mount_test.go +++ b/http/sys_mount_test.go @@ -37,6 +37,7 @@ func TestSysMounts(t *testing.T) { }, "local": false, "seal_wrap": false, + "options": map[string]interface{}{"versioned": "true"}, }, "sys/": map[string]interface{}{ "description": "system endpoints used for control, policy and debugging", @@ -49,6 +50,7 @@ func TestSysMounts(t *testing.T) { }, "local": false, "seal_wrap": false, + "options": interface{}(nil), }, "cubbyhole/": map[string]interface{}{ "description": "per-token private secret storage", @@ -61,6 +63,7 @@ func TestSysMounts(t *testing.T) { }, "local": true, "seal_wrap": false, + "options": interface{}(nil), }, "identity/": map[string]interface{}{ "description": "identity store", @@ -73,6 +76,7 @@ func TestSysMounts(t *testing.T) { }, "local": false, "seal_wrap": false, + "options": interface{}(nil), }, }, "secret/": map[string]interface{}{ @@ -86,6 +90,7 @@ func TestSysMounts(t *testing.T) { }, "local": false, "seal_wrap": false, + "options": map[string]interface{}{"versioned": "true"}, }, "sys/": map[string]interface{}{ "description": "system endpoints used for control, policy and debugging", @@ -98,6 +103,7 @@ func TestSysMounts(t *testing.T) { }, "local": false, "seal_wrap": false, + "options": interface{}(nil), }, "cubbyhole/": map[string]interface{}{ "description": "per-token private secret storage", @@ -110,6 +116,7 @@ func TestSysMounts(t *testing.T) { }, "local": true, "seal_wrap": false, + "options": interface{}(nil), }, "identity/": map[string]interface{}{ "description": "identity store", @@ -122,6 +129,7 @@ func TestSysMounts(t *testing.T) { }, "local": false, "seal_wrap": false, + "options": interface{}(nil), }, } testResponseStatus(t, resp, 200) @@ -149,6 +157,9 @@ func TestSysMount(t *testing.T) { resp := testHttpPost(t, token, addr+"/v1/sys/mounts/foo", map[string]interface{}{ "type": "kv", "description": "foo", + "options": map[string]string{ + "versioned": "true", + }, }) testResponseStatus(t, resp, 204) @@ -174,6 +185,7 @@ func TestSysMount(t *testing.T) { }, "local": false, "seal_wrap": false, + "options": map[string]interface{}{"versioned": "true"}, }, "secret/": map[string]interface{}{ "description": "key/value secret storage", @@ -186,6 +198,7 @@ func TestSysMount(t *testing.T) { }, "local": false, "seal_wrap": false, + "options": map[string]interface{}{"versioned": "true"}, }, "sys/": map[string]interface{}{ "description": "system endpoints used for control, policy and debugging", @@ -198,6 +211,7 @@ func TestSysMount(t *testing.T) { }, "local": false, "seal_wrap": false, + "options": interface{}(nil), }, "cubbyhole/": map[string]interface{}{ "description": "per-token private secret storage", @@ -210,6 +224,7 @@ func TestSysMount(t *testing.T) { }, "local": true, "seal_wrap": false, + "options": interface{}(nil), }, "identity/": map[string]interface{}{ "description": "identity store", @@ -222,6 +237,7 @@ func TestSysMount(t *testing.T) { }, "local": false, "seal_wrap": false, + "options": interface{}(nil), }, }, "foo/": map[string]interface{}{ @@ -235,6 +251,7 @@ func TestSysMount(t *testing.T) { }, "local": false, "seal_wrap": false, + "options": map[string]interface{}{"versioned": "true"}, }, "secret/": map[string]interface{}{ "description": "key/value secret storage", @@ -247,6 +264,7 @@ func TestSysMount(t *testing.T) { }, "local": false, "seal_wrap": false, + "options": map[string]interface{}{"versioned": "true"}, }, "sys/": map[string]interface{}{ "description": "system endpoints used for control, policy and debugging", @@ -259,6 +277,7 @@ func TestSysMount(t *testing.T) { }, "local": false, "seal_wrap": false, + "options": interface{}(nil), }, "cubbyhole/": map[string]interface{}{ "description": "per-token private secret storage", @@ -271,6 +290,7 @@ func TestSysMount(t *testing.T) { }, "local": true, "seal_wrap": false, + "options": interface{}(nil), }, "identity/": map[string]interface{}{ "description": "identity store", @@ -283,6 +303,7 @@ func TestSysMount(t *testing.T) { }, "local": false, "seal_wrap": false, + "options": interface{}(nil), }, } testResponseStatus(t, resp, 200) @@ -357,6 +378,7 @@ func TestSysRemount(t *testing.T) { }, "local": false, "seal_wrap": false, + "options": map[string]interface{}{}, }, "secret/": map[string]interface{}{ "description": "key/value secret storage", @@ -369,6 +391,7 @@ func TestSysRemount(t *testing.T) { }, "local": false, "seal_wrap": false, + "options": map[string]interface{}{"versioned": "true"}, }, "sys/": map[string]interface{}{ "description": "system endpoints used for control, policy and debugging", @@ -381,6 +404,7 @@ func TestSysRemount(t *testing.T) { }, "local": false, "seal_wrap": false, + "options": interface{}(nil), }, "cubbyhole/": map[string]interface{}{ "description": "per-token private secret storage", @@ -393,6 +417,7 @@ func TestSysRemount(t *testing.T) { }, "local": true, "seal_wrap": false, + "options": interface{}(nil), }, "identity/": map[string]interface{}{ "description": "identity store", @@ -405,6 +430,7 @@ func TestSysRemount(t *testing.T) { }, "local": false, "seal_wrap": false, + "options": interface{}(nil), }, }, "bar/": map[string]interface{}{ @@ -418,6 +444,7 @@ func TestSysRemount(t *testing.T) { }, "local": false, "seal_wrap": false, + "options": map[string]interface{}{}, }, "secret/": map[string]interface{}{ "description": "key/value secret storage", @@ -430,6 +457,7 @@ func TestSysRemount(t *testing.T) { }, "local": false, "seal_wrap": false, + "options": map[string]interface{}{"versioned": "true"}, }, "sys/": map[string]interface{}{ "description": "system endpoints used for control, policy and debugging", @@ -442,6 +470,7 @@ func TestSysRemount(t *testing.T) { }, "local": false, "seal_wrap": false, + "options": interface{}(nil), }, "cubbyhole/": map[string]interface{}{ "description": "per-token private secret storage", @@ -454,6 +483,7 @@ func TestSysRemount(t *testing.T) { }, "local": true, "seal_wrap": false, + "options": interface{}(nil), }, "identity/": map[string]interface{}{ "description": "identity store", @@ -466,6 +496,7 @@ func TestSysRemount(t *testing.T) { }, "local": false, "seal_wrap": false, + "options": interface{}(nil), }, } testResponseStatus(t, resp, 200) @@ -521,6 +552,7 @@ func TestSysUnmount(t *testing.T) { }, "local": false, "seal_wrap": false, + "options": map[string]interface{}{"versioned": "true"}, }, "sys/": map[string]interface{}{ "description": "system endpoints used for control, policy and debugging", @@ -533,6 +565,7 @@ func TestSysUnmount(t *testing.T) { }, "local": false, "seal_wrap": false, + "options": interface{}(nil), }, "cubbyhole/": map[string]interface{}{ "description": "per-token private secret storage", @@ -545,6 +578,7 @@ func TestSysUnmount(t *testing.T) { }, "local": true, "seal_wrap": false, + "options": interface{}(nil), }, "identity/": map[string]interface{}{ "description": "identity store", @@ -557,6 +591,7 @@ func TestSysUnmount(t *testing.T) { }, "local": false, "seal_wrap": false, + "options": interface{}(nil), }, }, "secret/": map[string]interface{}{ @@ -570,6 +605,7 @@ func TestSysUnmount(t *testing.T) { }, "local": false, "seal_wrap": false, + "options": map[string]interface{}{"versioned": "true"}, }, "sys/": map[string]interface{}{ "description": "system endpoints used for control, policy and debugging", @@ -582,6 +618,7 @@ func TestSysUnmount(t *testing.T) { }, "local": false, "seal_wrap": false, + "options": interface{}(nil), }, "cubbyhole/": map[string]interface{}{ "description": "per-token private secret storage", @@ -594,6 +631,7 @@ func TestSysUnmount(t *testing.T) { }, "local": true, "seal_wrap": false, + "options": interface{}(nil), }, "identity/": map[string]interface{}{ "description": "identity store", @@ -606,6 +644,7 @@ func TestSysUnmount(t *testing.T) { }, "local": false, "seal_wrap": false, + "options": interface{}(nil), }, } testResponseStatus(t, resp, 200) @@ -624,6 +663,89 @@ func TestSysUnmount(t *testing.T) { } } +func TestSysTuneMount_Options(t *testing.T) { + core, _, token := vault.TestCoreUnsealed(t) + ln, addr := TestServer(t, core) + defer ln.Close() + TestServerAuth(t, addr, token) + + resp := testHttpPost(t, token, addr+"/v1/sys/mounts/foo", map[string]interface{}{ + "type": "kv", + "description": "foo", + }) + + testResponseStatus(t, resp, 204) + // Mount-tune the options + resp = testHttpPost(t, token, addr+"/v1/sys/mounts/foo/tune", map[string]interface{}{ + "options": map[string]string{ + "test": "true", + }, + }) + testResponseStatus(t, resp, 204) + + // Check results + resp = testHttpGet(t, token, addr+"/v1/sys/mounts/foo/tune") + testResponseStatus(t, resp, 200) + + actual := map[string]interface{}{} + expected := map[string]interface{}{ + "lease_id": "", + "renewable": false, + "lease_duration": json.Number("0"), + "wrap_info": nil, + "warnings": nil, + "auth": nil, + "data": map[string]interface{}{ + "default_lease_ttl": json.Number("2764800"), + "max_lease_ttl": json.Number("2764800"), + "force_no_cache": false, + "options": map[string]interface{}{"test": "true"}, + }, + "default_lease_ttl": json.Number("2764800"), + "max_lease_ttl": json.Number("2764800"), + "force_no_cache": false, + "options": map[string]interface{}{"test": "true"}, + } + testResponseBody(t, resp, &actual) + expected["request_id"] = actual["request_id"] + if !reflect.DeepEqual(actual, expected) { + t.Fatalf("bad:\nExpected: %#v\nActual:%#v", expected, actual) + } + + // Unset the mount tune value + resp = testHttpPost(t, token, addr+"/v1/sys/mounts/foo/tune", map[string]interface{}{ + "options": map[string]string{}, + }) + testResponseStatus(t, resp, 204) + + // Check results + resp = testHttpGet(t, token, addr+"/v1/sys/mounts/foo/tune") + testResponseStatus(t, resp, 200) + + actual = map[string]interface{}{} + expected = map[string]interface{}{ + "lease_id": "", + "renewable": false, + "lease_duration": json.Number("0"), + "wrap_info": nil, + "warnings": nil, + "auth": nil, + "data": map[string]interface{}{ + "default_lease_ttl": json.Number("2764800"), + "max_lease_ttl": json.Number("2764800"), + "force_no_cache": false, + }, + "default_lease_ttl": json.Number("2764800"), + "max_lease_ttl": json.Number("2764800"), + "force_no_cache": false, + } + testResponseBody(t, resp, &actual) + expected["request_id"] = actual["request_id"] + if !reflect.DeepEqual(actual, expected) { + t.Fatalf("bad:\nExpected: %#v\nActual:%#v", expected, actual) + } +} + func TestSysTuneMount(t *testing.T) { core, _, token := vault.TestCoreUnsealed(t) ln, addr := TestServer(t, core) @@ -658,6 +780,7 @@ func TestSysTuneMount(t *testing.T) { }, "local": false, "seal_wrap": false, + "options": map[string]interface{}{}, }, "secret/": map[string]interface{}{ "description": "key/value secret storage", @@ -670,6 +793,7 @@ func TestSysTuneMount(t *testing.T) { }, "local": false, "seal_wrap": false, + "options": map[string]interface{}{"versioned": "true"}, }, "sys/": map[string]interface{}{ "description": "system endpoints used for control, policy and debugging", @@ -682,6 +806,7 @@ func TestSysTuneMount(t *testing.T) { }, "local": false, "seal_wrap": false, + "options": interface{}(nil), }, "cubbyhole/": map[string]interface{}{ "description": "per-token private secret storage", @@ -694,6 +819,7 @@ func TestSysTuneMount(t *testing.T) { }, "local": true, "seal_wrap": false, + "options": interface{}(nil), }, "identity/": map[string]interface{}{ "description": "identity store", @@ -706,6 +832,7 @@ func TestSysTuneMount(t *testing.T) { }, "local": false, "seal_wrap": false, + "options": interface{}(nil), }, }, "foo/": map[string]interface{}{ @@ -719,6 +846,7 @@ func TestSysTuneMount(t *testing.T) { }, "local": false, "seal_wrap": false, + "options": map[string]interface{}{}, }, "secret/": map[string]interface{}{ "description": "key/value secret storage", @@ -731,6 +859,7 @@ func TestSysTuneMount(t *testing.T) { }, "local": false, "seal_wrap": false, + "options": map[string]interface{}{"versioned": "true"}, }, "sys/": map[string]interface{}{ "description": "system endpoints used for control, policy and debugging", @@ -743,6 +872,7 @@ func TestSysTuneMount(t *testing.T) { }, "local": false, "seal_wrap": false, + "options": interface{}(nil), }, "cubbyhole/": map[string]interface{}{ "description": "per-token private secret storage", @@ -755,6 +885,7 @@ func TestSysTuneMount(t *testing.T) { }, "local": true, "seal_wrap": false, + "options": interface{}(nil), }, "identity/": map[string]interface{}{ "description": "identity store", @@ -767,6 +898,7 @@ func TestSysTuneMount(t *testing.T) { }, "local": false, "seal_wrap": false, + "options": interface{}(nil), }, } testResponseStatus(t, resp, 200) @@ -820,6 +952,14 @@ func TestSysTuneMount(t *testing.T) { }) testResponseStatus(t, resp, 204) + // mark as versioned + resp = testHttpPost(t, token, addr+"/v1/sys/mounts/foo/tune", map[string]interface{}{ + "options": map[string]string{ + "versioned": "true", + }, + }) + testResponseStatus(t, resp, 200) + resp = testHttpGet(t, token, addr+"/v1/sys/mounts") expected = map[string]interface{}{ "lease_id": "", @@ -840,6 +980,7 @@ func TestSysTuneMount(t *testing.T) { }, "local": false, "seal_wrap": false, + "options": map[string]interface{}{"versioned": "true"}, }, "secret/": map[string]interface{}{ "description": "key/value secret storage", @@ -852,6 +993,7 @@ func TestSysTuneMount(t *testing.T) { }, "local": false, "seal_wrap": false, + "options": map[string]interface{}{"versioned": "true"}, }, "sys/": map[string]interface{}{ "description": "system endpoints used for control, policy and debugging", @@ -864,6 +1006,7 @@ func TestSysTuneMount(t *testing.T) { }, "local": false, "seal_wrap": false, + "options": interface{}(nil), }, "cubbyhole/": map[string]interface{}{ "description": "per-token private secret storage", @@ -876,6 +1019,7 @@ func TestSysTuneMount(t *testing.T) { }, "local": true, "seal_wrap": false, + "options": interface{}(nil), }, "identity/": map[string]interface{}{ "description": "identity store", @@ -888,6 +1032,7 @@ func TestSysTuneMount(t *testing.T) { }, "local": false, "seal_wrap": false, + "options": interface{}(nil), }, }, "foo/": map[string]interface{}{ @@ -901,6 +1046,7 @@ func TestSysTuneMount(t *testing.T) { }, "local": false, "seal_wrap": false, + "options": map[string]interface{}{"versioned": "true"}, }, "secret/": map[string]interface{}{ "description": "key/value secret storage", @@ -913,6 +1059,7 @@ func TestSysTuneMount(t *testing.T) { }, "local": false, "seal_wrap": false, + "options": map[string]interface{}{"versioned": "true"}, }, "sys/": map[string]interface{}{ "description": "system endpoints used for control, policy and debugging", @@ -925,6 +1072,7 @@ func TestSysTuneMount(t *testing.T) { }, "local": false, "seal_wrap": false, + "options": interface{}(nil), }, "cubbyhole/": map[string]interface{}{ "description": "per-token private secret storage", @@ -937,6 +1085,7 @@ func TestSysTuneMount(t *testing.T) { }, "local": true, "seal_wrap": false, + "options": interface{}(nil), }, "identity/": map[string]interface{}{ "description": "identity store", @@ -949,6 +1098,7 @@ func TestSysTuneMount(t *testing.T) { }, "local": false, "seal_wrap": false, + "options": interface{}(nil), }, } @@ -981,10 +1131,12 @@ func TestSysTuneMount(t *testing.T) { "default_lease_ttl": json.Number("259196400"), "max_lease_ttl": json.Number("259200000"), "force_no_cache": false, + "options": map[string]interface{}{"versioned": "true"}, }, "default_lease_ttl": json.Number("259196400"), "max_lease_ttl": json.Number("259200000"), "force_no_cache": false, + "options": map[string]interface{}{"versioned": "true"}, } testResponseStatus(t, resp, 200) @@ -1014,10 +1166,12 @@ func TestSysTuneMount(t *testing.T) { "default_lease_ttl": json.Number("40"), "max_lease_ttl": json.Number("80"), "force_no_cache": false, + "options": map[string]interface{}{"versioned": "true"}, }, "default_lease_ttl": json.Number("40"), "max_lease_ttl": json.Number("80"), "force_no_cache": false, + "options": map[string]interface{}{"versioned": "true"}, } testResponseStatus(t, resp, 200) @@ -1109,12 +1263,14 @@ func TestSysTuneMount_nonHMACKeys(t *testing.T) { "force_no_cache": false, "audit_non_hmac_request_keys": []interface{}{"foo"}, "audit_non_hmac_response_keys": []interface{}{"bar"}, + "options": map[string]interface{}{"versioned": "true"}, }, "default_lease_ttl": json.Number("2764800"), "max_lease_ttl": json.Number("2764800"), "force_no_cache": false, "audit_non_hmac_request_keys": []interface{}{"foo"}, "audit_non_hmac_response_keys": []interface{}{"bar"}, + "options": map[string]interface{}{"versioned": "true"}, } testResponseBody(t, resp, &actual) expected["request_id"] = actual["request_id"] @@ -1148,10 +1304,12 @@ func TestSysTuneMount_nonHMACKeys(t *testing.T) { "default_lease_ttl": json.Number("2764800"), "max_lease_ttl": json.Number("2764800"), "force_no_cache": false, + "options": map[string]interface{}{"versioned": "true"}, }, "default_lease_ttl": json.Number("2764800"), "max_lease_ttl": json.Number("2764800"), "force_no_cache": false, + "options": map[string]interface{}{"versioned": "true"}, } testResponseBody(t, resp, &actual) expected["request_id"] = actual["request_id"] @@ -1182,10 +1340,12 @@ func TestSysTuneMount_showUIMount(t *testing.T) { "default_lease_ttl": json.Number("2764800"), "max_lease_ttl": json.Number("2764800"), "force_no_cache": false, + "options": map[string]interface{}{"versioned": "true"}, }, "default_lease_ttl": json.Number("2764800"), "max_lease_ttl": json.Number("2764800"), "force_no_cache": false, + "options": map[string]interface{}{"versioned": "true"}, } testResponseBody(t, resp, &actual) expected["request_id"] = actual["request_id"] @@ -1216,11 +1376,13 @@ func TestSysTuneMount_showUIMount(t *testing.T) { "max_lease_ttl": json.Number("2764800"), "force_no_cache": false, "listing_visibility": "unauth", + "options": map[string]interface{}{"versioned": "true"}, }, "default_lease_ttl": json.Number("2764800"), "max_lease_ttl": json.Number("2764800"), "force_no_cache": false, "listing_visibility": "unauth", + "options": map[string]interface{}{"versioned": "true"}, } testResponseBody(t, resp, &actual) expected["request_id"] = actual["request_id"] diff --git a/logical/logical.go b/logical/logical.go index 8f945e279..6ac40ab7b 100644 --- a/logical/logical.go +++ b/logical/logical.go @@ -96,6 +96,10 @@ type BackendConfig struct { // is useful for backends, such as the default/max lease TTLs System SystemView + // BackendUUID is a unique identifier provided to this backend. It's useful + // when a backend needs a consistent and unique string without using storage. + BackendUUID string + // Config is the opaque user configuration provided when mounting Config map[string]string } diff --git a/logical/plugin/backend_client.go b/logical/plugin/backend_client.go index a639ebd24..8f03e956e 100644 --- a/logical/plugin/backend_client.go +++ b/logical/plugin/backend_client.go @@ -63,10 +63,11 @@ type HandleExistenceCheckReply struct { // SetupArgs is the args for Setup method. type SetupArgs struct { - StorageID uint32 - LoggerID uint32 - SysViewID uint32 - Config map[string]string + StorageID uint32 + LoggerID uint32 + SysViewID uint32 + Config map[string]string + BackendUUID string } // SetupReply is the reply for Setup method. @@ -224,10 +225,11 @@ func (b *backendPluginClient) Setup(ctx context.Context, config *logical.Backend }) args := &SetupArgs{ - StorageID: storageID, - LoggerID: loggerID, - SysViewID: sysViewID, - Config: config.Config, + StorageID: storageID, + LoggerID: loggerID, + SysViewID: sysViewID, + Config: config.Config, + BackendUUID: config.BackendUUID, } var reply SetupReply diff --git a/logical/plugin/backend_server.go b/logical/plugin/backend_server.go index e2cff35d0..db88ea208 100644 --- a/logical/plugin/backend_server.go +++ b/logical/plugin/backend_server.go @@ -140,6 +140,7 @@ func (b *backendPluginServer) Setup(args *SetupArgs, reply *SetupReply) error { Logger: logger, System: sysView, Config: args.Config, + BackendUUID: args.BackendUUID, } // Call the underlying backend factory after shims have been created diff --git a/logical/plugin/grpc_backend_client.go b/logical/plugin/grpc_backend_client.go index c980f795b..a24893878 100644 --- a/logical/plugin/grpc_backend_client.go +++ b/logical/plugin/grpc_backend_client.go @@ -206,8 +206,9 @@ func (b *backendGRPCPluginClient) Setup(ctx context.Context, config *logical.Bac go b.broker.AcceptAndServe(brokerID, serverFunc) args := &pb.SetupArgs{ - BrokerID: brokerID, - Config: config.Config, + BrokerID: brokerID, + Config: config.Config, + BackendUUID: config.BackendUUID, } ctx, cancel := context.WithCancel(ctx) diff --git a/logical/plugin/grpc_backend_server.go b/logical/plugin/grpc_backend_server.go index 3e902e033..bb264f015 100644 --- a/logical/plugin/grpc_backend_server.go +++ b/logical/plugin/grpc_backend_server.go @@ -39,6 +39,7 @@ func (b *backendGRPCPluginServer) Setup(ctx context.Context, args *pb.SetupArgs) Logger: b.logger, System: sysView, Config: args.Config, + BackendUUID: args.BackendUUID, } // Call the underlying backend factory after shims have been created diff --git a/logical/plugin/pb/backend.pb.go b/logical/plugin/pb/backend.pb.go index 7cebdd539..e2a2a3116 100644 --- a/logical/plugin/pb/backend.pb.go +++ b/logical/plugin/pb/backend.pb.go @@ -983,8 +983,9 @@ func (m *HandleExistenceCheckReply) GetErr() *ProtoError { // SetupArgs is the args for Setup method. type SetupArgs struct { - BrokerID uint32 `sentinel:"" protobuf:"varint,1,opt,name=broker_id,json=brokerId" json:"broker_id,omitempty"` - Config map[string]string `sentinel:"" protobuf:"bytes,2,rep,name=Config" json:"Config,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + BrokerID uint32 `sentinel:"" protobuf:"varint,1,opt,name=broker_id,json=brokerId" json:"broker_id,omitempty"` + Config map[string]string `sentinel:"" protobuf:"bytes,2,rep,name=Config" json:"Config,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + BackendUUID string `sentinel:"" protobuf:"bytes,3,opt,name=backendUUID" json:"backendUUID,omitempty"` } func (m *SetupArgs) Reset() { *m = SetupArgs{} } @@ -1006,6 +1007,13 @@ func (m *SetupArgs) GetConfig() map[string]string { return nil } +func (m *SetupArgs) GetBackendUUID() string { + if m != nil { + return m.BackendUUID + } + return "" +} + // SetupReply is the reply for Setup method. type SetupReply struct { Err string `sentinel:"" protobuf:"bytes,1,opt,name=err" json:"err,omitempty"` @@ -2345,136 +2353,137 @@ var _SystemView_serviceDesc = grpc.ServiceDesc{ func init() { proto.RegisterFile("logical/plugin/pb/backend.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 2085 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x58, 0x5b, 0x73, 0xdb, 0xc6, - 0xf5, 0x1f, 0x92, 0x22, 0x09, 0x1e, 0x92, 0xba, 0xac, 0x65, 0xff, 0x21, 0xda, 0xf9, 0x8b, 0x45, - 0xc6, 0x0a, 0xe3, 0xa9, 0x29, 0x9b, 0xbd, 0x39, 0xed, 0x24, 0x1d, 0x55, 0x56, 0x1c, 0x35, 0x52, - 0xa2, 0x81, 0xd4, 0xa6, 0x9d, 0x76, 0x86, 0x59, 0x01, 0x47, 0x14, 0x46, 0x20, 0x80, 0x2e, 0x16, - 0x92, 0xf9, 0xd4, 0x6f, 0x91, 0x7e, 0x9c, 0xbe, 0x76, 0xa6, 0xcf, 0xfd, 0x04, 0x7d, 0xef, 0x43, - 0x3f, 0x41, 0x67, 0x2f, 0x00, 0x17, 0x24, 0x55, 0xbb, 0x33, 0xed, 0xdb, 0x9e, 0xcb, 0xee, 0xb9, - 0xe0, 0x9c, 0xdf, 0xd9, 0x05, 0xec, 0x86, 0xf1, 0x24, 0xf0, 0x68, 0xb8, 0x9f, 0x84, 0xd9, 0x24, - 0x88, 0xf6, 0x93, 0xcb, 0xfd, 0x4b, 0xea, 0xdd, 0x60, 0xe4, 0x0f, 0x13, 0x16, 0xf3, 0x98, 0x54, - 0x93, 0xcb, 0xde, 0xee, 0x24, 0x8e, 0x27, 0x21, 0xee, 0x4b, 0xce, 0x65, 0x76, 0xb5, 0xcf, 0x83, - 0x29, 0xa6, 0x9c, 0x4e, 0x13, 0xa5, 0xe4, 0x34, 0xa1, 0x7e, 0x34, 0x4d, 0xf8, 0xcc, 0xe9, 0x43, - 0xe3, 0x0b, 0xa4, 0x3e, 0x32, 0xf2, 0x08, 0x1a, 0xd7, 0x72, 0x65, 0x57, 0xfa, 0xb5, 0x41, 0xcb, - 0xd5, 0x94, 0xf3, 0x3b, 0x80, 0x33, 0xb1, 0xe7, 0x88, 0xb1, 0x98, 0x91, 0x1d, 0xb0, 0x90, 0xb1, - 0x31, 0x9f, 0x25, 0x68, 0x57, 0xfa, 0x95, 0x41, 0xd7, 0x6d, 0x22, 0x63, 0x17, 0xb3, 0x04, 0xc9, - 0xff, 0x81, 0x58, 0x8e, 0xa7, 0xe9, 0xc4, 0xae, 0xf6, 0x2b, 0xe2, 0x04, 0x64, 0xec, 0x34, 0x9d, - 0xe4, 0x7b, 0xbc, 0xd8, 0x47, 0xbb, 0xd6, 0xaf, 0x0c, 0x6a, 0x72, 0xcf, 0x61, 0xec, 0xa3, 0xf3, - 0x5d, 0x05, 0xea, 0x67, 0x94, 0x5f, 0xa7, 0x84, 0xc0, 0x1a, 0x8b, 0x63, 0xae, 0x8d, 0xcb, 0x35, - 0x19, 0xc0, 0x46, 0x16, 0xd1, 0x8c, 0x5f, 0x63, 0xc4, 0x03, 0x8f, 0x72, 0xf4, 0xed, 0xaa, 0x14, - 0x2f, 0xb2, 0xc9, 0x87, 0xd0, 0x0d, 0x63, 0x8f, 0x86, 0xe3, 0x94, 0xc7, 0x8c, 0x4e, 0x84, 0x1d, - 0xa1, 0xd7, 0x91, 0xcc, 0x73, 0xc5, 0x23, 0xcf, 0x60, 0x2b, 0x45, 0x1a, 0x8e, 0xef, 0x18, 0x4d, - 0x0a, 0xc5, 0x35, 0x75, 0xa0, 0x10, 0x7c, 0xc3, 0x68, 0xa2, 0x75, 0x9d, 0x3f, 0x37, 0xa0, 0xe9, - 0xe2, 0x1f, 0x32, 0x4c, 0x39, 0x59, 0x87, 0x6a, 0xe0, 0xcb, 0x68, 0x5b, 0x6e, 0x35, 0xf0, 0xc9, - 0x10, 0x88, 0x8b, 0x49, 0x28, 0x4c, 0x07, 0x71, 0x74, 0x18, 0x66, 0x29, 0x47, 0xa6, 0x63, 0x5e, - 0x21, 0x21, 0x4f, 0xa0, 0x15, 0x27, 0xc8, 0x24, 0x4f, 0x26, 0xa0, 0xe5, 0xce, 0x19, 0x22, 0xf0, - 0x84, 0xf2, 0x6b, 0x7b, 0x4d, 0x0a, 0xe4, 0x5a, 0xf0, 0x7c, 0xca, 0xa9, 0x5d, 0x57, 0x3c, 0xb1, - 0x26, 0x0e, 0x34, 0x52, 0xf4, 0x18, 0x72, 0xbb, 0xd1, 0xaf, 0x0c, 0xda, 0x23, 0x18, 0x26, 0x97, - 0xc3, 0x73, 0xc9, 0x71, 0xb5, 0x84, 0x3c, 0x81, 0x35, 0x91, 0x17, 0xbb, 0x29, 0x35, 0x2c, 0xa1, - 0x71, 0x90, 0xf1, 0x6b, 0x57, 0x72, 0xc9, 0x08, 0x9a, 0xea, 0x9b, 0xa6, 0xb6, 0xd5, 0xaf, 0x0d, - 0xda, 0x23, 0x5b, 0x28, 0xe8, 0x28, 0x87, 0xaa, 0x0c, 0xd2, 0xa3, 0x88, 0xb3, 0x99, 0x9b, 0x2b, - 0x92, 0xef, 0x41, 0xc7, 0x0b, 0x03, 0x8c, 0xf8, 0x98, 0xc7, 0x37, 0x18, 0xd9, 0x2d, 0xe9, 0x51, - 0x5b, 0xf1, 0x2e, 0x04, 0x8b, 0x8c, 0xe0, 0xa1, 0xa9, 0x32, 0xa6, 0x9e, 0x87, 0x69, 0x1a, 0x33, - 0x1b, 0xa4, 0xee, 0x03, 0x43, 0xf7, 0x40, 0x8b, 0xc4, 0xb1, 0x7e, 0x90, 0x26, 0x21, 0x9d, 0x8d, - 0x23, 0x3a, 0x45, 0xbb, 0xad, 0x8e, 0xd5, 0xbc, 0xaf, 0xe8, 0x14, 0xc9, 0x2e, 0xb4, 0xa7, 0x71, - 0x16, 0xf1, 0x71, 0x12, 0x07, 0x11, 0xb7, 0x3b, 0x52, 0x03, 0x24, 0xeb, 0x4c, 0x70, 0xc8, 0x07, - 0xa0, 0x28, 0x55, 0x8c, 0x5d, 0x95, 0x57, 0xc9, 0x91, 0xe5, 0xf8, 0x14, 0xd6, 0x95, 0xb8, 0xf0, - 0x67, 0x5d, 0xaa, 0x74, 0x25, 0xb7, 0xf0, 0xe4, 0x05, 0xb4, 0x64, 0x3d, 0x04, 0xd1, 0x55, 0x6c, - 0x6f, 0xc8, 0xbc, 0x3d, 0x30, 0xd2, 0x22, 0x6a, 0xe2, 0x38, 0xba, 0x8a, 0x5d, 0xeb, 0x4e, 0xaf, - 0xc8, 0xa7, 0xf0, 0xb8, 0x14, 0x2f, 0xc3, 0x29, 0x0d, 0xa2, 0x20, 0x9a, 0x8c, 0xb3, 0x14, 0x53, - 0x7b, 0x53, 0x56, 0xb8, 0x6d, 0x44, 0xed, 0xe6, 0x0a, 0xbf, 0x4a, 0x31, 0x25, 0x8f, 0xa1, 0x25, - 0xea, 0x96, 0xcf, 0xc6, 0x81, 0x6f, 0x6f, 0x49, 0x97, 0x2c, 0xc5, 0x38, 0xf6, 0xc9, 0x47, 0xb0, - 0x91, 0xc4, 0x61, 0xe0, 0xcd, 0xc6, 0xf1, 0x2d, 0x32, 0x16, 0xf8, 0x68, 0x93, 0x7e, 0x65, 0x60, - 0xb9, 0xeb, 0x8a, 0xfd, 0xb5, 0xe6, 0xae, 0x6a, 0x8d, 0x07, 0x52, 0x71, 0xa9, 0x35, 0x86, 0x00, - 0x5e, 0x1c, 0x45, 0xe8, 0xc9, 0xf2, 0xdb, 0x96, 0x11, 0xae, 0x8b, 0x08, 0x0f, 0x0b, 0xae, 0x6b, - 0x68, 0xf4, 0x3e, 0x87, 0x8e, 0x59, 0x0a, 0x64, 0x13, 0x6a, 0x37, 0x38, 0xd3, 0xe5, 0x2f, 0x96, - 0xa4, 0x0f, 0xf5, 0x5b, 0x1a, 0x66, 0x28, 0x4b, 0x5e, 0x17, 0xa2, 0xda, 0xe2, 0x2a, 0xc1, 0x4f, - 0xab, 0xaf, 0x2a, 0x0e, 0x85, 0xfa, 0x41, 0x18, 0xd0, 0x74, 0xe1, 0x3b, 0x55, 0xde, 0xfd, 0x9d, - 0xaa, 0xab, 0xbe, 0x13, 0x81, 0x35, 0x59, 0x29, 0xaa, 0x7f, 0xe4, 0xda, 0xf9, 0x67, 0x0d, 0xd6, + // 2101 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, 0x4e, 0x84, 0xe0, 0x6b, 0xc5, 0x77, 0x3b, 0xa1, 0x41, 0x09, 0xd4, 0x08, - 0x22, 0x8e, 0x2c, 0xa2, 0xe1, 0x58, 0xf6, 0x9b, 0xb2, 0xdc, 0xc9, 0x99, 0xaf, 0x45, 0xdf, 0x2d, - 0x96, 0x6a, 0x6d, 0xb9, 0x54, 0x7b, 0x60, 0xc9, 0xcf, 0x13, 0x60, 0xaa, 0xf1, 0xa4, 0xa0, 0xc9, - 0x08, 0xac, 0x29, 0x72, 0xaa, 0xdb, 0x59, 0x74, 0xdd, 0xa3, 0xbc, 0x2d, 0x87, 0xa7, 0x5a, 0xa0, - 0x7a, 0xae, 0xd0, 0x5b, 0x6a, 0xba, 0xc6, 0x72, 0xd3, 0xf5, 0xc0, 0x2a, 0xf2, 0xd5, 0x54, 0x45, - 0x94, 0xd3, 0x02, 0xc9, 0x13, 0x64, 0x41, 0xec, 0xdb, 0x96, 0xac, 0x45, 0x4d, 0x09, 0x1c, 0x8e, - 0xb2, 0xa9, 0xaa, 0xd2, 0x96, 0xc2, 0xe1, 0x28, 0x9b, 0x2e, 0x17, 0x25, 0x2c, 0x14, 0xe5, 0x2e, - 0xd4, 0xa9, 0xf8, 0x92, 0xb2, 0x4b, 0xdb, 0xa3, 0x96, 0xf4, 0x5f, 0x30, 0x5c, 0xc5, 0x27, 0x43, - 0xe8, 0x4e, 0x58, 0x9c, 0x25, 0x63, 0x49, 0x62, 0x6a, 0x77, 0x64, 0xa0, 0x86, 0x62, 0x47, 0xca, - 0x0f, 0x94, 0xb8, 0xf7, 0x33, 0xe8, 0x96, 0x42, 0x5f, 0x51, 0x63, 0xdb, 0x66, 0x8d, 0xb5, 0xcc, - 0xba, 0xfa, 0x53, 0x05, 0x3a, 0xe6, 0x37, 0x15, 0x9b, 0x2f, 0x2e, 0x4e, 0xe4, 0xe6, 0x9a, 0x2b, - 0x96, 0x02, 0x70, 0x19, 0x46, 0x78, 0x47, 0x2f, 0x43, 0x75, 0x80, 0xe5, 0xce, 0x19, 0x42, 0x1a, - 0x44, 0x1e, 0xc3, 0x29, 0x46, 0x5c, 0xcf, 0xa3, 0x39, 0x83, 0x7c, 0x02, 0x10, 0xa4, 0x69, 0x86, - 0x63, 0x31, 0x32, 0x25, 0x28, 0xb7, 0x47, 0xbd, 0xa1, 0x9a, 0xa7, 0xc3, 0x7c, 0x9e, 0x0e, 0x2f, - 0xf2, 0x79, 0xea, 0xb6, 0xa4, 0xb6, 0xa0, 0x9d, 0x3f, 0x42, 0x43, 0xe1, 0xf1, 0xff, 0xb4, 0x1e, - 0x77, 0xc0, 0x52, 0x67, 0x07, 0xbe, 0xae, 0xc5, 0xa6, 0xa4, 0x8f, 0x7d, 0xe7, 0xaf, 0x15, 0xb0, + 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, 0x8e, 0x32, 0x01, 0x74, 0xa9, 0x2c, 0xf5, 0x96, 0x5b, 0xd0, 0xe4, 0xa5, 0x09, 0xb3, - 0x6a, 0x80, 0x6d, 0x2b, 0x98, 0x55, 0xee, 0x2e, 0xe3, 0xac, 0xf3, 0x97, 0x2a, 0x6c, 0x2e, 0x8a, + 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, 0xca, 0xfb, 0xec, 0x11, 0x34, 0xae, 0x62, + 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, 0x06, 0x36, 0x16, 0xe6, 0xd9, 0x8a, 0x44, 0xce, 0xcd, 0x57, 0x4b, 0xe6, 0x4b, 0x27, 0xd7, - 0x16, 0x4e, 0xfe, 0x2d, 0x6c, 0x7d, 0x41, 0x23, 0x3f, 0x44, 0x7d, 0xfe, 0x01, 0x9b, 0x48, 0xc4, - 0xd7, 0xd7, 0xab, 0xb1, 0xbe, 0x38, 0x75, 0xdd, 0x96, 0xe6, 0x1c, 0xfb, 0xe4, 0x29, 0x34, 0x99, + 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, 0x4f, 0xd0, 0x0b, 0x68, 0x28, 0xef, 0xa0, 0xca, 0xc0, 0x2e, 0xd4, 0x45, 0x92, 0xf3, 0x9e, - 0x95, 0x20, 0xa6, 0xc4, 0x8a, 0xef, 0x7c, 0x0b, 0xb6, 0xf2, 0xeb, 0xe8, 0x6d, 0x90, 0x72, 0x8c, - 0x3c, 0x3c, 0xbc, 0x46, 0xef, 0xe6, 0xbf, 0x18, 0xf9, 0x2d, 0xec, 0xac, 0xb2, 0x90, 0xfb, 0xd7, - 0xf6, 0x04, 0x35, 0xbe, 0x8a, 0xb3, 0x48, 0xd9, 0xb0, 0x5c, 0x90, 0xac, 0xcf, 0x05, 0x47, 0x7c, - 0x47, 0x14, 0xfb, 0x52, 0x0d, 0x7d, 0x9a, 0xca, 0xf3, 0x51, 0xbb, 0x3f, 0x1f, 0xdf, 0x55, 0xa0, - 0x75, 0x8e, 0x3c, 0x4b, 0x64, 0x2c, 0x8f, 0xa1, 0x75, 0xc9, 0xe2, 0x1b, 0x64, 0xf3, 0x50, 0x2c, - 0xc5, 0x38, 0xf6, 0xc9, 0x4b, 0x68, 0x1c, 0xc6, 0xd1, 0x55, 0x30, 0x91, 0x37, 0xf2, 0xf6, 0x68, - 0x47, 0xa1, 0x8b, 0xde, 0x3b, 0x54, 0x32, 0x35, 0xd7, 0xb4, 0x62, 0xef, 0x13, 0x68, 0x1b, 0xec, - 0xff, 0x08, 0xf3, 0xff, 0x1f, 0x40, 0x9e, 0xad, 0x32, 0xb0, 0xa9, 0x02, 0xd1, 0x3b, 0x85, 0xe3, - 0xbb, 0xd0, 0x12, 0x77, 0x09, 0x25, 0x26, 0xb0, 0x66, 0x3c, 0x4f, 0xe4, 0xda, 0x79, 0x0a, 0x5b, - 0xc7, 0xd1, 0x2d, 0x0d, 0x03, 0x9f, 0x72, 0xfc, 0x12, 0x67, 0x32, 0xc0, 0x25, 0x0f, 0x9c, 0x73, - 0xe8, 0xe8, 0x07, 0xc0, 0x7b, 0xf9, 0xd8, 0xd1, 0x3e, 0xfe, 0xfb, 0x16, 0xf9, 0x18, 0x36, 0xf4, - 0xa1, 0x27, 0x81, 0x6e, 0x10, 0x31, 0xa1, 0x19, 0x5e, 0x05, 0x6f, 0xf5, 0xd1, 0x9a, 0x72, 0x5e, - 0xc1, 0xa6, 0xa1, 0x5a, 0x84, 0x73, 0x83, 0xb3, 0x34, 0x7f, 0x18, 0x89, 0x75, 0x9e, 0x81, 0xea, - 0x3c, 0x03, 0x0e, 0xac, 0xeb, 0x9d, 0x6f, 0x90, 0xdf, 0x13, 0xdd, 0x97, 0x85, 0x23, 0x6f, 0x50, - 0x1f, 0xbe, 0x07, 0x75, 0x14, 0x91, 0x9a, 0x03, 0xca, 0xcc, 0x80, 0xab, 0xc4, 0x2b, 0x0c, 0xbe, - 0x2a, 0x0c, 0x9e, 0x65, 0xca, 0xe0, 0x7b, 0x9e, 0xe5, 0x7c, 0x58, 0xb8, 0x71, 0x96, 0xf1, 0xfb, - 0xbe, 0xe8, 0x53, 0xd8, 0xd2, 0x4a, 0xaf, 0x31, 0x44, 0x8e, 0xf7, 0x84, 0xb4, 0x07, 0xa4, 0xa4, - 0x76, 0xdf, 0x71, 0x4f, 0xc0, 0xba, 0xb8, 0x38, 0x29, 0xa4, 0x65, 0xe4, 0x73, 0x3e, 0x85, 0xad, - 0xf3, 0xcc, 0x8f, 0xcf, 0x58, 0x70, 0x1b, 0x84, 0x38, 0x51, 0xc6, 0xf2, 0x77, 0x59, 0xc5, 0x78, - 0x97, 0xad, 0x9c, 0x35, 0xce, 0x00, 0x48, 0x69, 0x7b, 0xf1, 0xdd, 0xd2, 0xcc, 0x8f, 0x75, 0x83, - 0xca, 0xb5, 0x33, 0x80, 0xce, 0x05, 0x15, 0xd3, 0xdc, 0x57, 0x3a, 0x36, 0x34, 0xb9, 0xa2, 0xb5, - 0x5a, 0x4e, 0x3a, 0x23, 0xd8, 0x3e, 0xa4, 0xde, 0x75, 0x10, 0x4d, 0x5e, 0x07, 0xa9, 0xb8, 0xb6, - 0xe8, 0x1d, 0x3d, 0xb0, 0x7c, 0xcd, 0xd0, 0x5b, 0x0a, 0xda, 0x79, 0x0e, 0x0f, 0x8d, 0xd7, 0xe7, - 0x39, 0xa7, 0x79, 0x3e, 0xb6, 0xa1, 0x9e, 0x0a, 0x4a, 0xee, 0xa8, 0xbb, 0x8a, 0x70, 0xbe, 0x82, - 0x6d, 0x73, 0xbc, 0x8a, 0xcb, 0x45, 0x1e, 0xb8, 0x1c, 0xfb, 0x15, 0x63, 0xec, 0xeb, 0x9c, 0x55, - 0xe7, 0xd3, 0x62, 0x13, 0x6a, 0xbf, 0xfc, 0xe6, 0x42, 0x17, 0xbb, 0x58, 0x3a, 0xbf, 0x17, 0xe6, - 0xcb, 0xe7, 0x29, 0xf3, 0xa5, 0xd9, 0x5f, 0x79, 0x9f, 0xd9, 0xbf, 0xa2, 0xde, 0x9e, 0xc3, 0xd6, - 0x69, 0x18, 0x7b, 0x37, 0x47, 0x91, 0x91, 0x0d, 0x1b, 0x9a, 0x18, 0x99, 0xc9, 0xc8, 0x49, 0xe7, - 0x23, 0xd8, 0x38, 0x11, 0x6f, 0xff, 0x53, 0xf1, 0x88, 0x28, 0xb2, 0x20, 0x7f, 0x07, 0x68, 0x55, - 0x45, 0x38, 0xcf, 0x01, 0xe6, 0x0f, 0x21, 0x01, 0xae, 0x0c, 0xa7, 0x31, 0xc7, 0x31, 0xf5, 0xfd, - 0xbc, 0x82, 0x40, 0xb1, 0x0e, 0x7c, 0x9f, 0x8d, 0xfe, 0x51, 0x85, 0xe6, 0x2f, 0xd4, 0xff, 0x16, - 0xf2, 0x19, 0x74, 0x4b, 0x03, 0x8a, 0x3c, 0x94, 0x2f, 0xa1, 0xc5, 0x71, 0xd8, 0x7b, 0xb4, 0xc4, - 0x56, 0x0e, 0xbd, 0x80, 0x8e, 0x39, 0x7e, 0x88, 0x1c, 0x35, 0xf2, 0xb7, 0x4c, 0x4f, 0x9e, 0xb4, - 0x3c, 0x9b, 0xce, 0x61, 0x7b, 0xd5, 0x60, 0x20, 0x4f, 0xe6, 0x16, 0x96, 0x87, 0x52, 0xef, 0x83, - 0xfb, 0xa4, 0xf9, 0x40, 0x69, 0x1e, 0x86, 0x48, 0xa3, 0x2c, 0x31, 0x3d, 0x98, 0x2f, 0xc9, 0x4b, - 0xe8, 0x96, 0xc0, 0x53, 0xc5, 0xb9, 0x84, 0xa7, 0xe6, 0x96, 0x3d, 0xa8, 0x4b, 0xc0, 0x26, 0xdd, - 0xd2, 0x5c, 0xe8, 0xad, 0x17, 0xa4, 0xb2, 0xdd, 0x87, 0x35, 0xf9, 0x08, 0x34, 0x0c, 0xcb, 0x1d, - 0x05, 0x9a, 0x8f, 0xfe, 0x56, 0x81, 0x66, 0xfe, 0x03, 0xe7, 0x25, 0xac, 0x09, 0x5c, 0x24, 0x0f, - 0x0c, 0x68, 0xc9, 0x31, 0xb5, 0xb7, 0xbd, 0xc0, 0x54, 0x06, 0x86, 0x50, 0x7b, 0x83, 0x9c, 0x10, - 0x43, 0xa8, 0x01, 0xb2, 0xf7, 0xa0, 0xcc, 0x2b, 0xf4, 0xcf, 0xb2, 0xb2, 0xbe, 0xc6, 0xb7, 0x92, - 0x7e, 0x81, 0x5c, 0x3f, 0x81, 0x86, 0x42, 0x1e, 0x95, 0x94, 0x25, 0xcc, 0x52, 0x1f, 0x7f, 0x19, - 0xa3, 0x46, 0x7f, 0xaf, 0x01, 0x9c, 0xcf, 0x52, 0x8e, 0xd3, 0x5f, 0x07, 0x78, 0x47, 0x9e, 0xc1, - 0xc6, 0x6b, 0xbc, 0xa2, 0x59, 0xc8, 0xe5, 0xfb, 0x40, 0x74, 0x98, 0x91, 0x13, 0x79, 0xc5, 0x29, - 0x00, 0x6c, 0x0f, 0xda, 0xa7, 0xf4, 0xed, 0xbb, 0xf5, 0x3e, 0x83, 0x6e, 0x09, 0x97, 0xb4, 0x8b, - 0x8b, 0x48, 0xa7, 0x5d, 0x5c, 0x46, 0xb0, 0x3d, 0x68, 0x6a, 0xb4, 0x32, 0x6d, 0x48, 0x5c, 0x2f, - 0xa1, 0xd8, 0x8f, 0x61, 0x63, 0x01, 0xab, 0x4c, 0x7d, 0xf9, 0x93, 0x69, 0x25, 0x96, 0xbd, 0x12, - 0xf7, 0xfb, 0x32, 0x5e, 0x99, 0x1b, 0x77, 0x14, 0x46, 0xac, 0x02, 0xb4, 0x37, 0xe5, 0x97, 0x81, - 0x7c, 0x17, 0xd9, 0x8b, 0x90, 0x92, 0x03, 0x5a, 0x7e, 0xd0, 0x2a, 0x68, 0x7a, 0x01, 0x1d, 0x13, - 0x55, 0x96, 0x5a, 0x70, 0x19, 0x72, 0xbe, 0x0f, 0x30, 0x07, 0x16, 0x53, 0x5f, 0x96, 0xc7, 0x02, - 0xe6, 0x5c, 0x36, 0xe4, 0x5b, 0xe2, 0x07, 0xff, 0x0a, 0x00, 0x00, 0xff, 0xff, 0xe5, 0x31, 0x02, - 0x9d, 0xb6, 0x15, 0x00, 0x00, + 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, } diff --git a/logical/plugin/pb/backend.proto b/logical/plugin/pb/backend.proto index 533b0f7ba..db7c4a026 100644 --- a/logical/plugin/pb/backend.proto +++ b/logical/plugin/pb/backend.proto @@ -338,6 +338,7 @@ message HandleExistenceCheckReply { message SetupArgs { uint32 broker_id = 1; map Config = 2; + string backendUUID = 3; } // SetupReply is the reply for Setup method. diff --git a/vault/auth.go b/vault/auth.go index 487b94230..eb9e28c8b 100644 --- a/vault/auth.go +++ b/vault/auth.go @@ -87,6 +87,13 @@ func (c *Core) enableCredential(ctx context.Context, entry *MountEntry) error { } entry.UUID = entryUUID } + if entry.BackendAwareUUID == "" { + bUUID, err := uuid.GenerateUUID() + if err != nil { + return err + } + entry.BackendAwareUUID = bUUID + } if entry.Accessor == "" { accessor, err := c.generateMountAccessor("auth_" + entry.Type) if err != nil { @@ -108,13 +115,9 @@ func (c *Core) enableCredential(ctx context.Context, entry *MountEntry) error { var err error var backend logical.Backend sysView := c.mountEntrySysView(entry) - conf := make(map[string]string) - if entry.Config.PluginName != "" { - conf["plugin_name"] = entry.Config.PluginName - } // Create the new backend - backend, err = c.newCredentialBackend(ctx, entry.Type, sysView, view, conf) + backend, err = c.newCredentialBackend(ctx, entry, sysView, view) if err != nil { return err } @@ -349,6 +352,14 @@ func (c *Core) loadCredentials(ctx context.Context) error { entry.Accessor = accessor needPersist = true } + if entry.BackendAwareUUID == "" { + bUUID, err := uuid.GenerateUUID() + if err != nil { + return err + } + entry.BackendAwareUUID = bUUID + needPersist = true + } // Sync values to the cache entry.SyncCache() @@ -466,12 +477,8 @@ func (c *Core) setupCredentials(ctx context.Context) error { // Initialize the backend sysView := c.mountEntrySysView(entry) - conf := make(map[string]string) - if entry.Config.PluginName != "" { - conf["plugin_name"] = entry.Config.PluginName - } - backend, err = c.newCredentialBackend(ctx, entry.Type, sysView, view, conf) + backend, err = c.newCredentialBackend(ctx, entry, sysView, view) if err != nil { c.logger.Error("core: failed to create credential entry", "path", entry.Path, "error", err) if entry.Type == "plugin" { @@ -546,12 +553,8 @@ func (c *Core) teardownCredentials(ctx context.Context) error { } // newCredentialBackend is used to create and configure a new credential backend by name -func (c *Core) newCredentialBackend( - ctx context.Context, - t string, - sysView logical.SystemView, - view logical.Storage, - conf map[string]string) (logical.Backend, error) { +func (c *Core) newCredentialBackend(ctx context.Context, entry *MountEntry, sysView logical.SystemView, view logical.Storage) (logical.Backend, error) { + t := entry.Type if alias, ok := credentialAliases[t]; ok { t = alias } @@ -560,11 +563,21 @@ func (c *Core) newCredentialBackend( return nil, fmt.Errorf("unknown backend type: %s", t) } + // Set up conf to pass in plugin_name + conf := make(map[string]string, len(entry.Options)+1) + for k, v := range entry.Options { + conf[k] = v + } + if entry.Config.PluginName != "" { + conf["plugin_name"] = entry.Config.PluginName + } + config := &logical.BackendConfig{ StorageView: view, Logger: c.logger, Config: conf, System: sysView, + BackendUUID: entry.BackendAwareUUID, } b, err := f(ctx, config) @@ -588,13 +601,18 @@ func (c *Core) defaultAuthTable() *MountTable { if err != nil { panic(fmt.Sprintf("could not generate accessor for default auth table token entry: %v", err)) } + tokenBackendUUID, err := uuid.GenerateUUID() + if err != nil { + panic(fmt.Sprintf("could not create identity backend UUID: %v", err)) + } tokenAuth := &MountEntry{ - Table: credentialTableType, - Path: "token/", - Type: "token", - Description: "token based credentials", - UUID: tokenUUID, - Accessor: tokenAccessor, + Table: credentialTableType, + Path: "token/", + Type: "token", + Description: "token based credentials", + UUID: tokenUUID, + Accessor: tokenAccessor, + BackendAwareUUID: tokenBackendUUID, } table.Entries = append(table.Entries, tokenAuth) return table diff --git a/vault/auth_test.go b/vault/auth_test.go index cbbb9f022..6f66b4c58 100644 --- a/vault/auth_test.go +++ b/vault/auth_test.go @@ -124,18 +124,20 @@ func TestCore_EnableCredential_Local(t *testing.T) { Type: credentialTableType, Entries: []*MountEntry{ &MountEntry{ - Table: credentialTableType, - Path: "noop/", - Type: "noop", - UUID: "abcd", - Accessor: "noop-abcd", + Table: credentialTableType, + Path: "noop/", + Type: "noop", + UUID: "abcd", + Accessor: "noop-abcd", + BackendAwareUUID: "abcde", }, &MountEntry{ - Table: credentialTableType, - Path: "noop2/", - Type: "noop", - UUID: "bcde", - Accessor: "noop-bcde", + Table: credentialTableType, + Path: "noop2/", + Type: "noop", + UUID: "bcde", + Accessor: "noop-bcde", + BackendAwareUUID: "bcdea", }, }, } diff --git a/vault/identity_store_entities_test.go b/vault/identity_store_entities_test.go index 0f0d8601a..98e239c81 100644 --- a/vault/identity_store_entities_test.go +++ b/vault/identity_store_entities_test.go @@ -337,7 +337,7 @@ func TestIdentityStore_LoadingEntities(t *testing.T) { ghSysview := c.mountEntrySysView(meGH) // Create new github auth credential backend - ghAuth, err := c.newCredentialBackend(context.Background(), meGH.Type, ghSysview, ghView, nil) + ghAuth, err := c.newCredentialBackend(context.Background(), meGH, ghSysview, ghView) if err != nil { t.Fatal(err) } diff --git a/vault/logical_system.go b/vault/logical_system.go index 7b000153f..ba6560273 100644 --- a/vault/logical_system.go +++ b/vault/logical_system.go @@ -16,6 +16,7 @@ import ( "sync" "time" + "github.com/hashicorp/errwrap" uuid "github.com/hashicorp/go-uuid" "github.com/hashicorp/vault/helper/compressutil" "github.com/hashicorp/vault/helper/consts" @@ -266,6 +267,10 @@ func NewSystemBackend(core *Core) *SystemBackend { Type: framework.TypeCommaStringSlice, Description: strings.TrimSpace(sysHelp["tune_audit_non_hmac_response_keys"][0]), }, + "options": &framework.FieldSchema{ + Type: framework.TypeKVPairs, + Description: strings.TrimSpace(sysHelp["tune_mount_options"][0]), + }, "listing_visibility": &framework.FieldSchema{ Type: framework.TypeString, Description: strings.TrimSpace(sysHelp["listing_visibility"][0]), @@ -307,6 +312,10 @@ func NewSystemBackend(core *Core) *SystemBackend { Type: framework.TypeCommaStringSlice, Description: strings.TrimSpace(sysHelp["tune_audit_non_hmac_response_keys"][0]), }, + "options": &framework.FieldSchema{ + Type: framework.TypeKVPairs, + Description: strings.TrimSpace(sysHelp["tune_mount_options"][0]), + }, "listing_visibility": &framework.FieldSchema{ Type: framework.TypeString, Description: strings.TrimSpace(sysHelp["listing_visibility"][0]), @@ -356,6 +365,10 @@ func NewSystemBackend(core *Core) *SystemBackend { Type: framework.TypeString, Description: strings.TrimSpace(sysHelp["mount_plugin_name"][0]), }, + "options": &framework.FieldSchema{ + Type: framework.TypeKVPairs, + Description: strings.TrimSpace(sysHelp["mount_options"][0]), + }, }, Callbacks: map[logical.Operation]framework.OperationFunc{ @@ -576,6 +589,10 @@ func NewSystemBackend(core *Core) *SystemBackend { Type: framework.TypeString, Description: strings.TrimSpace(sysHelp["auth_plugin"][0]), }, + "options": &framework.FieldSchema{ + Type: framework.TypeKVPairs, + Description: strings.TrimSpace(sysHelp["auth_options"][0]), + }, }, Callbacks: map[logical.Operation]framework.OperationFunc{ @@ -727,7 +744,7 @@ func NewSystemBackend(core *Core) *SystemBackend { Description: strings.TrimSpace(sysHelp["audit_desc"][0]), }, "options": &framework.FieldSchema{ - Type: framework.TypeMap, + Type: framework.TypeKVPairs, Description: strings.TrimSpace(sysHelp["audit_opts"][0]), }, "local": &framework.FieldSchema{ @@ -1462,6 +1479,7 @@ func (b *SystemBackend) handleMountTable(ctx context.Context, req *logical.Reque "accessor": entry.Accessor, "local": entry.Local, "seal_wrap": entry.SealWrap, + "options": entry.Options, } entryConfig := map[string]interface{}{ "default_lease_ttl": int64(entry.Config.DefaultLeaseTTL.Seconds()), @@ -1504,6 +1522,7 @@ func (b *SystemBackend) handleMount(ctx context.Context, req *logical.Request, d description := data.Get("description").(string) pluginName := data.Get("plugin_name").(string) sealWrap := data.Get("seal_wrap").(bool) + options := data.Get("options").(map[string]string) var config MountConfig var apiConfig APIMountConfig @@ -1603,6 +1622,7 @@ func (b *SystemBackend) handleMount(ctx context.Context, req *logical.Request, d Config: config, Local: local, SealWrap: sealWrap, + Options: options, } // Attempt mount @@ -1762,6 +1782,10 @@ func (b *SystemBackend) handleTuneReadCommon(path string) (*logical.Response, er resp.Data["listing_visibility"] = mountEntry.Config.ListingVisibility } + if len(mountEntry.Options) > 0 { + resp.Data["options"] = mountEntry.Options + } + return resp, nil } @@ -1976,7 +2000,57 @@ func (b *SystemBackend) handleTuneWriteCommon(ctx context.Context, path string, } } - return nil, nil + var resp *logical.Response + if optionsRaw, ok := data.GetOk("options"); ok { + b.Core.logger.Info("core: mount tuning of options", "path", path) + options := optionsRaw.(map[string]string) + + b.Core.logger.Info("core: mount tuning of options", "path", path, "options", options) + // Special case to make sure we can not disable versioning once it's + // enabeled. If the vkv backend suports downgrading this can be removed. + meVersioned, err := parseutil.ParseBool(mountEntry.Options["versioned"]) + if err != nil { + return nil, errwrap.Wrapf("unable to parse mount entry: {{err}}", err) + } + optVersioned, err := parseutil.ParseBool(options["versioned"]) + if err != nil { + return handleError(errwrap.Wrapf("unable to parse options: {{err}}", err)) + } + if meVersioned && !optVersioned { + return logical.ErrorResponse("cannot disable versioning once it's enabled"), logical.ErrInvalidRequest + } + + oldVal := mountEntry.Options + mountEntry.Options = options + // Update the mount table + switch { + case strings.HasPrefix(path, "auth/"): + err = b.Core.persistAuth(ctx, b.Core.auth, mountEntry.Local) + default: + err = b.Core.persistMounts(ctx, b.Core.mounts, mountEntry.Local) + } + if err != nil { + mountEntry.Options = oldVal + return handleError(err) + } + + // Another special case to trigger the upgrade path if we are enabling + // versioning for the first time. + oldVersioned, err := parseutil.ParseBool(oldVal["versioned"]) + if err != nil { + return nil, errwrap.Wrapf("unable to parse mount entry: {{err}}", err) + } + if !oldVersioned && optVersioned { + resp = &logical.Response{} + resp.AddWarning("Uprading from non-versioned to versioned data. This backend will be unavailable for a brief period and will resume service shortly.") + mountEntry.Options["upgrade"] = "true" + } + + b.Core.reloadBackendCommon(ctx, mountEntry, strings.HasPrefix(path, credentialRoutePrefix)) + + delete(mountEntry.Options, "upgrade") + } + return resp, nil } // handleLease is use to view the metadata for a given LeaseID @@ -2122,6 +2196,7 @@ func (b *SystemBackend) handleAuthTable(ctx context.Context, req *logical.Reques "accessor": entry.Accessor, "local": entry.Local, "seal_wrap": entry.SealWrap, + "options": entry.Options, } entryConfig := map[string]interface{}{ "default_lease_ttl": int64(entry.Config.DefaultLeaseTTL.Seconds()), @@ -2160,6 +2235,7 @@ func (b *SystemBackend) handleEnableAuth(ctx context.Context, req *logical.Reque description := data.Get("description").(string) pluginName := data.Get("plugin_name").(string) sealWrap := data.Get("seal_wrap").(bool) + options := data.Get("options").(map[string]string) var config MountConfig var apiConfig APIMountConfig @@ -2254,6 +2330,7 @@ func (b *SystemBackend) handleEnableAuth(ctx context.Context, req *logical.Reque Config: config, Local: local, SealWrap: sealWrap, + Options: options, } // Attempt enabling @@ -2528,17 +2605,7 @@ func (b *SystemBackend) handleEnableAudit(ctx context.Context, req *logical.Requ path := data.Get("path").(string) backendType := data.Get("type").(string) description := data.Get("description").(string) - options := data.Get("options").(map[string]interface{}) - - optionMap := make(map[string]string) - for k, v := range options { - vStr, ok := v.(string) - if !ok { - return logical.ErrorResponse("options must be string valued"), - logical.ErrInvalidRequest - } - optionMap[k] = vStr - } + options := data.Get("options").(map[string]string) // Create the mount entry me := &MountEntry{ @@ -2546,7 +2613,7 @@ func (b *SystemBackend) handleEnableAudit(ctx context.Context, req *logical.Requ Path: path, Type: backendType, Description: description, - Options: optionMap, + Options: options, Local: local, } @@ -3326,6 +3393,10 @@ and is unaffected by replication.`, in the plugin catalog.`, }, + "mount_options": { + `The options to pass into the backend. Should be a json object with string keys and values.`, + }, + "seal_wrap": { `Whether to turn on seal wrapping for the mount.`, }, @@ -3346,6 +3417,10 @@ in the plugin catalog.`, `The list of keys in the response data object that will not be HMAC'ed by audit devices.`, }, + "tune_mount_options": { + `The options to pass into the backend. Should be a json object with string keys and values.`, + }, + "remount": { "Move the mount point of an already-mounted backend.", ` @@ -3483,6 +3558,10 @@ Example: you might have an OAuth backend for GitHub, and one for Google Apps. "", }, + "auth_options": { + `The options to pass into the backend. Should be a json object with string keys and values.`, + }, + "policy-list": { `List the configured access control policies.`, ` diff --git a/vault/logical_system_test.go b/vault/logical_system_test.go index 5a53b9f4f..7c2ad7165 100644 --- a/vault/logical_system_test.go +++ b/vault/logical_system_test.go @@ -129,6 +129,9 @@ func TestSystemBackend_mounts(t *testing.T) { }, "local": false, "seal_wrap": false, + "options": map[string]string{ + "versioned": "true", + }, }, "sys/": map[string]interface{}{ "type": "system", @@ -142,6 +145,7 @@ func TestSystemBackend_mounts(t *testing.T) { }, "local": false, "seal_wrap": false, + "options": map[string]string(nil), }, "cubbyhole/": map[string]interface{}{ "description": "per-token private secret storage", @@ -155,6 +159,7 @@ func TestSystemBackend_mounts(t *testing.T) { }, "local": true, "seal_wrap": false, + "options": map[string]string(nil), }, "identity/": map[string]interface{}{ "description": "identity store", @@ -168,6 +173,7 @@ func TestSystemBackend_mounts(t *testing.T) { }, "local": false, "seal_wrap": false, + "options": map[string]string(nil), }, } if !reflect.DeepEqual(resp.Data, exp) { @@ -186,6 +192,9 @@ func TestSystemBackend_mount(t *testing.T) { } req.Data["local"] = true req.Data["seal_wrap"] = true + req.Data["options"] = map[string]string{ + "versioned": "true", + } resp, err := b.HandleRequest(context.Background(), req) if err != nil { @@ -216,6 +225,9 @@ func TestSystemBackend_mount(t *testing.T) { }, "local": false, "seal_wrap": false, + "options": map[string]string{ + "versioned": "true", + }, }, "sys/": map[string]interface{}{ "type": "system", @@ -229,6 +241,7 @@ func TestSystemBackend_mount(t *testing.T) { }, "local": false, "seal_wrap": false, + "options": map[string]string(nil), }, "cubbyhole/": map[string]interface{}{ "description": "per-token private secret storage", @@ -242,6 +255,7 @@ func TestSystemBackend_mount(t *testing.T) { }, "local": true, "seal_wrap": false, + "options": map[string]string(nil), }, "identity/": map[string]interface{}{ "description": "identity store", @@ -255,6 +269,7 @@ func TestSystemBackend_mount(t *testing.T) { }, "local": false, "seal_wrap": false, + "options": map[string]string(nil), }, "prod/secret/": map[string]interface{}{ "description": "", @@ -268,6 +283,9 @@ func TestSystemBackend_mount(t *testing.T) { }, "local": true, "seal_wrap": true, + "options": map[string]string{ + "versioned": "true", + }, }, } if !reflect.DeepEqual(resp.Data, exp) { @@ -1392,6 +1410,7 @@ func TestSystemBackend_authTable(t *testing.T) { }, "local": false, "seal_wrap": false, + "options": map[string]string(nil), }, } if !reflect.DeepEqual(resp.Data, exp) { @@ -1443,6 +1462,7 @@ func TestSystemBackend_enableAuth(t *testing.T) { }, "local": true, "seal_wrap": true, + "options": map[string]string{}, }, "token/": map[string]interface{}{ "type": "token", @@ -1455,6 +1475,7 @@ func TestSystemBackend_enableAuth(t *testing.T) { }, "local": false, "seal_wrap": false, + "options": map[string]string(nil), }, } if !reflect.DeepEqual(resp.Data, exp) { diff --git a/vault/mount.go b/vault/mount.go index b60834c61..aa2c739e9 100644 --- a/vault/mount.go +++ b/vault/mount.go @@ -171,17 +171,18 @@ func (t *MountTable) sortEntriesByPath() *MountTable { // MountEntry is used to represent a mount table entry type MountEntry struct { - Table string `json:"table"` // The table it belongs to - Path string `json:"path"` // Mount Path - Type string `json:"type"` // Logical backend Type - Description string `json:"description"` // User-provided description - UUID string `json:"uuid"` // Barrier view UUID - Accessor string `json:"accessor"` // Unique but more human-friendly ID. Does not change, not used for any sensitive things (like as a salt, which the UUID sometimes is). - Config MountConfig `json:"config"` // Configuration related to this mount (but not backend-derived) - Options map[string]string `json:"options"` // Backend options - Local bool `json:"local"` // Local mounts are not replicated or affected by replication - SealWrap bool `json:"seal_wrap"` // Whether to wrap CSPs - Tainted bool `json:"tainted,omitempty"` // Set as a Write-Ahead flag for unmount/remount + Table string `json:"table"` // The table it belongs to + Path string `json:"path"` // Mount Path + Type string `json:"type"` // Logical backend Type + Description string `json:"description"` // User-provided description + UUID string `json:"uuid"` // Barrier view UUID + BackendAwareUUID string `json:"backend_aware_uuid"` // UUID that can be used by the backend as a helper when a consistent value is needed outside of storage. + Accessor string `json:"accessor"` // Unique but more human-friendly ID. Does not change, not used for any sensitive things (like as a salt, which the UUID sometimes is). + Config MountConfig `json:"config"` // Configuration related to this mount (but not backend-derived) + Options map[string]string `json:"options"` // Backend options + Local bool `json:"local"` // Local mounts are not replicated or affected by replication + SealWrap bool `json:"seal_wrap"` // Whether to wrap CSPs + Tainted bool `json:"tainted,omitempty"` // Set as a Write-Ahead flag for unmount/remount // synthesizedConfigCache is used to cache configuration values synthesizedConfigCache sync.Map @@ -273,6 +274,13 @@ func (c *Core) mountInternal(ctx context.Context, entry *MountEntry) error { } entry.UUID = entryUUID } + if entry.BackendAwareUUID == "" { + bUUID, err := uuid.GenerateUUID() + if err != nil { + return err + } + entry.BackendAwareUUID = bUUID + } if entry.Accessor == "" { accessor, err := c.generateMountAccessor(entry.Type) if err != nil { @@ -295,13 +303,9 @@ func (c *Core) mountInternal(ctx context.Context, entry *MountEntry) error { var backend logical.Backend var err error sysView := c.mountEntrySysView(entry) - conf := make(map[string]string) - if entry.Config.PluginName != "" { - conf["plugin_name"] = entry.Config.PluginName - } // Consider having plugin name under entry.Options - backend, err = c.newLogicalBackend(ctx, entry.Type, sysView, view, conf) + backend, err = c.newLogicalBackend(ctx, entry, sysView, view) if err != nil { return err } @@ -674,6 +678,14 @@ func (c *Core) loadMounts(ctx context.Context) error { entry.Accessor = accessor needPersist = true } + if entry.BackendAwareUUID == "" { + bUUID, err := uuid.GenerateUUID() + if err != nil { + return err + } + entry.BackendAwareUUID = bUUID + needPersist = true + } // Sync values to the cache entry.SyncCache() @@ -791,13 +803,9 @@ func (c *Core) setupMounts(ctx context.Context) error { var backend logical.Backend var err error sysView := c.mountEntrySysView(entry) - // Set up conf to pass in plugin_name - conf := make(map[string]string) - if entry.Config.PluginName != "" { - conf["plugin_name"] = entry.Config.PluginName - } + // Create the new backend - backend, err = c.newLogicalBackend(ctx, entry.Type, sysView, view, conf) + backend, err = c.newLogicalBackend(ctx, entry, sysView, view) if err != nil { c.logger.Error("core: failed to create mount entry", "path", entry.Path, "error", err) if entry.Type == "plugin" { @@ -864,7 +872,8 @@ func (c *Core) unloadMounts(ctx context.Context) error { } // newLogicalBackend is used to create and configure a new logical backend by name -func (c *Core) newLogicalBackend(ctx context.Context, t string, sysView logical.SystemView, view logical.Storage, conf map[string]string) (logical.Backend, error) { +func (c *Core) newLogicalBackend(ctx context.Context, entry *MountEntry, sysView logical.SystemView, view logical.Storage) (logical.Backend, error) { + t := entry.Type if alias, ok := mountAliases[t]; ok { t = alias } @@ -873,11 +882,21 @@ func (c *Core) newLogicalBackend(ctx context.Context, t string, sysView logical. return nil, fmt.Errorf("unknown backend type: %s", t) } + // Set up conf to pass in plugin_name + conf := make(map[string]string, len(entry.Options)+1) + for k, v := range entry.Options { + conf[k] = v + } + if entry.Config.PluginName != "" { + conf["plugin_name"] = entry.Config.PluginName + } + config := &logical.BackendConfig{ StorageView: view, Logger: c.logger, Config: conf, System: sysView, + BackendUUID: entry.BackendAwareUUID, } b, err := f(ctx, config) @@ -913,13 +932,22 @@ func (c *Core) defaultMountTable() *MountTable { if err != nil { panic(fmt.Sprintf("could not generate default secret mount accessor: %v", err)) } + bUUID, err := uuid.GenerateUUID() + if err != nil { + panic(fmt.Sprintf("could not create default secret mount backend UUID: %v", err)) + } + kvMount := &MountEntry{ - Table: mountTableType, - Path: "secret/", - Type: "kv", - Description: "key/value secret storage", - UUID: mountUUID, - Accessor: mountAccessor, + Table: mountTableType, + Path: "secret/", + Type: "kv", + Description: "key/value secret storage", + UUID: mountUUID, + Accessor: mountAccessor, + BackendAwareUUID: bUUID, + Options: map[string]string{ + "versioned": "true", + }, } table.Entries = append(table.Entries, kvMount) table.Entries = append(table.Entries, c.requiredMountTable().Entries...) @@ -940,14 +968,19 @@ func (c *Core) requiredMountTable() *MountTable { if err != nil { panic(fmt.Sprintf("could not generate cubbyhole accessor: %v", err)) } + cubbyholeBackendUUID, err := uuid.GenerateUUID() + if err != nil { + panic(fmt.Sprintf("could not create cubbyhole backend UUID: %v", err)) + } cubbyholeMount := &MountEntry{ - Table: mountTableType, - Path: "cubbyhole/", - Type: "cubbyhole", - Description: "per-token private secret storage", - UUID: cubbyholeUUID, - Accessor: cubbyholeAccessor, - Local: true, + Table: mountTableType, + Path: "cubbyhole/", + Type: "cubbyhole", + Description: "per-token private secret storage", + UUID: cubbyholeUUID, + Accessor: cubbyholeAccessor, + Local: true, + BackendAwareUUID: cubbyholeBackendUUID, } sysUUID, err := uuid.GenerateUUID() @@ -958,13 +991,18 @@ func (c *Core) requiredMountTable() *MountTable { if err != nil { panic(fmt.Sprintf("could not generate sys accessor: %v", err)) } + sysBackendUUID, err := uuid.GenerateUUID() + if err != nil { + panic(fmt.Sprintf("could not create sys backend UUID: %v", err)) + } sysMount := &MountEntry{ - Table: mountTableType, - Path: "sys/", - Type: "system", - Description: "system endpoints used for control, policy and debugging", - UUID: sysUUID, - Accessor: sysAccessor, + Table: mountTableType, + Path: "sys/", + Type: "system", + Description: "system endpoints used for control, policy and debugging", + UUID: sysUUID, + Accessor: sysAccessor, + BackendAwareUUID: sysBackendUUID, } identityUUID, err := uuid.GenerateUUID() @@ -975,14 +1013,18 @@ func (c *Core) requiredMountTable() *MountTable { if err != nil { panic(fmt.Sprintf("could not generate identity accessor: %v", err)) } - + identityBackendUUID, err := uuid.GenerateUUID() + if err != nil { + panic(fmt.Sprintf("could not create identity backend UUID: %v", err)) + } identityMount := &MountEntry{ - Table: mountTableType, - Path: "identity/", - Type: "identity", - Description: "identity store", - UUID: identityUUID, - Accessor: identityAccessor, + Table: mountTableType, + Path: "identity/", + Type: "identity", + Description: "identity store", + UUID: identityUUID, + Accessor: identityAccessor, + BackendAwareUUID: identityBackendUUID, } table.Entries = append(table.Entries, cubbyholeMount) diff --git a/vault/mount_test.go b/vault/mount_test.go index 6e58b9341..fc0432fa4 100644 --- a/vault/mount_test.go +++ b/vault/mount_test.go @@ -118,18 +118,20 @@ func TestCore_Mount_Local(t *testing.T) { Type: mountTableType, Entries: []*MountEntry{ &MountEntry{ - Table: mountTableType, - Path: "noop/", - Type: "kv", - UUID: "abcd", - Accessor: "kv-abcd", + Table: mountTableType, + Path: "noop/", + Type: "kv", + UUID: "abcd", + Accessor: "kv-abcd", + BackendAwareUUID: "abcde", }, &MountEntry{ - Table: mountTableType, - Path: "noop2/", - Type: "kv", - UUID: "bcde", - Accessor: "kv-bcde", + Table: mountTableType, + Path: "noop2/", + Type: "kv", + UUID: "bcde", + Accessor: "kv-bcde", + BackendAwareUUID: "bcdea", }, }, } diff --git a/vault/plugin_reload.go b/vault/plugin_reload.go index ea5df9467..1d3bdd572 100644 --- a/vault/plugin_reload.go +++ b/vault/plugin_reload.go @@ -31,7 +31,7 @@ func (c *Core) reloadMatchingPluginMounts(ctx context.Context, mounts []string) } if entry.Type == "plugin" { - err := c.reloadPluginCommon(ctx, entry, isAuth) + err := c.reloadBackendCommon(ctx, entry, isAuth) if err != nil { errors = multierror.Append(errors, fmt.Errorf("cannot reload plugin on %s: %v", mount, err)) continue @@ -52,7 +52,7 @@ func (c *Core) reloadMatchingPlugin(ctx context.Context, pluginName string) erro // Filter mount entries that only matches the plugin name for _, entry := range c.mounts.Entries { if entry.Config.PluginName == pluginName && entry.Type == "plugin" { - err := c.reloadPluginCommon(ctx, entry, false) + err := c.reloadBackendCommon(ctx, entry, false) if err != nil { return err } @@ -63,7 +63,7 @@ func (c *Core) reloadMatchingPlugin(ctx context.Context, pluginName string) erro // Filter auth mount entries that ony matches the plugin name for _, entry := range c.auth.Entries { if entry.Config.PluginName == pluginName && entry.Type == "plugin" { - err := c.reloadPluginCommon(ctx, entry, true) + err := c.reloadBackendCommon(ctx, entry, true) if err != nil { return err } @@ -74,10 +74,9 @@ func (c *Core) reloadMatchingPlugin(ctx context.Context, pluginName string) erro return nil } -// reloadPluginCommon is a generic method to reload a backend provided a -// MountEntry. entry.Type should be checked by the caller to ensure that -// it's a "plugin" type. -func (c *Core) reloadPluginCommon(ctx context.Context, entry *MountEntry, isAuth bool) error { +// reloadBackendCommon is a generic method to reload a backend provided a +// MountEntry. +func (c *Core) reloadBackendCommon(ctx context.Context, entry *MountEntry, isAuth bool) error { path := entry.Path if isAuth { @@ -92,6 +91,11 @@ func (c *Core) reloadPluginCommon(ctx context.Context, entry *MountEntry, isAuth re := raw.(*routeEntry) + // Grab the lock, this allows requests to drain before we cleanup the + // client. + re.l.Lock() + defer re.l.Unlock() + // Only call Cleanup if backend is initialized if re.backend != nil { // Call backend's Cleanup routine @@ -101,18 +105,14 @@ func (c *Core) reloadPluginCommon(ctx context.Context, entry *MountEntry, isAuth view := re.storageView sysView := c.mountEntrySysView(entry) - conf := make(map[string]string) - if entry.Config.PluginName != "" { - conf["plugin_name"] = entry.Config.PluginName - } var backend logical.Backend var err error if !isAuth { // Dispense a new backend - backend, err = c.newLogicalBackend(ctx, entry.Type, sysView, view, conf) + backend, err = c.newLogicalBackend(ctx, entry, sysView, view) } else { - backend, err = c.newCredentialBackend(ctx, entry.Type, sysView, view, conf) + backend, err = c.newCredentialBackend(ctx, entry, sysView, view) } if err != nil { return err diff --git a/vault/request_handling.go b/vault/request_handling.go index 98a4759bd..8cbc01044 100644 --- a/vault/request_handling.go +++ b/vault/request_handling.go @@ -312,14 +312,39 @@ func (c *Core) handleRequest(ctx context.Context, req *logical.Request) (retResp // KV mounts should return the TTL but not register // for a lease as this provides a massive slowdown registerLease := true - matchingBackend := c.router.MatchingBackend(req.Path) - if matchingBackend == nil { - c.logger.Error("core: unable to retrieve kv backend from router") + + matchingMountEntry := c.router.MatchingMountEntry(req.Path) + if matchingMountEntry == nil { + c.logger.Error("core: unable to retrieve kv mount entry from router") retErr = multierror.Append(retErr, ErrInternalError) return nil, auth, retErr } - if ptbe, ok := matchingBackend.(*PassthroughBackend); ok { - if !ptbe.GeneratesLeases() { + + switch matchingMountEntry.Type { + case "kv", "generic": + // If we are kv type, first see if we are an older passthrough + // backend, and otherwise check the mount entry options. + matchingBackend := c.router.MatchingBackend(req.Path) + if matchingBackend == nil { + c.logger.Error("core: unable to retrieve kv backend from router") + retErr = multierror.Append(retErr, ErrInternalError) + return nil, auth, retErr + } + + if ptbe, ok := matchingBackend.(*PassthroughBackend); ok { + if !ptbe.GeneratesLeases() { + registerLease = false + resp.Secret.Renewable = false + } + } else if matchingMountEntry.Options == nil || matchingMountEntry.Options["leased_passthrough"] != "true" { + registerLease = false + resp.Secret.Renewable = false + } + + case "plugin": + // If we are a plugin type and the plugin name is "kv" check the + // mount entry options. + if matchingMountEntry.Config.PluginName == "kv" && (matchingMountEntry.Options == nil || matchingMountEntry.Options["leased_passthrough"] != "true") { registerLease = false resp.Secret.Renewable = false } diff --git a/vault/router.go b/vault/router.go index 2edebe045..209c29856 100644 --- a/vault/router.go +++ b/vault/router.go @@ -10,6 +10,7 @@ import ( "github.com/armon/go-metrics" "github.com/armon/go-radix" + "github.com/hashicorp/vault/helper/consts" "github.com/hashicorp/vault/helper/salt" "github.com/hashicorp/vault/logical" ) @@ -47,6 +48,7 @@ type routeEntry struct { storagePrefix string rootPaths atomic.Value loginPaths atomic.Value + l sync.RWMutex } type validateMountResponse struct { @@ -400,6 +402,11 @@ func (r *Router) routeCommon(ctx context.Context, req *logical.Request, existenc strings.Replace(mount, "/", "-", -1)}, time.Now()) re := raw.(*routeEntry) + // Grab a read lock on the route entry, this protects against the backend + // being reloaded during a request. + re.l.RLock() + defer re.l.RUnlock() + // Filtered mounts will have a nil backend if re.backend == nil { return logical.ErrorResponse(fmt.Sprintf("no handler for route '%s'", req.Path)), false, false, logical.ErrUnsupportedPath @@ -470,6 +477,13 @@ func (r *Router) routeCommon(ctx context.Context, req *logical.Request, existenc headers := req.Headers req.Headers = nil + // Whitelist the X-Vault-Kv-Client header for use in the kv backend. + if val, ok := headers[consts.VaultKVCLIClientHeader]; ok { + req.Headers = map[string][]string{ + consts.VaultKVCLIClientHeader: val, + } + } + // Cache the wrap info of the request var wrapInfo *logical.RequestWrapInfo if req.WrapInfo != nil { diff --git a/vault/testing.go b/vault/testing.go index 2bbd91950..f6535edf7 100644 --- a/vault/testing.go +++ b/vault/testing.go @@ -322,7 +322,7 @@ func testTokenStore(t testing.T, c *Core) *TokenStore { view := NewBarrierView(c.barrier, credentialBarrierPrefix+me.UUID+"/") sysView := c.mountEntrySysView(me) - tokenstore, _ := c.newCredentialBackend(context.Background(), "token", sysView, view, nil) + tokenstore, _ := c.newCredentialBackend(context.Background(), me, sysView, view) ts := tokenstore.(*TokenStore) err = c.router.Unmount(context.Background(), "auth/token/")