Audit HMAC values on AuthConfig (#4077)
* Add audit hmac values to AuthConfigInput and AuthConfigOutput, fix docs * docs: Add ttl params to auth enable endpoint * Rewording of go string to simply string * Add audit hmac keys as CLI flags on auth/secrets enable * Fix copypasta mistake * Add audit hmac keys to auth and secrets list * Only set config values if they exist * Fix http sys/auth tests * More auth plugin_name test fixes * Pass API values into MountEntry's config when creating auth/secrets mount * Update usage wording
This commit is contained in:
parent
0216f99727
commit
034f83f1cd
@ -91,9 +91,11 @@ type EnableAuthOptions struct {
|
||||
}
|
||||
|
||||
type AuthConfigInput 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"`
|
||||
PluginName string `json:"plugin_name,omitempty" structs:"plugin_name,omitempty" mapstructure:"plugin_name"`
|
||||
DefaultLeaseTTL string `json:"default_lease_ttl" structs:"default_lease_ttl" mapstructure:"default_lease_ttl"`
|
||||
MaxLeaseTTL string `json:"max_lease_ttl" structs:"max_lease_ttl" mapstructure:"max_lease_ttl"`
|
||||
PluginName string `json:"plugin_name,omitempty" structs:"plugin_name,omitempty" mapstructure:"plugin_name"`
|
||||
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"`
|
||||
}
|
||||
|
||||
type AuthMount struct {
|
||||
@ -106,7 +108,9 @@ type AuthMount struct {
|
||||
}
|
||||
|
||||
type AuthConfigOutput 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"`
|
||||
PluginName string `json:"plugin_name,omitempty" structs:"plugin_name,omitempty" mapstructure:"plugin_name"`
|
||||
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"`
|
||||
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"`
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
@ -16,13 +17,15 @@ var _ cli.CommandAutocomplete = (*AuthEnableCommand)(nil)
|
||||
type AuthEnableCommand struct {
|
||||
*BaseCommand
|
||||
|
||||
flagDescription string
|
||||
flagPath string
|
||||
flagDefaultLeaseTTL time.Duration
|
||||
flagMaxLeaseTTL time.Duration
|
||||
flagPluginName string
|
||||
flagLocal bool
|
||||
flagSealWrap bool
|
||||
flagDescription string
|
||||
flagPath string
|
||||
flagDefaultLeaseTTL time.Duration
|
||||
flagMaxLeaseTTL time.Duration
|
||||
flagAuditNonHMACRequestKeys []string
|
||||
flagAuditNonHMACResponseKeys []string
|
||||
flagPluginName string
|
||||
flagLocal bool
|
||||
flagSealWrap bool
|
||||
}
|
||||
|
||||
func (c *AuthEnableCommand) Synopsis() string {
|
||||
@ -96,6 +99,20 @@ func (c *AuthEnableCommand) Flags() *FlagSets {
|
||||
"TTL.",
|
||||
})
|
||||
|
||||
f.StringSliceVar(&StringSliceVar{
|
||||
Name: flagNameAuditNonHMACRequestKeys,
|
||||
Target: &c.flagAuditNonHMACRequestKeys,
|
||||
Usage: "Comma-separated string or list of keys that will not be HMAC'd by audit" +
|
||||
"devices in the request data object.",
|
||||
})
|
||||
|
||||
f.StringSliceVar(&StringSliceVar{
|
||||
Name: flagNameAuditNonHMACResponseKeys,
|
||||
Target: &c.flagAuditNonHMACResponseKeys,
|
||||
Usage: "Comma-separated string or list of keys that will not be HMAC'd by audit" +
|
||||
"devices in the response data object.",
|
||||
})
|
||||
|
||||
f.StringVar(&StringVar{
|
||||
Name: "plugin-name",
|
||||
Target: &c.flagPluginName,
|
||||
@ -170,7 +187,7 @@ func (c *AuthEnableCommand) Run(args []string) int {
|
||||
// Append a trailing slash to indicate it's a path in output
|
||||
authPath = ensureTrailingSlash(authPath)
|
||||
|
||||
if err := client.Sys().EnableAuthWithOptions(authPath, &api.EnableAuthOptions{
|
||||
authOpts := &api.EnableAuthOptions{
|
||||
Type: authType,
|
||||
Description: c.flagDescription,
|
||||
Local: c.flagLocal,
|
||||
@ -180,7 +197,20 @@ func (c *AuthEnableCommand) Run(args []string) int {
|
||||
MaxLeaseTTL: c.flagMaxLeaseTTL.String(),
|
||||
PluginName: c.flagPluginName,
|
||||
},
|
||||
}); err != nil {
|
||||
}
|
||||
|
||||
// Set these values only if they are provided in the CLI
|
||||
f.Visit(func(fl *flag.Flag) {
|
||||
if fl.Name == flagNameAuditNonHMACRequestKeys {
|
||||
authOpts.Config.AuditNonHMACRequestKeys = c.flagAuditNonHMACRequestKeys
|
||||
}
|
||||
|
||||
if fl.Name == flagNameAuditNonHMACResponseKeys {
|
||||
authOpts.Config.AuditNonHMACRequestKeys = c.flagAuditNonHMACResponseKeys
|
||||
}
|
||||
})
|
||||
|
||||
if err := client.Sys().EnableAuthWithOptions(authPath, authOpts); err != nil {
|
||||
c.UI.Error(fmt.Sprintf("Error enabling %s auth: %s", authType, err))
|
||||
return 2
|
||||
}
|
||||
|
@ -332,6 +332,12 @@ func (f *FlagSets) Args() []string {
|
||||
return f.mainSet.Args()
|
||||
}
|
||||
|
||||
// Visit visits the flags in lexicographical order, calling fn for each. It
|
||||
// visits only those flags that have been set.
|
||||
func (f *FlagSets) Visit(fn func(*flag.Flag)) {
|
||||
f.mainSet.Visit(fn)
|
||||
}
|
||||
|
||||
// Help builds custom help for this command, grouping by flag set.
|
||||
func (fs *FlagSets) Help() string {
|
||||
var out bytes.Buffer
|
||||
|
@ -71,6 +71,11 @@ const (
|
||||
EnvVaultCLINoColor = `VAULT_CLI_NO_COLOR`
|
||||
// EnvVaultFormat is the output format
|
||||
EnvVaultFormat = `VAULT_FORMAT`
|
||||
|
||||
// flagNameAuditNonHMACRequestKeys is the flag name used for auth/secrets enable
|
||||
flagNameAuditNonHMACRequestKeys = "audit-non-hmac-request-keys"
|
||||
// flagNameAuditNonHMACResponseKeys is the flag name used for auth/secrets enable
|
||||
flagNameAuditNonHMACResponseKeys = "audit-non-hmac-response-keys"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -1,6 +1,7 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
@ -16,14 +17,16 @@ var _ cli.CommandAutocomplete = (*SecretsEnableCommand)(nil)
|
||||
type SecretsEnableCommand struct {
|
||||
*BaseCommand
|
||||
|
||||
flagDescription string
|
||||
flagPath string
|
||||
flagDefaultLeaseTTL time.Duration
|
||||
flagMaxLeaseTTL time.Duration
|
||||
flagForceNoCache bool
|
||||
flagPluginName string
|
||||
flagLocal bool
|
||||
flagSealWrap bool
|
||||
flagDescription string
|
||||
flagPath string
|
||||
flagDefaultLeaseTTL time.Duration
|
||||
flagMaxLeaseTTL time.Duration
|
||||
flagAuditNonHMACRequestKeys []string
|
||||
flagAuditNonHMACResponseKeys []string
|
||||
flagForceNoCache bool
|
||||
flagPluginName string
|
||||
flagLocal bool
|
||||
flagSealWrap bool
|
||||
}
|
||||
|
||||
func (c *SecretsEnableCommand) Synopsis() string {
|
||||
@ -104,6 +107,20 @@ func (c *SecretsEnableCommand) Flags() *FlagSets {
|
||||
"TTL.",
|
||||
})
|
||||
|
||||
f.StringSliceVar(&StringSliceVar{
|
||||
Name: flagNameAuditNonHMACRequestKeys,
|
||||
Target: &c.flagAuditNonHMACRequestKeys,
|
||||
Usage: "Comma-separated string or list of keys that will not be HMAC'd by audit" +
|
||||
"devices in the request data object.",
|
||||
})
|
||||
|
||||
f.StringSliceVar(&StringSliceVar{
|
||||
Name: flagNameAuditNonHMACResponseKeys,
|
||||
Target: &c.flagAuditNonHMACResponseKeys,
|
||||
Usage: "Comma-separated string or list of keys that will not be HMAC'd by audit" +
|
||||
"devices in the response data object.",
|
||||
})
|
||||
|
||||
f.BoolVar(&BoolVar{
|
||||
Name: "force-no-cache",
|
||||
Target: &c.flagForceNoCache,
|
||||
@ -202,6 +219,17 @@ func (c *SecretsEnableCommand) Run(args []string) int {
|
||||
},
|
||||
}
|
||||
|
||||
// Set these values only if they are provided in the CLI
|
||||
f.Visit(func(fl *flag.Flag) {
|
||||
if fl.Name == flagNameAuditNonHMACRequestKeys {
|
||||
mountInput.Config.AuditNonHMACRequestKeys = c.flagAuditNonHMACRequestKeys
|
||||
}
|
||||
|
||||
if fl.Name == flagNameAuditNonHMACResponseKeys {
|
||||
mountInput.Config.AuditNonHMACRequestKeys = c.flagAuditNonHMACResponseKeys
|
||||
}
|
||||
})
|
||||
|
||||
if err := client.Sys().Mount(mountPath, mountInput); err != nil {
|
||||
c.UI.Error(fmt.Sprintf("Error enabling: %s", err))
|
||||
return 2
|
||||
|
@ -31,6 +31,7 @@ func TestSysAuth(t *testing.T) {
|
||||
"config": map[string]interface{}{
|
||||
"default_lease_ttl": json.Number("0"),
|
||||
"max_lease_ttl": json.Number("0"),
|
||||
"plugin_name": "",
|
||||
},
|
||||
"local": false,
|
||||
"seal_wrap": false,
|
||||
@ -42,6 +43,7 @@ func TestSysAuth(t *testing.T) {
|
||||
"config": map[string]interface{}{
|
||||
"default_lease_ttl": json.Number("0"),
|
||||
"max_lease_ttl": json.Number("0"),
|
||||
"plugin_name": "",
|
||||
},
|
||||
"local": false,
|
||||
"seal_wrap": false,
|
||||
@ -93,6 +95,7 @@ func TestSysEnableAuth(t *testing.T) {
|
||||
"config": map[string]interface{}{
|
||||
"default_lease_ttl": json.Number("0"),
|
||||
"max_lease_ttl": json.Number("0"),
|
||||
"plugin_name": "",
|
||||
},
|
||||
"local": false,
|
||||
"seal_wrap": false,
|
||||
@ -103,6 +106,7 @@ func TestSysEnableAuth(t *testing.T) {
|
||||
"config": map[string]interface{}{
|
||||
"default_lease_ttl": json.Number("0"),
|
||||
"max_lease_ttl": json.Number("0"),
|
||||
"plugin_name": "",
|
||||
},
|
||||
"local": false,
|
||||
"seal_wrap": false,
|
||||
@ -114,6 +118,7 @@ func TestSysEnableAuth(t *testing.T) {
|
||||
"config": map[string]interface{}{
|
||||
"default_lease_ttl": json.Number("0"),
|
||||
"max_lease_ttl": json.Number("0"),
|
||||
"plugin_name": "",
|
||||
},
|
||||
"local": false,
|
||||
"seal_wrap": false,
|
||||
@ -124,6 +129,7 @@ func TestSysEnableAuth(t *testing.T) {
|
||||
"config": map[string]interface{}{
|
||||
"default_lease_ttl": json.Number("0"),
|
||||
"max_lease_ttl": json.Number("0"),
|
||||
"plugin_name": "",
|
||||
},
|
||||
"local": false,
|
||||
"seal_wrap": false,
|
||||
@ -176,6 +182,7 @@ func TestSysDisableAuth(t *testing.T) {
|
||||
"config": map[string]interface{}{
|
||||
"default_lease_ttl": json.Number("0"),
|
||||
"max_lease_ttl": json.Number("0"),
|
||||
"plugin_name": "",
|
||||
},
|
||||
"description": "token based credentials",
|
||||
"type": "token",
|
||||
@ -187,6 +194,7 @@ func TestSysDisableAuth(t *testing.T) {
|
||||
"config": map[string]interface{}{
|
||||
"default_lease_ttl": json.Number("0"),
|
||||
"max_lease_ttl": json.Number("0"),
|
||||
"plugin_name": "",
|
||||
},
|
||||
"description": "token based credentials",
|
||||
"type": "token",
|
||||
|
@ -1443,15 +1443,22 @@ func (b *SystemBackend) handleMountTable(ctx context.Context, req *logical.Reque
|
||||
"type": entry.Type,
|
||||
"description": entry.Description,
|
||||
"accessor": entry.Accessor,
|
||||
"config": map[string]interface{}{
|
||||
"default_lease_ttl": int64(entry.Config.DefaultLeaseTTL.Seconds()),
|
||||
"max_lease_ttl": int64(entry.Config.MaxLeaseTTL.Seconds()),
|
||||
"force_no_cache": entry.Config.ForceNoCache,
|
||||
"plugin_name": entry.Config.PluginName,
|
||||
},
|
||||
"local": entry.Local,
|
||||
"seal_wrap": entry.SealWrap,
|
||||
"local": entry.Local,
|
||||
"seal_wrap": entry.SealWrap,
|
||||
}
|
||||
entryConfig := map[string]interface{}{
|
||||
"default_lease_ttl": int64(entry.Config.DefaultLeaseTTL.Seconds()),
|
||||
"max_lease_ttl": int64(entry.Config.MaxLeaseTTL.Seconds()),
|
||||
"force_no_cache": entry.Config.ForceNoCache,
|
||||
"plugin_name": entry.Config.PluginName,
|
||||
}
|
||||
if rawVal, ok := entry.synthesizedConfigCache.Load("audit_non_hmac_request_keys"); ok {
|
||||
entryConfig["audit_non_hmac_request_keys"] = rawVal.([]string)
|
||||
}
|
||||
if rawVal, ok := entry.synthesizedConfigCache.Load("audit_non_hmac_response_keys"); ok {
|
||||
entryConfig["audit_non_hmac_response_keys"] = rawVal.([]string)
|
||||
}
|
||||
info["config"] = entryConfig
|
||||
resp.Data[entry.Path] = info
|
||||
}
|
||||
|
||||
@ -1553,6 +1560,14 @@ func (b *SystemBackend) handleMount(ctx context.Context, req *logical.Request, d
|
||||
config.ForceNoCache = true
|
||||
}
|
||||
|
||||
if len(apiConfig.AuditNonHMACRequestKeys) > 0 {
|
||||
config.AuditNonHMACRequestKeys = apiConfig.AuditNonHMACRequestKeys
|
||||
}
|
||||
|
||||
if len(apiConfig.AuditNonHMACResponseKeys) > 0 {
|
||||
config.AuditNonHMACResponseKeys = apiConfig.AuditNonHMACResponseKeys
|
||||
}
|
||||
|
||||
// Create the mount entry
|
||||
me := &MountEntry{
|
||||
Table: mountTableType,
|
||||
@ -2028,13 +2043,21 @@ func (b *SystemBackend) handleAuthTable(ctx context.Context, req *logical.Reques
|
||||
"type": entry.Type,
|
||||
"description": entry.Description,
|
||||
"accessor": entry.Accessor,
|
||||
"config": map[string]interface{}{
|
||||
"default_lease_ttl": int64(entry.Config.DefaultLeaseTTL.Seconds()),
|
||||
"max_lease_ttl": int64(entry.Config.MaxLeaseTTL.Seconds()),
|
||||
},
|
||||
"local": entry.Local,
|
||||
"seal_wrap": entry.SealWrap,
|
||||
"local": entry.Local,
|
||||
"seal_wrap": entry.SealWrap,
|
||||
}
|
||||
entryConfig := map[string]interface{}{
|
||||
"default_lease_ttl": int64(entry.Config.DefaultLeaseTTL.Seconds()),
|
||||
"max_lease_ttl": int64(entry.Config.MaxLeaseTTL.Seconds()),
|
||||
"plugin_name": entry.Config.PluginName,
|
||||
}
|
||||
if rawVal, ok := entry.synthesizedConfigCache.Load("audit_non_hmac_request_keys"); ok {
|
||||
entryConfig["audit_non_hmac_request_keys"] = rawVal.([]string)
|
||||
}
|
||||
if rawVal, ok := entry.synthesizedConfigCache.Load("audit_non_hmac_response_keys"); ok {
|
||||
entryConfig["audit_non_hmac_response_keys"] = rawVal.([]string)
|
||||
}
|
||||
info["config"] = entryConfig
|
||||
resp.Data[entry.Path] = info
|
||||
}
|
||||
return resp, nil
|
||||
@ -2129,6 +2152,14 @@ func (b *SystemBackend) handleEnableAuth(ctx context.Context, req *logical.Reque
|
||||
|
||||
path = sanitizeMountPath(path)
|
||||
|
||||
if len(apiConfig.AuditNonHMACRequestKeys) > 0 {
|
||||
config.AuditNonHMACRequestKeys = apiConfig.AuditNonHMACRequestKeys
|
||||
}
|
||||
|
||||
if len(apiConfig.AuditNonHMACResponseKeys) > 0 {
|
||||
config.AuditNonHMACResponseKeys = apiConfig.AuditNonHMACResponseKeys
|
||||
}
|
||||
|
||||
// Create the mount entry
|
||||
me := &MountEntry{
|
||||
Table: credentialTableType,
|
||||
|
@ -1388,6 +1388,7 @@ func TestSystemBackend_authTable(t *testing.T) {
|
||||
"config": map[string]interface{}{
|
||||
"default_lease_ttl": int64(0),
|
||||
"max_lease_ttl": int64(0),
|
||||
"plugin_name": "",
|
||||
},
|
||||
"local": false,
|
||||
"seal_wrap": false,
|
||||
@ -1438,6 +1439,7 @@ func TestSystemBackend_enableAuth(t *testing.T) {
|
||||
"config": map[string]interface{}{
|
||||
"default_lease_ttl": int64(2100),
|
||||
"max_lease_ttl": int64(2700),
|
||||
"plugin_name": "",
|
||||
},
|
||||
"local": true,
|
||||
"seal_wrap": true,
|
||||
@ -1449,6 +1451,7 @@ func TestSystemBackend_enableAuth(t *testing.T) {
|
||||
"config": map[string]interface{}{
|
||||
"default_lease_ttl": int64(0),
|
||||
"max_lease_ttl": int64(0),
|
||||
"plugin_name": "",
|
||||
},
|
||||
"local": false,
|
||||
"seal_wrap": false,
|
||||
|
@ -77,7 +77,20 @@ For example, enable the "foo" auth method will make it accessible at
|
||||
- `config` `(map<string|string>: nil)` – Specifies configuration options for
|
||||
this auth method. These are the possible values:
|
||||
|
||||
- `plugin_name`
|
||||
- `default_lease_ttl` `(string: "")` - The default lease duration, specified
|
||||
as a string duration like "5s" or "30m".
|
||||
|
||||
- `max_lease_ttl` `(string: "")` - The maximum lease duration, specified as a
|
||||
string duration like "5s" or "30m".
|
||||
|
||||
- `plugin_name` `(string: "")` - The name of the plugin in the plugin catalog
|
||||
to use.
|
||||
|
||||
- `audit_non_hmac_request_keys` `(array: [])` - Comma-separated list of keys
|
||||
that will not be HMAC'd by audit devices in the request data object.
|
||||
|
||||
- `audit_non_hmac_response_keys` `(array: [])` - Comma-separated list of keys
|
||||
that will not be HMAC'd by audit devices in the response data object.
|
||||
|
||||
The plugin_name can be provided in the config map or as a top-level option,
|
||||
with the former taking precedence.
|
||||
|
@ -80,23 +80,29 @@ This endpoint enables a new secrets engine at the given path.
|
||||
- `config` `(map<string|string>: nil)` – Specifies configuration options for
|
||||
this mount. This is an object with four possible values:
|
||||
|
||||
- `default_lease_ttl` `(string: "")` - the default lease duration, specified
|
||||
as a go string duration like "5s" or "30m".
|
||||
- `default_lease_ttl` `(string: "")` - The default lease duration, specified
|
||||
as a string duration like "5s" or "30m".
|
||||
|
||||
- `max_lease_ttl` `(string: "")` - the maximum lease duration, specified as
|
||||
a go string duration like "5s" or "30m".
|
||||
- `max_lease_ttl` `(string: "")` - The maximum lease duration, specified as a
|
||||
string duration like "5s" or "30m".
|
||||
|
||||
- `force_no_cache` `(bool: false)` - disable caching.
|
||||
- `force_no_cache` `(bool: false)` - Disable caching.
|
||||
|
||||
- `plugin_name` `(string: "")` - the name of the plugin in the plugin
|
||||
catalog to use.
|
||||
- `plugin_name` `(string: "")` - The name of the plugin in the plugin catalog
|
||||
to use.
|
||||
|
||||
- `audit_non_hmac_request_keys` `(array: [])` - Comma-separated list of keys
|
||||
that will not be HMAC'd by audit devices in the request data object.
|
||||
|
||||
- `audit_non_hmac_response_keys` `(array: [])` - Comma-separated list of keys
|
||||
that will not be HMAC'd by audit devices in the response data object.
|
||||
|
||||
These control the default and maximum lease time-to-live, force
|
||||
disabling backend caching, and option plugin name for plugin backends
|
||||
respectively. The first three options override the global defaults if
|
||||
set on a specific mount. The plugin_name can be provided in the config
|
||||
map or as a top-level option, with the former taking precedence.
|
||||
|
||||
|
||||
When used with supported seals (`pkcs11`, `awskms`, etc.), `seal_wrap`
|
||||
causes key material for supporting mounts to be wrapped by the seal's
|
||||
encryption capability. This is currently only supported for `transit` and
|
||||
|
Loading…
Reference in New Issue
Block a user