Add deprecation status to auth/secrets list (#16849)
* auth: Add Deprecation Status to auth list -detailed * secrets: Add Deprecation Status to secrets list -detailed * Add changelog entry for deprecation status list
This commit is contained in:
parent
ae8622ba7d
commit
2c16be25e3
|
@ -286,6 +286,7 @@ type MountOutput struct {
|
||||||
RunningVersion string `json:"running_version"`
|
RunningVersion string `json:"running_version"`
|
||||||
Sha string `json:"sha"`
|
Sha string `json:"sha"`
|
||||||
RunningSha string `json:"running_sha"`
|
RunningSha string `json:"running_sha"`
|
||||||
|
DeprecationStatus string `json:"deprecation_status" mapstructure:"deprecation_status"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type MountConfigOutput struct {
|
type MountConfigOutput struct {
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
```release-note:change
|
||||||
|
auth: `GET /sys/auth` endpoint now returns an additional `deprecation_status` field in the response data for builtins.
|
||||||
|
```
|
||||||
|
```release-note:change
|
||||||
|
auth: `GET /sys/auth/:name` endpoint now returns an additional `deprecation_status` field in the response data for builtins.
|
||||||
|
```
|
||||||
|
```release-note:change
|
||||||
|
secrets: `GET /sys/mounts` endpoint now returns an additional `deprecation_status` field in the response data for builtins.
|
||||||
|
```
|
||||||
|
```release-note:change
|
||||||
|
secrets: `GET /sys/mounts/:name` endpoint now returns an additional `deprecation_status` field in the response data for builtins.
|
||||||
|
```
|
||||||
|
```release-note:improvement
|
||||||
|
cli: `auth` and `secrets` list `-detailed` commands now show Deprecation Status for builtin plugins.
|
||||||
|
```
|
|
@ -145,7 +145,7 @@ func (c *AuthListCommand) detailedMounts(auths map[string]*api.AuthMount) []stri
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
out := []string{"Path | Plugin | Accessor | Default TTL | Max TTL | Token Type | Replication | Seal Wrap | External Entropy Access | Options | Description | UUID | Version"}
|
out := []string{"Path | Plugin | Accessor | Default TTL | Max TTL | Token Type | Replication | Seal Wrap | External Entropy Access | Options | Description | UUID | Version | Deprecation Status"}
|
||||||
for _, path := range paths {
|
for _, path := range paths {
|
||||||
mount := auths[path]
|
mount := auths[path]
|
||||||
|
|
||||||
|
@ -162,7 +162,7 @@ func (c *AuthListCommand) detailedMounts(auths map[string]*api.AuthMount) []stri
|
||||||
pluginName = mount.Config.PluginName
|
pluginName = mount.Config.PluginName
|
||||||
}
|
}
|
||||||
|
|
||||||
out = append(out, fmt.Sprintf("%s | %s | %s | %s | %s | %s | %s | %t | %v | %s | %s | %s | %s",
|
out = append(out, fmt.Sprintf("%s | %s | %s | %s | %s | %s | %s | %t | %v | %s | %s | %s | %s | %s",
|
||||||
path,
|
path,
|
||||||
pluginName,
|
pluginName,
|
||||||
mount.Accessor,
|
mount.Accessor,
|
||||||
|
@ -176,6 +176,7 @@ func (c *AuthListCommand) detailedMounts(auths map[string]*api.AuthMount) []stri
|
||||||
mount.Description,
|
mount.Description,
|
||||||
mount.UUID,
|
mount.UUID,
|
||||||
mount.Version,
|
mount.Version,
|
||||||
|
mount.DeprecationStatus,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -145,7 +145,7 @@ func (c *SecretsListCommand) detailedMounts(mounts map[string]*api.MountOutput)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
out := []string{"Path | Plugin | Accessor | Default TTL | Max TTL | Force No Cache | Replication | Seal Wrap | External Entropy Access | Options | Description | UUID "}
|
out := []string{"Path | Plugin | Accessor | Default TTL | Max TTL | Force No Cache | Replication | Seal Wrap | External Entropy Access | Options | Description | UUID | Deprecation Status"}
|
||||||
for _, path := range paths {
|
for _, path := range paths {
|
||||||
mount := mounts[path]
|
mount := mounts[path]
|
||||||
|
|
||||||
|
@ -162,7 +162,7 @@ func (c *SecretsListCommand) detailedMounts(mounts map[string]*api.MountOutput)
|
||||||
pluginName = mount.Config.PluginName
|
pluginName = mount.Config.PluginName
|
||||||
}
|
}
|
||||||
|
|
||||||
out = append(out, fmt.Sprintf("%s | %s | %s | %s | %s | %t | %s | %t | %v | %s | %s | %s",
|
out = append(out, fmt.Sprintf("%s | %s | %s | %s | %s | %t | %s | %t | %v | %s | %s | %s | %s",
|
||||||
path,
|
path,
|
||||||
pluginName,
|
pluginName,
|
||||||
mount.Accessor,
|
mount.Accessor,
|
||||||
|
@ -175,6 +175,7 @@ func (c *SecretsListCommand) detailedMounts(mounts map[string]*api.MountOutput)
|
||||||
mount.Options,
|
mount.Options,
|
||||||
mount.Description,
|
mount.Description,
|
||||||
mount.UUID,
|
mount.UUID,
|
||||||
|
mount.DeprecationStatus,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,7 @@ func TestSecretsListCommand_Run(t *testing.T) {
|
||||||
{
|
{
|
||||||
"detailed",
|
"detailed",
|
||||||
[]string{"-detailed"},
|
[]string{"-detailed"},
|
||||||
"Default TTL",
|
"Deprecation Status",
|
||||||
0,
|
0,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,7 +96,7 @@ func TestSysEnableAuth(t *testing.T) {
|
||||||
TestServerAuth(t, addr, token)
|
TestServerAuth(t, addr, token)
|
||||||
|
|
||||||
resp := testHttpPost(t, token, addr+"/v1/sys/auth/foo", map[string]interface{}{
|
resp := testHttpPost(t, token, addr+"/v1/sys/auth/foo", map[string]interface{}{
|
||||||
"type": "noop",
|
"type": "approle",
|
||||||
"description": "foo",
|
"description": "foo",
|
||||||
})
|
})
|
||||||
testResponseStatus(t, resp, 204)
|
testResponseStatus(t, resp, 204)
|
||||||
|
@ -114,8 +114,9 @@ func TestSysEnableAuth(t *testing.T) {
|
||||||
"data": map[string]interface{}{
|
"data": map[string]interface{}{
|
||||||
"foo/": map[string]interface{}{
|
"foo/": map[string]interface{}{
|
||||||
"description": "foo",
|
"description": "foo",
|
||||||
"type": "noop",
|
"type": "approle",
|
||||||
"external_entropy_access": false,
|
"external_entropy_access": false,
|
||||||
|
"deprecation_status": "supported",
|
||||||
"config": map[string]interface{}{
|
"config": map[string]interface{}{
|
||||||
"default_lease_ttl": json.Number("0"),
|
"default_lease_ttl": json.Number("0"),
|
||||||
"max_lease_ttl": json.Number("0"),
|
"max_lease_ttl": json.Number("0"),
|
||||||
|
@ -151,8 +152,9 @@ func TestSysEnableAuth(t *testing.T) {
|
||||||
},
|
},
|
||||||
"foo/": map[string]interface{}{
|
"foo/": map[string]interface{}{
|
||||||
"description": "foo",
|
"description": "foo",
|
||||||
"type": "noop",
|
"type": "approle",
|
||||||
"external_entropy_access": false,
|
"external_entropy_access": false,
|
||||||
|
"deprecation_status": "supported",
|
||||||
"config": map[string]interface{}{
|
"config": map[string]interface{}{
|
||||||
"default_lease_ttl": json.Number("0"),
|
"default_lease_ttl": json.Number("0"),
|
||||||
"max_lease_ttl": json.Number("0"),
|
"max_lease_ttl": json.Number("0"),
|
||||||
|
|
|
@ -879,7 +879,7 @@ func (b *SystemBackend) handleRekeyDeleteRecovery(ctx context.Context, req *logi
|
||||||
return b.handleRekeyDelete(ctx, req, data, true)
|
return b.handleRekeyDelete(ctx, req, data, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func mountInfo(entry *MountEntry) map[string]interface{} {
|
func (b *SystemBackend) mountInfo(ctx context.Context, entry *MountEntry) map[string]interface{} {
|
||||||
info := map[string]interface{}{
|
info := map[string]interface{}{
|
||||||
"type": entry.Type,
|
"type": entry.Type,
|
||||||
"description": entry.Description,
|
"description": entry.Description,
|
||||||
|
@ -923,6 +923,11 @@ func mountInfo(entry *MountEntry) map[string]interface{} {
|
||||||
entryConfig["token_type"] = entry.Config.TokenType.String()
|
entryConfig["token_type"] = entry.Config.TokenType.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add deprecation status only if it exists
|
||||||
|
builtinType := b.Core.builtinTypeFromMountEntry(ctx, entry)
|
||||||
|
if status, ok := b.Core.builtinRegistry.DeprecationStatus(entry.Type, builtinType); ok {
|
||||||
|
info["deprecation_status"] = status.String()
|
||||||
|
}
|
||||||
info["config"] = entryConfig
|
info["config"] = entryConfig
|
||||||
|
|
||||||
return info
|
return info
|
||||||
|
@ -957,7 +962,8 @@ func (b *SystemBackend) handleMountTable(ctx context.Context, req *logical.Reque
|
||||||
}
|
}
|
||||||
|
|
||||||
// Populate mount info
|
// Populate mount info
|
||||||
info := mountInfo(entry)
|
info := b.mountInfo(ctx, entry)
|
||||||
|
|
||||||
resp.Data[entry.Path] = info
|
resp.Data[entry.Path] = info
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1159,7 +1165,7 @@ func (b *SystemBackend) handleReadMount(ctx context.Context, req *logical.Reques
|
||||||
}
|
}
|
||||||
|
|
||||||
return &logical.Response{
|
return &logical.Response{
|
||||||
Data: mountInfo(entry),
|
Data: b.mountInfo(ctx, entry),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2149,7 +2155,7 @@ func (b *SystemBackend) handleAuthTable(ctx context.Context, req *logical.Reques
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
info := mountInfo(entry)
|
info := b.mountInfo(ctx, entry)
|
||||||
resp.Data[entry.Path] = info
|
resp.Data[entry.Path] = info
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2183,7 +2189,7 @@ func (b *SystemBackend) handleReadAuth(ctx context.Context, req *logical.Request
|
||||||
}
|
}
|
||||||
|
|
||||||
return &logical.Response{
|
return &logical.Response{
|
||||||
Data: mountInfo(entry),
|
Data: b.mountInfo(ctx, entry),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3849,7 +3855,7 @@ func (b *SystemBackend) pathInternalUIMountsRead(ctx context.Context, req *logic
|
||||||
if ns.ID == entry.NamespaceID && hasAccess(ctx, entry) {
|
if ns.ID == entry.NamespaceID && hasAccess(ctx, entry) {
|
||||||
if isAuthed {
|
if isAuthed {
|
||||||
// If this is an authed request return all the mount info
|
// If this is an authed request return all the mount info
|
||||||
secretMounts[entry.Path] = mountInfo(entry)
|
secretMounts[entry.Path] = b.mountInfo(ctx, entry)
|
||||||
} else {
|
} else {
|
||||||
secretMounts[entry.Path] = map[string]interface{}{
|
secretMounts[entry.Path] = map[string]interface{}{
|
||||||
"type": entry.Type,
|
"type": entry.Type,
|
||||||
|
@ -3876,7 +3882,7 @@ func (b *SystemBackend) pathInternalUIMountsRead(ctx context.Context, req *logic
|
||||||
if ns.ID == entry.NamespaceID && hasAccess(ctx, entry) {
|
if ns.ID == entry.NamespaceID && hasAccess(ctx, entry) {
|
||||||
if isAuthed {
|
if isAuthed {
|
||||||
// If this is an authed request return all the mount info
|
// If this is an authed request return all the mount info
|
||||||
authMounts[entry.Path] = mountInfo(entry)
|
authMounts[entry.Path] = b.mountInfo(ctx, entry)
|
||||||
} else {
|
} else {
|
||||||
authMounts[entry.Path] = map[string]interface{}{
|
authMounts[entry.Path] = map[string]interface{}{
|
||||||
"type": entry.Type,
|
"type": entry.Type,
|
||||||
|
@ -3934,7 +3940,7 @@ func (b *SystemBackend) pathInternalUIMountRead(ctx context.Context, req *logica
|
||||||
return errResp, logical.ErrPermissionDenied
|
return errResp, logical.ErrPermissionDenied
|
||||||
}
|
}
|
||||||
resp := &logical.Response{
|
resp := &logical.Response{
|
||||||
Data: mountInfo(me),
|
Data: b.mountInfo(ctx, me),
|
||||||
}
|
}
|
||||||
resp.Data["path"] = me.Path
|
resp.Data["path"] = me.Path
|
||||||
|
|
||||||
|
|
|
@ -665,6 +665,43 @@ func (c *Core) mountInternal(ctx context.Context, entry *MountEntry, updateStora
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// builtinTypeFromMountEntry attempts to find a builtin PluginType associated
|
||||||
|
// with the specified MountEntry. Returns consts.PluginTypeUnknown if not found.
|
||||||
|
func (c *Core) builtinTypeFromMountEntry(ctx context.Context, entry *MountEntry) consts.PluginType {
|
||||||
|
if c.builtinRegistry == nil || entry == nil {
|
||||||
|
return consts.PluginTypeUnknown
|
||||||
|
}
|
||||||
|
|
||||||
|
builtinPluginType := func(name string, pluginType consts.PluginType) (consts.PluginType, bool) {
|
||||||
|
plugin, err := c.pluginCatalog.Get(ctx, name, pluginType, "")
|
||||||
|
if err == nil && plugin != nil && plugin.Builtin {
|
||||||
|
return plugin.Type, true
|
||||||
|
}
|
||||||
|
return consts.PluginTypeUnknown, false
|
||||||
|
}
|
||||||
|
|
||||||
|
// auth plugins have their own dedicated mount table
|
||||||
|
if pluginType, err := consts.ParsePluginType(entry.Table); err == nil {
|
||||||
|
if builtinType, ok := builtinPluginType(entry.Type, pluginType); ok {
|
||||||
|
return builtinType
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for possible matches
|
||||||
|
var builtinTypes []consts.PluginType
|
||||||
|
for _, pluginType := range [...]consts.PluginType{consts.PluginTypeSecrets, consts.PluginTypeDatabase} {
|
||||||
|
if builtinType, ok := builtinPluginType(entry.Type, pluginType); ok {
|
||||||
|
builtinTypes = append(builtinTypes, builtinType)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(builtinTypes) == 1 {
|
||||||
|
return builtinTypes[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
return consts.PluginTypeUnknown
|
||||||
|
}
|
||||||
|
|
||||||
// Unmount is used to unmount a path. The boolean indicates whether the mount
|
// Unmount is used to unmount a path. The boolean indicates whether the mount
|
||||||
// was found.
|
// was found.
|
||||||
func (c *Core) unmount(ctx context.Context, path string) error {
|
func (c *Core) unmount(ctx context.Context, path string) error {
|
||||||
|
|
|
@ -2290,11 +2290,20 @@ func (m *mockBuiltinRegistry) Keys(pluginType consts.PluginType) []string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *mockBuiltinRegistry) Contains(name string, pluginType consts.PluginType) bool {
|
func (m *mockBuiltinRegistry) Contains(name string, pluginType consts.PluginType) bool {
|
||||||
|
for _, key := range m.Keys(pluginType) {
|
||||||
|
if key == name {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *mockBuiltinRegistry) DeprecationStatus(name string, pluginType consts.PluginType) (consts.DeprecationStatus, bool) {
|
func (m *mockBuiltinRegistry) DeprecationStatus(name string, pluginType consts.PluginType) (consts.DeprecationStatus, bool) {
|
||||||
return consts.Supported, true
|
if m.Contains(name, pluginType) {
|
||||||
|
return consts.Supported, true
|
||||||
|
}
|
||||||
|
|
||||||
|
return consts.Unknown, false
|
||||||
}
|
}
|
||||||
|
|
||||||
type NoopAudit struct {
|
type NoopAudit struct {
|
||||||
|
|
|
@ -11,6 +11,13 @@ description: |-
|
||||||
The `auth list` command lists the auth methods enabled. The output lists the
|
The `auth list` command lists the auth methods enabled. The output lists the
|
||||||
enabled auth methods and options for those methods.
|
enabled auth methods and options for those methods.
|
||||||
|
|
||||||
|
## Deprecation Status Column
|
||||||
|
|
||||||
|
As of 1.12, all builtin auth engines will have an associated Deprecation
|
||||||
|
Status. This status will be reflected in the `Deprecation Status` column, seen
|
||||||
|
below. All auth engines which are not provided by builtin plugins will show a
|
||||||
|
`Deprecation Status` of "n/a".
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
List all auth methods:
|
List all auth methods:
|
||||||
|
@ -27,10 +34,11 @@ List detailed auth method information:
|
||||||
|
|
||||||
```shell-session
|
```shell-session
|
||||||
$ vault auth list -detailed
|
$ vault auth list -detailed
|
||||||
Path Type Accessor Plugin Default TTL Max TTL Replication Description
|
Path Plugin Accessor Default TTL Max TTL Token Type Replication Seal Wrap External Entropy Access Options Description UUID Deprecation Status
|
||||||
---- ---- -------- ------ ----------- ------- ----------- -----------
|
---- ------ -------- ----------- ------- ---------- ----------- --------- ----------------------- ------- ----------- ---- ------------------
|
||||||
token/ token auth_token_b2166f9e n/a system system replicated token based credentials
|
app-id/ app-id auth_app-id_c88ad56f system system default-service replicated false false map[] n/a a7c702b4-0dba-02b6-483c-2fd6be33240a pending removal
|
||||||
userpass/ userpass auth_userpass_eea6507e n/a system system replicated n/a
|
approle/ approle auth_approle_95df932e system system default-service replicated false false map[] n/a 931df9d1-8737-b7dc-4ca2-3e0e892fce92 supported
|
||||||
|
token/ token auth_token_aafab997 system system default-service replicated false false map[] token based credentials 6eb5db7b-ac7f-4304-1f52-9b802c6f06c1 n/a
|
||||||
```
|
```
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
|
@ -15,6 +15,13 @@ This command also outputs information about the enabled path including
|
||||||
configured TTLs and human-friendly descriptions. A TTL of "system" indicates
|
configured TTLs and human-friendly descriptions. A TTL of "system" indicates
|
||||||
that the system default is in use.
|
that the system default is in use.
|
||||||
|
|
||||||
|
## Deprecation Status Column
|
||||||
|
|
||||||
|
As of 1.12, all builtin secrets engines will have an associated Deprecation
|
||||||
|
Status. This status will be reflected in the `Deprecation Status` column, seen
|
||||||
|
below. All secrets engines which are not provided by builtin plugins will show a
|
||||||
|
`Deprecation Status` of "n/a".
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
List all enabled secrets engines:
|
List all enabled secrets engines:
|
||||||
|
@ -32,11 +39,12 @@ List all enabled secrets engines with detailed output:
|
||||||
|
|
||||||
```shell-session
|
```shell-session
|
||||||
$ vault secrets list -detailed
|
$ vault secrets list -detailed
|
||||||
Path Type Accessor Plugin Default TTL Max TTL Force No Cache Replication Description
|
Path Plugin Accessor Default TTL Max TTL Force No Cache Replication Seal Wrap External Entropy Access Options Description UUID Deprecation Status
|
||||||
---- ---- -------- ------ ----------- ------- -------------- ----------- -----------
|
---- ------ -------- ----------- ------- -------------- ----------- --------- ----------------------- ------- ----------- ---- ------------------
|
||||||
cubbyhole/ cubbyhole cubbyhole_10fbb584 n/a n/a n/a false local per-token private secret storage
|
cubbyhole/ cubbyhole cubbyhole_b16d1bc0 n/a n/a false local false false map[] per-token private secret storage 8c64d56b-9d46-d667-1155-a8c1a83a5d01 n/a
|
||||||
secret/ kv kv_167ce199 n/a system system false replicated key/value secret storage
|
identity/ identity identity_3d67c936 system system false replicated false false map[] identity store 5aa1e59c-33b5-9dec-05d6-c80c9a800557 n/a
|
||||||
sys/ system system_a9fd745d n/a n/a n/a false replicated system endpoints used for control, policy and debugging
|
postgresql/ postgresql postgresql_f0a54308 system system false replicated false false map[] n/a 8cdc1d2d-0713-eaa6-17e3-49790a60650b deprecated
|
||||||
|
sys/ system system_c86bd362 n/a n/a false replicated true false map[] system endpoints used for control, policy and debugging e3193999-0875-d38d-3458-21d9f2762c80 n/a
|
||||||
```
|
```
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
Loading…
Reference in New Issue