diff --git a/CHANGELOG.md b/CHANGELOG.md index b4181635f0..92fe466dba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,11 @@ Canonical reference for changes, improvements, and bugfixes for Boundary. See Deprecations/Changes for some additional details. [PR](https://github.com/hashicorp/boundary/pull/2160). +### Bug Fixes + +* The plugin execution_dir configuration parameter is now respected. + [PR](https://github.com/hashicorp/boundary/pull/2183). + ### Deprecations/Changes * Credential Libraries: The `user_password` credential type has been renamed to diff --git a/internal/cmd/base/servers.go b/internal/cmd/base/servers.go index 92a314ba6b..eebce3f25c 100644 --- a/internal/cmd/base/servers.go +++ b/internal/cmd/base/servers.go @@ -555,6 +555,7 @@ func (b *Server) SetupKMSes(ctx context.Context, ui cli.Ui, config *config.Confi configutil.WithPluginOptions( pluginutil.WithPluginsMap(kms_plugin_assets.BuiltinKmsPlugins()), pluginutil.WithPluginsFilesystem(kms_plugin_assets.KmsPluginPrefix, kms_plugin_assets.FileSystem()), + pluginutil.WithPluginExecutionDirectory(config.Plugins.ExecutionDir), ), configutil.WithLogger(pluginLogger.Named(kms.Type).With("purpose", purpose)), ) diff --git a/internal/daemon/controller/controller_test.go b/internal/daemon/controller/controller_test.go index 1608865957..6ec8d61389 100644 --- a/internal/daemon/controller/controller_test.go +++ b/internal/daemon/controller/controller_test.go @@ -2,12 +2,17 @@ package controller import ( "context" + "os" + "path/filepath" "testing" + "github.com/google/go-cmp/cmp" "github.com/hashicorp/boundary/internal/cmd/base" + "github.com/hashicorp/boundary/internal/cmd/config" "github.com/hashicorp/boundary/internal/iam" "github.com/hashicorp/boundary/internal/kms" "github.com/hashicorp/boundary/internal/types/scope" + host_plugin_assets "github.com/hashicorp/boundary/plugins/host" "github.com/hashicorp/go-secure-stdlib/listenerutil" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -223,3 +228,39 @@ func TestControllerNewListenerConfig(t *testing.T) { }) } } + +func TestController_NewPluginsConfig(t *testing.T) { + require := require.New(t) + testCtx := context.Background() + ctx, cancel := context.WithCancel(context.Background()) + tc := &TestController{ + t: t, + ctx: ctx, + cancel: cancel, + opts: nil, + } + + initialConfig, err := config.DevController() + require.NoError(err) + tmpDir := t.TempDir() + initialConfig.Plugins.ExecutionDir = tmpDir + conf := TestControllerConfig(t, ctx, tc, &TestControllerOpts{Config: initialConfig}) + conf.EnabledPlugins = []base.EnabledPlugin{ + base.EnabledPluginHostAws, + base.EnabledPluginHostAzure, + } + + _, err = New(testCtx, conf) + require.NoError(err) + + // Check that both plugins were written to the temp dir + files, err := os.ReadDir(tmpDir) + require.NoError(err) + require.Len(files, 2) + var pluginNames []string + for _, file := range files { + pluginNames = append(pluginNames, filepath.Base(file.Name())) + } + expectedPluginNames := []string{host_plugin_assets.HostPluginPrefix + "aws.gz", host_plugin_assets.HostPluginPrefix + "azure.gz"} + require.Empty(cmp.Diff(expectedPluginNames, pluginNames)) +} diff --git a/sdk/plugins/host/load.go b/sdk/plugins/host/load.go index d9d23c5593..ac74473ef5 100644 --- a/sdk/plugins/host/load.go +++ b/sdk/plugins/host/load.go @@ -60,7 +60,7 @@ func CreateHostPlugin( } // Create the plugin and cleanup func - plugClient, cleanup, err := pluginutil.CreatePlugin(pluginMap[pluginType]) + plugClient, cleanup, err := pluginutil.CreatePlugin(pluginMap[pluginType], opts.withPluginOptions...) if err != nil { return nil, cleanup, err } diff --git a/sdk/wrapper/wrapper.go b/sdk/wrapper/wrapper.go index 5945868c6f..fbd13fc32c 100644 --- a/sdk/wrapper/wrapper.go +++ b/sdk/wrapper/wrapper.go @@ -3,17 +3,43 @@ package wrapper import ( "context" "fmt" + "os" wrapping "github.com/hashicorp/go-kms-wrapping/v2" configutil "github.com/hashicorp/go-secure-stdlib/configutil/v2" + "github.com/hashicorp/go-secure-stdlib/pluginutil/v2" "github.com/hashicorp/go-secure-stdlib/strutil" + "github.com/hashicorp/hcl" ) +// pluginsConfig is used to pre-parse any plugins stanza +// in the configuration file, so that we can use the correct +// configuration when creating the KMS plugin for reading the +// rest of the config. +type pluginsConfig struct { + Plugins struct { + ExecutionDir string `hcl:"execution_dir"` + } `hcl:"plugins"` +} + func GetWrapperFromPath(ctx context.Context, path, purpose string, opt ...configutil.Option) (wrapping.Wrapper, func() error, error) { kmses, err := configutil.LoadConfigKMSes(path) if err != nil { return nil, nil, fmt.Errorf("Error parsing config file: %w", err) } + hclBytes, err := os.ReadFile(path) + if err != nil { + return nil, nil, fmt.Errorf("Error reading config file: %w", err) + } + pluginsConfig, err := parsePluginsConfig(string(hclBytes)) + if err != nil { + return nil, nil, fmt.Errorf("Error parsing plugins stanza in config file: %w", err) + } + if pluginsConfig.Plugins.ExecutionDir != "" { + // Note, this is safe to use because configutil.WithPluginOptions invocations + // are additive with each other. + opt = append(opt, configutil.WithPluginOptions(pluginutil.WithPluginExecutionDirectory(pluginsConfig.Plugins.ExecutionDir))) + } return getWrapper(ctx, kmses, purpose, opt...) } @@ -23,6 +49,15 @@ func GetWrapperFromHcl(ctx context.Context, inHcl, purpose string, opt ...config if err != nil { return nil, nil, fmt.Errorf("Error parsing KMS HCL: %w", err) } + pluginsConfig, err := parsePluginsConfig(inHcl) + if err != nil { + return nil, nil, fmt.Errorf("Error parsing plugins stanza in config file: %w", err) + } + if pluginsConfig.Plugins.ExecutionDir != "" { + // Note, this is safe to use because configutil.WithPluginOptions invocations + // are additive with each other. + opt = append(opt, configutil.WithPluginOptions(pluginutil.WithPluginExecutionDirectory(pluginsConfig.Plugins.ExecutionDir))) + } return getWrapper(ctx, kmses, purpose, opt...) } @@ -54,3 +89,11 @@ func getWrapper(ctx context.Context, kmses []*configutil.KMS, purpose string, op return wrapper, cleanup, nil } + +func parsePluginsConfig(inHcl string) (*pluginsConfig, error) { + var conf pluginsConfig + if err := hcl.Decode(&conf, inHcl); err != nil { + return nil, err + } + return &conf, nil +}