Handle deprecated builtins (#17005)

* core: Handle deprecated mounts on enable and unseal
* changelog: Deprecation Status handling
* core: Add Pending Removal override var
* core: Add some documentation for Pending Removal override
This commit is contained in:
Mike Palmiotto 2022-09-06 15:49:35 -04:00 committed by GitHub
parent 5db952eada
commit bf744e3bde
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 117 additions and 4 deletions

13
changelog/17005.txt Normal file
View File

@ -0,0 +1,13 @@
```release-note:change
auth: `auth enable` returns an error and `POST /sys/auth/:type` endpoint
reports an error for `Pending Removal` auth methods.
```
```release-note:change
secrets: `secrets enable` returns an error and `POST /sys/mount/:type` endpoint
reports an error for `Pending Removal` secrets engines.
```
```release-note:improvement
core: Handle and log deprecated builtin mounts. Introduces
`VAULT_ALLOW_PENDING_REMOVAL_MOUNTS` to override shutdown and error when
attempting to mount `Pending Removal` builtin plugins.
```

View File

@ -2,6 +2,7 @@ package command
import (
"io/ioutil"
"os"
"strings"
"testing"
@ -49,6 +50,18 @@ func TestAuthEnableCommand_Run(t *testing.T) {
"",
2,
},
{
"deprecated builtin with standard mount",
[]string{"app-id"},
"",
2,
},
{
"deprecated builtin with different mount",
[]string{"-path=/tmp", "app-id"},
"",
2,
},
}
for _, tc := range cases {
@ -211,6 +224,16 @@ func TestAuthEnableCommand_Run(t *testing.T) {
}
for _, b := range backends {
var expectedResult int = 0
status, _ := builtinplugins.Registry.DeprecationStatus(b, consts.PluginTypeCredential)
allowDeprecated := os.Getenv(consts.VaultAllowPendingRemovalMountsEnv)
// Need to handle deprecated builtins specially
if (status == consts.PendingRemoval && allowDeprecated == "") || status == consts.Removed {
expectedResult = 2
}
// Not a builtin
if b == "token" {
continue
}
@ -218,11 +241,11 @@ func TestAuthEnableCommand_Run(t *testing.T) {
ui, cmd := testAuthEnableCommand(t)
cmd.client = client
code := cmd.Run([]string{
actualResult := cmd.Run([]string{
b,
})
if exp := 0; code != exp {
t.Errorf("type %s, expected %d to be %d - %s", b, code, exp, ui.OutputWriter.String()+ui.ErrorWriter.String())
if actualResult != expectedResult {
t.Errorf("type: %s - got: %d, expected: %d - %s", b, actualResult, expectedResult, ui.OutputWriter.String()+ui.ErrorWriter.String())
}
}
})

View File

@ -1,5 +1,7 @@
package consts
const VaultAllowPendingRemovalMountsEnv = "VAULT_ALLOW_PENDING_REMOVAL_MOUNTS"
// DeprecationStatus represents the current deprecation state for builtins
type DeprecationStatus uint32

View File

@ -2385,6 +2385,11 @@ func (b *SystemBackend) handleEnableAuth(ctx context.Context, req *logical.Reque
Version: version,
}
err = b.Core.handleDeprecatedMountEntry(ctx, me, consts.PluginTypeCredential)
if err != nil {
return handleError(err)
}
// Attempt enabling
if err := b.Core.enableCredential(ctx, me); err != nil {
b.Backend.Logger().Error("error occurred during enable credential", "path", me.Path, "error", err)

View File

@ -463,6 +463,12 @@ func (c *Core) decodeMountTable(ctx context.Context, raw []byte) (*MountTable, e
continue
}
// Immediately shutdown the core if deprecated mounts are detected and VAULT_ALLOW_PENDING_REMOVAL_MOUNTS is unset
if err := c.handleDeprecatedMountEntry(ctx, entry, consts.PluginTypeUnknown); err != nil {
c.logger.Error("shutting down core", "error", err)
c.Shutdown()
}
entry.namespace = ns
mountEntries = append(mountEntries, entry)
}
@ -585,6 +591,11 @@ func (c *Core) mountInternal(ctx context.Context, entry *MountEntry, updateStora
addFilterablePath(c, viewPath)
}
// Detect and handle deprecated secrets engines
if err := c.handleDeprecatedMountEntry(ctx, entry, consts.PluginTypeSecrets); err != nil {
return err
}
nilMount, err := preprocessMount(c, entry, view)
if err != nil {
return err
@ -904,6 +915,54 @@ func (c *Core) taintMountEntry(ctx context.Context, nsID, mountPath string, upda
return nil
}
// handleDeprecatedMountEntry handles the Deprecation Status of the specified
// mount entry's builtin engine as follows:
//
// * Supported - do nothing
// * Deprecated - log a warning about builtin deprecation
// * PendingRemoval - log an error about builtin deprecation and return an error
// if VAULT_ALLOW_PENDING_REMOVAL_MOUNTS is unset
// * Removed - log an error about builtin deprecation and return an error
func (c *Core) handleDeprecatedMountEntry(ctx context.Context, entry *MountEntry, pluginType consts.PluginType) error {
if c.builtinRegistry == nil || entry == nil {
return nil
}
// Allow type to be determined from mount entry when not otherwise specified
if pluginType == consts.PluginTypeUnknown {
pluginType = c.builtinTypeFromMountEntry(ctx, entry)
}
// Handle aliases
t := entry.Type
if alias, ok := mountAliases[t]; ok {
t = alias
}
status, ok := c.builtinRegistry.DeprecationStatus(t, pluginType)
if ok {
// Deprecation sublogger with some identifying information
dl := c.logger.With("name", t, "type", pluginType, "status", status, "path", entry.Path)
errDeprecatedMount := fmt.Errorf("mount entry associated with %s builtin", status)
switch status {
case consts.Deprecated:
dl.Warn(errDeprecatedMount.Error())
case consts.PendingRemoval:
dl.Error(errDeprecatedMount.Error())
if allow := os.Getenv(consts.VaultAllowPendingRemovalMountsEnv); allow == "" {
return fmt.Errorf("could not mount %q: %w", t, errDeprecatedMount)
}
c.Logger().Info("mount allowed by environment variable", "env", consts.VaultAllowPendingRemovalMountsEnv)
case consts.Removed:
return fmt.Errorf("could not mount %s: %w", t, errDeprecatedMount)
}
}
return nil
}
// remountForceInternal takes a copy of the mount entry for the path and fully unmounts
// and remounts the backend to pick up any changes, such as filtered paths.
// Should be only used for internal usage.

View File

@ -60,6 +60,14 @@ flags](/docs/commands) included on all commands.
are "standard" and "json". This can also be specified via the
VAULT_LOG_FORMAT environment variable.
- `VAULT_ALLOW_PENDING_REMOVAL_MOUNTS` `(string: "")` - (environment variable)
Allow Vault to be started with builtin engines which have the `Pending Removal`
deprecation state. This is a temporary stopgap in place in order to perform an
upgrade and disable these engines. Once these engines are marked `Removed` (in
the next major release of Vault), the environment variable will no longer work
and a downgrade must be performed in order to remove the offending engines. For
more information, see the [deprecation faq](/docs/deprecation/faq).
### Dev Options
- `-dev` `(bool: false)` - Enable development mode. In this mode, Vault runs

View File

@ -29,7 +29,7 @@ If you are an Enterprise user, we recommend that you consider migrating to Hashi
### Q: What should I do if I use Mount Filters, AppID, or any of the standalone DB engines?
These features were deprecated in prior releases of Vault. We are targeting the removal of these features from the product in the Vault 1.11 release. Please plan to upgrade to these features before the release of Vault 1.11. Refer to the table below for a list of alternative features.
These features were deprecated in prior releases of Vault. We are targeting the removal of these features from the product in the Vault 1.12 release. Please plan to upgrade to these features before the release of Vault 1.12. Refer to the table below for a list of alternative features.
| Deprecated Feature | Alternative Feature |
| --------------------- | ------------------------------------------------------------------------------------------------------------------- |
@ -37,6 +37,8 @@ These features were deprecated in prior releases of Vault. We are targeting the
| AppID | [AppRole auth method](/docs/auth/approle) |
| Standalone DB engines | [Combined DB engines](/docs/secrets/databases) |
**Note:** After upgrading to 1.12, any attempt to unseal a core with one of the following features enabled will result in a core shutdown. This may temporarily be overridden using the `VAULT_ALLOW_PENDING_REMOVAL_MOUNTS` environment variable when launching the Vault server. These features will be officially removed from Vault in version 1.13 and this environment variable will not work. In order to upgrade to 1.13, you will have to completely disable all removed features.
### Q: What is the impact of removing support for X.509 certificates with signatures that use SHA-1?
Starting with Vault 1.12.0, Vault will be built with Go 1.18.

View File

@ -33,4 +33,5 @@ This announcement page is maintained and updated periodically to communicate imp
*If you use **Standalone DB Engines** or **AppID (OSS)**, you should actively plan to migrate away from their usage. If you use these features and upgrade to Release 1.12, Vault will log error messages and shut down, and any attempts to add new mounts will result in an error.
This behavior may temporarily be overridden when starting the Vault server by using the `VAULT_ALLOW_PENDING_REMOVAL_MOUNTS` environment variable until they are officially removed in Vault version 1.13.
If you are still using these deprecated features and attempt to upgrade to 1.13 (the target feature removal timeframe), you will not be able to start up Vault without downgrading and migrating away from these features.