test/plugin: refactor compilePlugin for reuse (#18952)

* test/plugin: refactor compilePlugin for reuse

- move compilePlugin to helper package
- make NewTestCluster use compilePlugin

* do not overwrite plugin directory in CoreConfig if set

* fix getting plugin directory path for go build
This commit is contained in:
John-Michael Faircloth 2023-02-03 16:27:11 -06:00 committed by GitHub
parent 660979d58b
commit 14e4d67026
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 230 additions and 161 deletions

View File

@ -0,0 +1,139 @@
// Package pluginhelpers contains testhelpers that don't depend on package
// vault, and thus can be used within vault (as well as elsewhere.)
package pluginhelpers
import (
"crypto/sha256"
"fmt"
"os"
"os/exec"
"path"
"path/filepath"
"sync"
"github.com/hashicorp/vault/sdk/helper/consts"
"github.com/mitchellh/go-testing-interface"
)
var (
testPluginCacheLock sync.Mutex
testPluginCache = map[string][]byte{}
)
type TestPlugin struct {
Name string
Typ consts.PluginType
Version string
FileName string
Sha256 string
}
func GetPlugin(t testing.T, typ consts.PluginType) (string, string, string, string) {
t.Helper()
var pluginName string
var pluginType string
var pluginMain string
var pluginVersionLocation string
switch typ {
case consts.PluginTypeCredential:
pluginType = "approle"
pluginName = "vault-plugin-auth-" + pluginType
pluginMain = filepath.Join("builtin", "credential", pluginType, "cmd", pluginType, "main.go")
pluginVersionLocation = fmt.Sprintf("github.com/hashicorp/vault/builtin/credential/%s.ReportedVersion", pluginType)
case consts.PluginTypeSecrets:
pluginType = "consul"
pluginName = "vault-plugin-secrets-" + pluginType
pluginMain = filepath.Join("builtin", "logical", pluginType, "cmd", pluginType, "main.go")
pluginVersionLocation = fmt.Sprintf("github.com/hashicorp/vault/builtin/logical/%s.ReportedVersion", pluginType)
case consts.PluginTypeDatabase:
pluginType = "postgresql"
pluginName = "vault-plugin-database-" + pluginType
pluginMain = filepath.Join("plugins", "database", pluginType, fmt.Sprintf("%s-database-plugin", pluginType), "main.go")
pluginVersionLocation = fmt.Sprintf("github.com/hashicorp/vault/plugins/database/%s.ReportedVersion", pluginType)
default:
t.Fatal(typ.String())
}
return pluginName, pluginType, pluginMain, pluginVersionLocation
}
// to mount a plugin, we need a working binary plugin, so we compile one here.
// pluginVersion is used to override the plugin's self-reported version
func CompilePlugin(t testing.T, typ consts.PluginType, pluginVersion string, pluginDir string) TestPlugin {
t.Helper()
pluginName, pluginType, pluginMain, pluginVersionLocation := GetPlugin(t, typ)
testPluginCacheLock.Lock()
defer testPluginCacheLock.Unlock()
var pluginBytes []byte
dir := ""
var err error
for {
dir, err = os.Getwd()
if err != nil {
t.Fatal(err)
}
// detect if we are in a subdirectory or the root directory and compensate
if _, err := os.Stat("builtin"); os.IsNotExist(err) {
err := os.Chdir("..")
if err != nil {
t.Fatal(err)
}
} else {
break
}
}
pluginPath := path.Join(pluginDir, pluginName)
if pluginVersion != "" {
pluginPath += "-" + pluginVersion
}
key := fmt.Sprintf("%s %s %s", pluginName, pluginType, pluginVersion)
// cache the compilation to only run once
var ok bool
pluginBytes, ok = testPluginCache[key]
if !ok {
// we need to compile
line := []string{"build"}
if pluginVersion != "" {
line = append(line, "-ldflags", fmt.Sprintf("-X %s=%s", pluginVersionLocation, pluginVersion))
}
line = append(line, "-o", pluginPath, pluginMain)
cmd := exec.Command("go", line...)
cmd.Dir = dir
output, err := cmd.CombinedOutput()
if err != nil {
t.Fatal(fmt.Errorf("error running go build %v output: %s", err, output))
}
testPluginCache[key], err = os.ReadFile(pluginPath)
if err != nil {
t.Fatal(err)
}
pluginBytes = testPluginCache[key]
}
// write the cached plugin if necessary
if _, err := os.Stat(pluginPath); os.IsNotExist(err) {
err = os.WriteFile(pluginPath, pluginBytes, 0o755)
}
if err != nil {
t.Fatal(err)
}
sha := sha256.New()
_, err = sha.Write(pluginBytes)
if err != nil {
t.Fatal(err)
}
return TestPlugin{
Name: pluginName,
Typ: typ,
Version: pluginVersion,
FileName: path.Base(pluginPath),
Sha256: fmt.Sprintf("%x", sha.Sum(nil)),
}
}

View File

@ -2,20 +2,19 @@ package vault
import (
"context"
"crypto/sha256"
"encoding/hex"
"errors"
"fmt"
"os"
"os/exec"
"path"
"path/filepath"
"strings"
"sync"
"testing"
log "github.com/hashicorp/go-hclog"
"github.com/hashicorp/vault/helper/namespace"
"github.com/hashicorp/vault/helper/testhelpers/corehelpers"
"github.com/hashicorp/vault/helper/testhelpers/pluginhelpers"
"github.com/hashicorp/vault/sdk/framework"
"github.com/hashicorp/vault/sdk/helper/consts"
"github.com/hashicorp/vault/sdk/helper/pluginutil"
@ -27,28 +26,15 @@ import (
const vaultTestingMockPluginEnv = "VAULT_TESTING_MOCK_PLUGIN"
var (
pluginCacheLock sync.Mutex
pluginCache = map[string][]byte{}
)
type testPlugin struct {
name string
typ consts.PluginType
version string
fileName string
sha256 string
}
// version is used to override the plugin's self-reported version
func testCoreWithPlugins(t *testing.T, typ consts.PluginType, versions ...string) (*Core, []testPlugin) {
func testCoreWithPlugins(t *testing.T, typ consts.PluginType, versions ...string) (*Core, []pluginhelpers.TestPlugin) {
t.Helper()
pluginDir, cleanup := corehelpers.MakeTestPluginDir(t)
t.Cleanup(func() { cleanup(t) })
var plugins []testPlugin
var plugins []pluginhelpers.TestPlugin
for _, version := range versions {
plugins = append(plugins, compilePlugin(t, typ, version, pluginDir))
plugins = append(plugins, pluginhelpers.CompilePlugin(t, typ, version, pluginDir))
}
conf := &CoreConfig{
BuiltinRegistry: corehelpers.NewMockBuiltinRegistry(),
@ -59,109 +45,6 @@ func testCoreWithPlugins(t *testing.T, typ consts.PluginType, versions ...string
return core, plugins
}
func getPlugin(t *testing.T, typ consts.PluginType) (string, string, string, string) {
t.Helper()
var pluginName string
var pluginType string
var pluginMain string
var pluginVersionLocation string
switch typ {
case consts.PluginTypeCredential:
pluginType = "approle"
pluginName = "vault-plugin-auth-" + pluginType
pluginMain = filepath.Join("builtin", "credential", pluginType, "cmd", pluginType, "main.go")
pluginVersionLocation = fmt.Sprintf("github.com/hashicorp/vault/builtin/credential/%s.ReportedVersion", pluginType)
case consts.PluginTypeSecrets:
pluginType = "consul"
pluginName = "vault-plugin-secrets-" + pluginType
pluginMain = filepath.Join("builtin", "logical", pluginType, "cmd", pluginType, "main.go")
pluginVersionLocation = fmt.Sprintf("github.com/hashicorp/vault/builtin/logical/%s.ReportedVersion", pluginType)
case consts.PluginTypeDatabase:
pluginType = "postgresql"
pluginName = "vault-plugin-database-" + pluginType
pluginMain = filepath.Join("plugins", "database", pluginType, fmt.Sprintf("%s-database-plugin", pluginType), "main.go")
pluginVersionLocation = fmt.Sprintf("github.com/hashicorp/vault/plugins/database/%s.ReportedVersion", pluginType)
default:
t.Fatal(typ.String())
}
return pluginName, pluginType, pluginMain, pluginVersionLocation
}
// to mount a plugin, we need a working binary plugin, so we compile one here.
// pluginVersion is used to override the plugin's self-reported version
func compilePlugin(t *testing.T, typ consts.PluginType, pluginVersion string, pluginDir string) testPlugin {
t.Helper()
pluginName, pluginType, pluginMain, pluginVersionLocation := getPlugin(t, typ)
pluginCacheLock.Lock()
defer pluginCacheLock.Unlock()
var pluginBytes []byte
dir := ""
// detect if we are in the "vault/" or the root directory and compensate
if _, err := os.Stat("builtin"); os.IsNotExist(err) {
wd, err := os.Getwd()
if err != nil {
t.Fatal(err)
}
dir = filepath.Dir(wd)
}
pluginPath := path.Join(pluginDir, pluginName)
if pluginVersion != "" {
pluginPath += "-" + pluginVersion
}
key := fmt.Sprintf("%s %s %s", pluginName, pluginType, pluginVersion)
// cache the compilation to only run once
var ok bool
pluginBytes, ok = pluginCache[key]
if !ok {
// we need to compile
line := []string{"build"}
if pluginVersion != "" {
line = append(line, "-ldflags", fmt.Sprintf("-X %s=%s", pluginVersionLocation, pluginVersion))
}
line = append(line, "-o", pluginPath, pluginMain)
cmd := exec.Command("go", line...)
cmd.Dir = dir
output, err := cmd.CombinedOutput()
if err != nil {
t.Fatal(fmt.Errorf("error running go build %v output: %s", err, output))
}
pluginCache[key], err = os.ReadFile(pluginPath)
if err != nil {
t.Fatal(err)
}
pluginBytes = pluginCache[key]
}
// write the cached plugin if necessary
var err error
if _, err := os.Stat(pluginPath); os.IsNotExist(err) {
err = os.WriteFile(pluginPath, pluginBytes, 0o755)
}
if err != nil {
t.Fatal(err)
}
sha := sha256.New()
_, err = sha.Write(pluginBytes)
if err != nil {
t.Fatal(err)
}
return testPlugin{
name: pluginName,
typ: typ,
version: pluginVersion,
fileName: path.Base(pluginPath),
sha256: fmt.Sprintf("%x", sha.Sum(nil)),
}
}
func TestCore_EnableExternalPlugin(t *testing.T) {
for name, tc := range map[string]struct {
pluginType consts.PluginType
@ -180,10 +63,31 @@ func TestCore_EnableExternalPlugin(t *testing.T) {
},
} {
t.Run(name, func(t *testing.T) {
c, plugins := testCoreWithPlugins(t, tc.pluginType, "")
registerPlugin(t, c.systemBackend, plugins[0].name, tc.pluginType.String(), "1.0.0", plugins[0].sha256, plugins[0].fileName)
coreConfig := &CoreConfig{
DisableMlock: true,
DisableCache: true,
Logger: log.NewNullLogger(),
CredentialBackends: map[string]logical.Factory{},
}
mountPlugin(t, c.systemBackend, plugins[0].name, tc.pluginType, "v1.0.0", "")
cluster := NewTestCluster(t, coreConfig, &TestClusterOptions{
Plugins: &TestPluginConfig{
Typ: tc.pluginType,
Versions: []string{""},
},
})
cluster.Start()
defer cluster.Cleanup()
c := cluster.Cores[0].Core
TestWaitActive(t, c)
plugins := cluster.Plugins
registerPlugin(t, c.systemBackend, plugins[0].Name, tc.pluginType.String(), "1.0.0", plugins[0].Sha256, plugins[0].FileName)
mountPlugin(t, c.systemBackend, plugins[0].Name, tc.pluginType, "v1.0.0", "")
match := c.router.MatchingMount(namespace.RootContext(nil), tc.routerPath)
if match != tc.expectedMatch {
@ -254,10 +158,10 @@ func TestCore_EnableExternalPlugin_MultipleVersions(t *testing.T) {
t.Run(name, func(t *testing.T) {
c, plugins := testCoreWithPlugins(t, tc.pluginType, "")
for _, version := range tc.registerVersions {
registerPlugin(t, c.systemBackend, plugins[0].name, tc.pluginType.String(), version, plugins[0].sha256, plugins[0].fileName)
registerPlugin(t, c.systemBackend, plugins[0].Name, tc.pluginType.String(), version, plugins[0].Sha256, plugins[0].FileName)
}
mountPlugin(t, c.systemBackend, plugins[0].name, tc.pluginType, tc.mountVersion, "")
mountPlugin(t, c.systemBackend, plugins[0].Name, tc.pluginType, tc.mountVersion, "")
match := c.router.MatchingMount(namespace.RootContext(nil), tc.routerPath)
if match != tc.expectedMatch {
@ -286,8 +190,8 @@ func TestCore_EnableExternalPlugin_Deregister_SealUnseal(t *testing.T) {
// create an external plugin to shadow the builtin "pending-removal-test-plugin"
pluginName := "therug"
plugin := compilePlugin(t, consts.PluginTypeCredential, "", pluginDir)
err := os.Link(path.Join(pluginDir, plugin.fileName), path.Join(pluginDir, pluginName))
plugin := pluginhelpers.CompilePlugin(t, consts.PluginTypeCredential, "", pluginDir)
err := os.Link(path.Join(pluginDir, plugin.FileName), path.Join(pluginDir, pluginName))
if err != nil {
t.Fatal(err)
}
@ -300,7 +204,7 @@ func TestCore_EnableExternalPlugin_Deregister_SealUnseal(t *testing.T) {
c, keys, root := testCoreUnsealed(t, c)
// Register a plugin
registerPlugin(t, c.systemBackend, pluginName, consts.PluginTypeCredential.String(), "", plugin.sha256, plugin.fileName)
registerPlugin(t, c.systemBackend, pluginName, consts.PluginTypeCredential.String(), "", plugin.Sha256, plugin.FileName)
mountPlugin(t, c.systemBackend, pluginName, consts.PluginTypeCredential, "", "")
plugct := len(c.pluginCatalog.externalPlugins)
if plugct != 1 {
@ -358,8 +262,8 @@ func TestCore_Unseal_isMajorVersionFirstMount_PendingRemoval_Plugin(t *testing.T
// create an external plugin to shadow the builtin "pending-removal-test-plugin"
pluginName := "pending-removal-test-plugin"
plugin := compilePlugin(t, consts.PluginTypeCredential, "", pluginDir)
err := os.Link(path.Join(pluginDir, plugin.fileName), path.Join(pluginDir, pluginName))
plugin := pluginhelpers.CompilePlugin(t, consts.PluginTypeCredential, "", pluginDir)
err := os.Link(path.Join(pluginDir, plugin.FileName), path.Join(pluginDir, pluginName))
if err != nil {
t.Fatal(err)
}
@ -371,11 +275,11 @@ func TestCore_Unseal_isMajorVersionFirstMount_PendingRemoval_Plugin(t *testing.T
c, keys, root := testCoreUnsealed(t, c)
// Register a shadow plugin
registerPlugin(t, c.systemBackend, pluginName, consts.PluginTypeCredential.String(), "", plugin.sha256, plugin.fileName)
registerPlugin(t, c.systemBackend, pluginName, consts.PluginTypeCredential.String(), "", plugin.Sha256, plugin.FileName)
mountPlugin(t, c.systemBackend, pluginName, consts.PluginTypeCredential, "", "")
// Deregister shadow plugin
deregisterPlugin(t, c.systemBackend, pluginName, consts.PluginTypeCredential.String(), "", plugin.sha256, plugin.fileName)
deregisterPlugin(t, c.systemBackend, pluginName, consts.PluginTypeCredential.String(), "", plugin.Sha256, plugin.FileName)
// Make sure this isn't the first mount for the current major version.
if c.isMajorVersionFirstMount(context.Background()) {
@ -437,8 +341,8 @@ func TestCore_EnableExternalPlugin_PendingRemoval(t *testing.T) {
// create an external plugin to shadow the builtin "pending-removal-test-plugin"
pluginName := "pending-removal-test-plugin"
plugin := compilePlugin(t, consts.PluginTypeCredential, "v1.2.3", pluginDir)
err := os.Link(path.Join(pluginDir, plugin.fileName), path.Join(pluginDir, pluginName))
plugin := pluginhelpers.CompilePlugin(t, consts.PluginTypeCredential, "v1.2.3", pluginDir)
err := os.Link(path.Join(pluginDir, plugin.FileName), path.Join(pluginDir, pluginName))
if err != nil {
t.Fatal(err)
}
@ -462,7 +366,7 @@ func TestCore_EnableExternalPlugin_PendingRemoval(t *testing.T) {
}
// Register a shadow plugin
registerPlugin(t, c.systemBackend, pluginName, consts.PluginTypeCredential.String(), "v1.2.3", plugin.sha256, plugin.fileName)
registerPlugin(t, c.systemBackend, pluginName, consts.PluginTypeCredential.String(), "v1.2.3", plugin.Sha256, plugin.FileName)
mountPlugin(t, c.systemBackend, pluginName, consts.PluginTypeCredential, "", "")
}
@ -471,8 +375,8 @@ func TestCore_EnableExternalPlugin_ShadowBuiltin(t *testing.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"))
plugin := pluginhelpers.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)
}
@ -511,7 +415,7 @@ func TestCore_EnableExternalPlugin_ShadowBuiltin(t *testing.T) {
}
// Register a shadow plugin
registerPlugin(t, c.systemBackend, pluginName, consts.PluginTypeCredential.String(), "v1.2.3", plugin.sha256, plugin.fileName)
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 {
@ -528,7 +432,7 @@ func TestCore_EnableExternalPlugin_ShadowBuiltin(t *testing.T) {
}
// Deregister shadow plugin
deregisterPlugin(t, c.systemBackend, pluginName, consts.PluginTypeSecrets.String(), "v1.2.3", plugin.sha256, plugin.fileName)
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 {
@ -550,8 +454,8 @@ func TestCore_EnableExternalKv_MultipleVersions(t *testing.T) {
t.Cleanup(func() { cleanup(t) })
// new kv plugin can be registered but not mounted
plugin := compilePlugin(t, consts.PluginTypeSecrets, "v1.2.3", pluginDir)
err := os.Link(path.Join(pluginDir, plugin.fileName), path.Join(pluginDir, "kv"))
plugin := pluginhelpers.CompilePlugin(t, consts.PluginTypeSecrets, "v1.2.3", pluginDir)
err := os.Link(path.Join(pluginDir, plugin.FileName), path.Join(pluginDir, "kv"))
if err != nil {
t.Fatal(err)
}
@ -563,7 +467,7 @@ func TestCore_EnableExternalKv_MultipleVersions(t *testing.T) {
c := TestCoreWithSealAndUI(t, conf)
c, _, _ = testCoreUnsealed(t, c)
registerPlugin(t, c.systemBackend, pluginName, consts.PluginTypeSecrets.String(), "v1.2.3", plugin.sha256, plugin.fileName)
registerPlugin(t, c.systemBackend, pluginName, consts.PluginTypeSecrets.String(), "v1.2.3", plugin.Sha256, plugin.FileName)
req := logical.TestRequest(t, logical.ReadOperation, "plugins/catalog")
resp, err := c.systemBackend.HandleRequest(namespace.RootContext(nil), req)
if err != nil {
@ -603,8 +507,8 @@ func TestCore_EnableExternalNoop_MultipleVersions(t *testing.T) {
t.Cleanup(func() { cleanup(t) })
// new noop plugin can be registered but not mounted
plugin := compilePlugin(t, consts.PluginTypeCredential, "v1.2.3", pluginDir)
err := os.Link(path.Join(pluginDir, plugin.fileName), path.Join(pluginDir, "noop"))
plugin := pluginhelpers.CompilePlugin(t, consts.PluginTypeCredential, "v1.2.3", pluginDir)
err := os.Link(path.Join(pluginDir, plugin.FileName), path.Join(pluginDir, "noop"))
if err != nil {
t.Fatal(err)
}
@ -616,7 +520,7 @@ func TestCore_EnableExternalNoop_MultipleVersions(t *testing.T) {
c := TestCoreWithSealAndUI(t, conf)
c, _, _ = testCoreUnsealed(t, c)
registerPlugin(t, c.systemBackend, pluginName, consts.PluginTypeCredential.String(), "v1.2.3", plugin.sha256, plugin.fileName)
registerPlugin(t, c.systemBackend, pluginName, consts.PluginTypeCredential.String(), "v1.2.3", plugin.Sha256, plugin.FileName)
req := logical.TestRequest(t, logical.ReadOperation, "plugins/catalog")
resp, err := c.systemBackend.HandleRequest(namespace.RootContext(nil), req)
if err != nil {
@ -674,10 +578,10 @@ func TestCore_EnableExternalPlugin_NoVersionsOkay(t *testing.T) {
// version specified should mount the unversioned plugin even if there
// are versioned plugins available.
for _, version := range []string{"", "v1.0.0"} {
registerPlugin(t, c.systemBackend, plugins[0].name, tc.pluginType.String(), version, plugins[0].sha256, plugins[0].fileName)
registerPlugin(t, c.systemBackend, plugins[0].Name, tc.pluginType.String(), version, plugins[0].Sha256, plugins[0].FileName)
}
mountPlugin(t, c.systemBackend, plugins[0].name, tc.pluginType, "", "")
mountPlugin(t, c.systemBackend, plugins[0].Name, tc.pluginType, "", "")
match := c.router.MatchingMount(namespace.RootContext(nil), tc.routerPath)
if match != tc.expectedMatch {
@ -711,11 +615,11 @@ func TestCore_EnableExternalCredentialPlugin_NoVersionOnRegister(t *testing.T) {
} {
t.Run(name, func(t *testing.T) {
c, plugins := testCoreWithPlugins(t, tc.pluginType, "")
registerPlugin(t, c.systemBackend, plugins[0].name, tc.pluginType.String(), "", plugins[0].sha256, plugins[0].fileName)
registerPlugin(t, c.systemBackend, plugins[0].Name, tc.pluginType.String(), "", plugins[0].Sha256, plugins[0].FileName)
req := logical.TestRequest(t, logical.UpdateOperation, mountTable(tc.pluginType))
req.Data = map[string]interface{}{
"type": plugins[0].name,
"type": plugins[0].Name,
"config": map[string]interface{}{
"plugin_version": "v1.0.0",
},
@ -743,10 +647,10 @@ func TestCore_EnableExternalCredentialPlugin_InvalidName(t *testing.T) {
c, plugins := testCoreWithPlugins(t, tc.pluginType, "")
d := &framework.FieldData{
Raw: map[string]interface{}{
"name": plugins[0].name,
"sha256": plugins[0].sha256,
"name": plugins[0].Name,
"sha256": plugins[0].Sha256,
"version": "v1.0.0",
"command": plugins[0].name + "xyz",
"command": plugins[0].Name + "xyz",
},
Schema: c.systemBackend.pluginsCatalogCRUDPath().Fields,
}
@ -778,12 +682,12 @@ func TestExternalPlugin_getBackendTypeVersion(t *testing.T) {
} {
t.Run(name, func(t *testing.T) {
c, plugins := testCoreWithPlugins(t, tc.pluginType, tc.setRunningVersion)
registerPlugin(t, c.systemBackend, plugins[0].name, tc.pluginType.String(), tc.setRunningVersion, plugins[0].sha256, plugins[0].fileName)
registerPlugin(t, c.systemBackend, plugins[0].Name, tc.pluginType.String(), tc.setRunningVersion, plugins[0].Sha256, plugins[0].FileName)
shaBytes, _ := hex.DecodeString(plugins[0].sha256)
commandFull := filepath.Join(c.pluginCatalog.directory, plugins[0].fileName)
shaBytes, _ := hex.DecodeString(plugins[0].Sha256)
commandFull := filepath.Join(c.pluginCatalog.directory, plugins[0].FileName)
entry := &pluginutil.PluginRunner{
Name: plugins[0].name,
Name: plugins[0].Name,
Command: commandFull,
Args: nil,
Sha256: shaBytes,
@ -843,13 +747,13 @@ func TestExternalPlugin_CheckFilePermissions(t *testing.T) {
} {
t.Run(name, func(t *testing.T) {
c, plugins := testCoreWithPlugins(t, tc.pluginType, tc.pluginVersion)
registeredPluginName := fmt.Sprintf(tc.pluginNameFmt, plugins[0].name)
registeredPluginName := fmt.Sprintf(tc.pluginNameFmt, plugins[0].Name)
// Permissions will be checked once during registration.
req := logical.TestRequest(t, logical.UpdateOperation, fmt.Sprintf("plugins/catalog/%s/%s", tc.pluginType.String(), registeredPluginName))
req.Data = map[string]interface{}{
"command": plugins[0].fileName,
"sha256": plugins[0].sha256,
"command": plugins[0].FileName,
"sha256": plugins[0].Sha256,
"version": tc.pluginVersion,
}
resp, err := c.systemBackend.HandleRequest(namespace.RootContext(nil), req)

View File

@ -41,6 +41,7 @@ import (
"github.com/hashicorp/vault/helper/metricsutil"
"github.com/hashicorp/vault/helper/namespace"
"github.com/hashicorp/vault/helper/testhelpers/corehelpers"
"github.com/hashicorp/vault/helper/testhelpers/pluginhelpers"
"github.com/hashicorp/vault/internalshared/configutil"
v5 "github.com/hashicorp/vault/sdk/database/dbplugin/v5"
"github.com/hashicorp/vault/sdk/framework"
@ -772,6 +773,7 @@ type TestCluster struct {
CAKeyPEM []byte
Cores []*TestClusterCore
ID string
Plugins []pluginhelpers.TestPlugin
RootToken string
RootCAs *x509.CertPool
TempDir string
@ -1182,6 +1184,13 @@ type TestClusterOptions struct {
EffectiveSDKVersionMap map[int]string
NoDefaultQuotas bool
Plugins *TestPluginConfig
}
type TestPluginConfig struct {
Typ consts.PluginType
Versions []string
}
var DefaultNumCores = 3
@ -1615,6 +1624,23 @@ func NewTestCluster(t testing.T, base *CoreConfig, opts *TestClusterOptions) *Te
opts.ClusterLayers = inmemCluster
}
if opts != nil && opts.Plugins != nil {
var pluginDir string
var cleanup func(t testing.T)
if coreConfig.PluginDirectory == "" {
pluginDir, cleanup = corehelpers.MakeTestPluginDir(t)
coreConfig.PluginDirectory = pluginDir
t.Cleanup(func() { cleanup(t) })
}
var plugins []pluginhelpers.TestPlugin
for _, version := range opts.Plugins.Versions {
plugins = append(plugins, pluginhelpers.CompilePlugin(t, opts.Plugins.Typ, version, coreConfig.PluginDirectory))
}
testCluster.Plugins = plugins
}
// Create cores
testCluster.cleanupFuncs = []func(){}
cores := []*Core{}