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:
Mike Palmiotto 2022-08-31 16:11:14 -04:00 committed by GitHub
parent ae8622ba7d
commit 2c16be25e3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 114 additions and 26 deletions

View File

@ -286,6 +286,7 @@ type MountOutput struct {
RunningVersion string `json:"running_version"`
Sha string `json:"sha"`
RunningSha string `json:"running_sha"`
DeprecationStatus string `json:"deprecation_status" mapstructure:"deprecation_status"`
}
type MountConfigOutput struct {

15
changelog/16849.txt Normal file
View File

@ -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.
```

View File

@ -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 {
mount := auths[path]
@ -162,7 +162,7 @@ func (c *AuthListCommand) detailedMounts(auths map[string]*api.AuthMount) []stri
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,
pluginName,
mount.Accessor,
@ -176,6 +176,7 @@ func (c *AuthListCommand) detailedMounts(auths map[string]*api.AuthMount) []stri
mount.Description,
mount.UUID,
mount.Version,
mount.DeprecationStatus,
))
}

View File

@ -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 {
mount := mounts[path]
@ -162,7 +162,7 @@ func (c *SecretsListCommand) detailedMounts(mounts map[string]*api.MountOutput)
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,
pluginName,
mount.Accessor,
@ -175,6 +175,7 @@ func (c *SecretsListCommand) detailedMounts(mounts map[string]*api.MountOutput)
mount.Options,
mount.Description,
mount.UUID,
mount.DeprecationStatus,
))
}

View File

@ -42,7 +42,7 @@ func TestSecretsListCommand_Run(t *testing.T) {
{
"detailed",
[]string{"-detailed"},
"Default TTL",
"Deprecation Status",
0,
},
}

View File

@ -96,7 +96,7 @@ func TestSysEnableAuth(t *testing.T) {
TestServerAuth(t, addr, token)
resp := testHttpPost(t, token, addr+"/v1/sys/auth/foo", map[string]interface{}{
"type": "noop",
"type": "approle",
"description": "foo",
})
testResponseStatus(t, resp, 204)
@ -114,8 +114,9 @@ func TestSysEnableAuth(t *testing.T) {
"data": map[string]interface{}{
"foo/": map[string]interface{}{
"description": "foo",
"type": "noop",
"type": "approle",
"external_entropy_access": false,
"deprecation_status": "supported",
"config": map[string]interface{}{
"default_lease_ttl": json.Number("0"),
"max_lease_ttl": json.Number("0"),
@ -151,8 +152,9 @@ func TestSysEnableAuth(t *testing.T) {
},
"foo/": map[string]interface{}{
"description": "foo",
"type": "noop",
"type": "approle",
"external_entropy_access": false,
"deprecation_status": "supported",
"config": map[string]interface{}{
"default_lease_ttl": json.Number("0"),
"max_lease_ttl": json.Number("0"),

View File

@ -879,7 +879,7 @@ func (b *SystemBackend) handleRekeyDeleteRecovery(ctx context.Context, req *logi
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{}{
"type": entry.Type,
"description": entry.Description,
@ -923,6 +923,11 @@ func mountInfo(entry *MountEntry) map[string]interface{} {
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
return info
@ -957,7 +962,8 @@ func (b *SystemBackend) handleMountTable(ctx context.Context, req *logical.Reque
}
// Populate mount info
info := mountInfo(entry)
info := b.mountInfo(ctx, entry)
resp.Data[entry.Path] = info
}
@ -1159,7 +1165,7 @@ func (b *SystemBackend) handleReadMount(ctx context.Context, req *logical.Reques
}
return &logical.Response{
Data: mountInfo(entry),
Data: b.mountInfo(ctx, entry),
}, nil
}
@ -2149,7 +2155,7 @@ func (b *SystemBackend) handleAuthTable(ctx context.Context, req *logical.Reques
continue
}
info := mountInfo(entry)
info := b.mountInfo(ctx, entry)
resp.Data[entry.Path] = info
}
@ -2183,7 +2189,7 @@ func (b *SystemBackend) handleReadAuth(ctx context.Context, req *logical.Request
}
return &logical.Response{
Data: mountInfo(entry),
Data: b.mountInfo(ctx, entry),
}, nil
}
@ -3849,7 +3855,7 @@ func (b *SystemBackend) pathInternalUIMountsRead(ctx context.Context, req *logic
if ns.ID == entry.NamespaceID && hasAccess(ctx, entry) {
if isAuthed {
// If this is an authed request return all the mount info
secretMounts[entry.Path] = mountInfo(entry)
secretMounts[entry.Path] = b.mountInfo(ctx, entry)
} else {
secretMounts[entry.Path] = map[string]interface{}{
"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 isAuthed {
// If this is an authed request return all the mount info
authMounts[entry.Path] = mountInfo(entry)
authMounts[entry.Path] = b.mountInfo(ctx, entry)
} else {
authMounts[entry.Path] = map[string]interface{}{
"type": entry.Type,
@ -3934,7 +3940,7 @@ func (b *SystemBackend) pathInternalUIMountRead(ctx context.Context, req *logica
return errResp, logical.ErrPermissionDenied
}
resp := &logical.Response{
Data: mountInfo(me),
Data: b.mountInfo(ctx, me),
}
resp.Data["path"] = me.Path

View File

@ -665,6 +665,43 @@ func (c *Core) mountInternal(ctx context.Context, entry *MountEntry, updateStora
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
// was found.
func (c *Core) unmount(ctx context.Context, path string) error {

View File

@ -2290,11 +2290,20 @@ func (m *mockBuiltinRegistry) Keys(pluginType consts.PluginType) []string {
}
func (m *mockBuiltinRegistry) Contains(name string, pluginType consts.PluginType) bool {
for _, key := range m.Keys(pluginType) {
if key == name {
return true
}
}
return false
}
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 {

View File

@ -11,6 +11,13 @@ description: |-
The `auth list` command lists the auth methods enabled. The output lists the
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
List all auth methods:
@ -27,10 +34,11 @@ List detailed auth method information:
```shell-session
$ vault auth list -detailed
Path Type Accessor Plugin Default TTL Max TTL Replication Description
---- ---- -------- ------ ----------- ------- ----------- -----------
token/ token auth_token_b2166f9e n/a system system replicated token based credentials
userpass/ userpass auth_userpass_eea6507e n/a system system replicated n/a
Path Plugin Accessor Default TTL Max TTL Token Type Replication Seal Wrap External Entropy Access Options Description UUID Deprecation Status
---- ------ -------- ----------- ------- ---------- ----------- --------- ----------------------- ------- ----------- ---- ------------------
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
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

View File

@ -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
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
List all enabled secrets engines:
@ -32,11 +39,12 @@ List all enabled secrets engines with detailed output:
```shell-session
$ vault secrets list -detailed
Path Type Accessor Plugin Default TTL Max TTL Force No Cache Replication Description
---- ---- -------- ------ ----------- ------- -------------- ----------- -----------
cubbyhole/ cubbyhole cubbyhole_10fbb584 n/a n/a n/a false local per-token private secret storage
secret/ kv kv_167ce199 n/a system system false replicated key/value secret storage
sys/ system system_a9fd745d n/a n/a n/a false replicated system endpoints used for control, policy and debugging
Path Plugin Accessor Default TTL Max TTL Force No Cache Replication Seal Wrap External Entropy Access Options Description UUID Deprecation Status
---- ------ -------- ----------- ------- -------------- ----------- --------- ----------------------- ------- ----------- ---- ------------------
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
identity/ identity identity_3d67c936 system system false replicated false false map[] identity store 5aa1e59c-33b5-9dec-05d6-c80c9a800557 n/a
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