Skip to content

Commit

Permalink
plugins: Filter builtins by RunningVersion (#17816)
Browse files Browse the repository at this point in the history
This commit adds some logic to handle the case where a mount entry has a
non-builtin RunningVersion. This ensures that we only report deprecation
status for builtins.
  • Loading branch information
mpalmi committed Nov 11, 2022
1 parent 5e2e5f0 commit 1ea6865
Show file tree
Hide file tree
Showing 3 changed files with 125 additions and 1 deletion.
3 changes: 3 additions & 0 deletions changelog/17816.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:bug
plugins: Only report deprecation status for builtin plugins.
```
116 changes: 116 additions & 0 deletions vault/external_plugin_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,85 @@ func TestCore_EnableExternalPlugin_MultipleVersions(t *testing.T) {
}
}

func TestCore_EnableExternalPlugin_ShadowBuiltin(t *testing.T) {
pluginDir, cleanup := MakeTestPluginDir(t)
t.Cleanup(func() { cleanup(t) })

// create an external plugin to shadow the builtin "approle"
plugin := compilePlugin(t, consts.PluginTypeCredential, "v1.2.3", pluginDir)
err := os.Link(path.Join(pluginDir, plugin.fileName), path.Join(pluginDir, "approle"))
if err != nil {
t.Fatal(err)
}
pluginName := "approle"
conf := &CoreConfig{
BuiltinRegistry: NewMockBuiltinRegistry(),
PluginDirectory: pluginDir,
}
c := TestCoreWithSealAndUI(t, conf)
c, _, _ = testCoreUnsealed(t, c)

verifyAuthListDeprecationStatus := func(authName string, checkExists bool) error {
req := logical.TestRequest(t, logical.ReadOperation, mountTable(consts.PluginTypeCredential))
req.Data = map[string]interface{}{
"type": authName,
}
resp, err := c.systemBackend.HandleRequest(namespace.RootContext(nil), req)
if err != nil {
return err
}
status := resp.Data["deprecation_status"]
if checkExists && status == nil {
return fmt.Errorf("expected deprecation status but found none")
} else if !checkExists && status != nil {
return fmt.Errorf("expected nil deprecation status but found %q", status)
}
return nil
}

// Create a new auth method with builtin approle
mountPlugin(t, c.systemBackend, pluginName, consts.PluginTypeCredential, "", "")

// Read the auth table to verify deprecation status
if err := verifyAuthListDeprecationStatus(pluginName, true); err != nil {
t.Fatal(err)
}

// Register a shadow plugin
registerPlugin(t, c.systemBackend, pluginName, consts.PluginTypeCredential.String(), "v1.2.3", plugin.sha256, plugin.fileName)

// Verify auth table hasn't changed
if err := verifyAuthListDeprecationStatus(pluginName, true); err != nil {
t.Fatal(err)
}

// Remount auth method using registered shadow plugin
unmountPlugin(t, c.systemBackend, pluginName, consts.PluginTypeCredential, "", "")
mountPlugin(t, c.systemBackend, pluginName, consts.PluginTypeCredential, "", "")

// Verify auth table has changed
if err := verifyAuthListDeprecationStatus(pluginName, false); err != nil {
t.Fatal(err)
}

// Deregister shadow plugin
deregisterPlugin(t, c.systemBackend, pluginName, consts.PluginTypeSecrets.String(), "v1.2.3", plugin.sha256, plugin.fileName)

// Verify auth table hasn't changed
if err := verifyAuthListDeprecationStatus(pluginName, false); err != nil {
t.Fatal(err)
}

// Remount auth method
unmountPlugin(t, c.systemBackend, pluginName, consts.PluginTypeCredential, "", "")
mountPlugin(t, c.systemBackend, pluginName, consts.PluginTypeCredential, "", "")

// Verify auth table has changed
if err := verifyAuthListDeprecationStatus(pluginName, false); err != nil {
t.Fatal(err)
}
}

func TestCore_EnableExternalKv_MultipleVersions(t *testing.T) {
pluginDir, cleanup := MakeTestPluginDir(t)
t.Cleanup(func() { cleanup(t) })
Expand Down Expand Up @@ -759,6 +838,43 @@ func mountPlugin(t *testing.T, sys *SystemBackend, pluginName string, pluginType
}
}

func unmountPlugin(t *testing.T, sys *SystemBackend, pluginName string, pluginType consts.PluginType, version, path string) {
t.Helper()
var mountPath string
if path == "" {
mountPath = mountTable(pluginType)
} else {
mountPath = mountTableWithPath(consts.PluginTypeSecrets, path)
}
req := logical.TestRequest(t, logical.DeleteOperation, mountPath)
req.Data = map[string]interface{}{
"type": pluginName,
}
if version != "" {
req.Data["config"] = map[string]interface{}{
"plugin_version": version,
}
}
resp, err := sys.HandleRequest(namespace.RootContext(nil), req)
if err != nil || (resp != nil && resp.IsError()) {
t.Fatalf("err:%v resp:%#v", err, resp)
}
}

func deregisterPlugin(t *testing.T, sys *SystemBackend, pluginName, pluginType, version, sha, command string) {
t.Helper()
req := logical.TestRequest(t, logical.DeleteOperation, fmt.Sprintf("plugins/catalog/%s/%s", pluginType, pluginName))
req.Data = map[string]interface{}{
"command": command,
"sha256": sha,
"version": version,
}
resp, err := sys.HandleRequest(namespace.RootContext(nil), req)
if err != nil || (resp != nil && resp.IsError()) {
t.Fatalf("err:%v resp:%#v", err, resp)
}
}

func mountTable(pluginType consts.PluginType) string {
return mountTableWithPath(pluginType, "foo")
}
Expand Down
7 changes: 6 additions & 1 deletion vault/mount.go
Original file line number Diff line number Diff line change
Expand Up @@ -717,8 +717,13 @@ func (c *Core) builtinTypeFromMountEntry(ctx context.Context, entry *MountEntry)
return consts.PluginTypeUnknown
}

// Builtin plugins should contain the "builtin" string in their RunningVersion
if !strings.Contains(entry.RunningVersion, "builtin") {
return consts.PluginTypeUnknown
}

builtinPluginType := func(name string, pluginType consts.PluginType) (consts.PluginType, bool) {
plugin, err := c.pluginCatalog.Get(ctx, name, pluginType, "")
plugin, err := c.pluginCatalog.Get(ctx, name, pluginType, entry.RunningVersion)
if err == nil && plugin != nil && plugin.Builtin {
return plugin.Type, true
}
Expand Down

0 comments on commit 1ea6865

Please sign in to comment.