You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
boundary/sdk/wrapper/wrapper.go

100 lines
3.0 KiB

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...)
}
func GetWrapperFromHcl(ctx context.Context, inHcl, purpose string, opt ...configutil.Option) (wrapping.Wrapper, func() error, error) {
kmses, err := configutil.ParseKMSes(inHcl)
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...)
}
func getWrapper(ctx context.Context, kmses []*configutil.KMS, purpose string, opt ...configutil.Option) (wrapping.Wrapper, func() error, error) {
var kms *configutil.KMS
for _, v := range kmses {
if strutil.StrListContains(v.Purpose, purpose) {
if kms != nil {
return nil, nil, fmt.Errorf("Only one %q block marked for %q purpose is allowed", "kms", purpose)
}
kms = v
}
}
if kms == nil {
return nil, nil, nil
}
wrapper, cleanup, err := configutil.ConfigureWrapper(
ctx,
kms,
nil,
nil,
opt...,
)
if err != nil {
return nil, nil, fmt.Errorf("Error configuring kms: %w", err)
}
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
}