Update config encrypt/decrypt CLI command (#309)

This updates the command to our emergent standards. It also enables
using a separate config file for a config kms, which allows non-string
values to be encrypted.

This allowed some nice cleanup as well.
This commit is contained in:
Jeff Mitchell authored and GitHub committed 2020-08-27 16:38:44 -04:00
1 parent 274afa6b02
commit 28df6eb7b0
18 files changed
+307 -197

No files matched your search

+1 -1
View File
@@ -122,6 +122,6 @@ internal/ui/assets.go
update-ui-assets*
# Test config file
test.hcl
test*.hcl
# vim: set filetype=conf :
+5 -6
View File
@@ -18,6 +18,7 @@ import (
"github.com/hashicorp/boundary/api"
"github.com/hashicorp/boundary/api/authtokens"
"github.com/hashicorp/boundary/internal/wrapper"
"github.com/hashicorp/boundary/recovery"
"github.com/mitchellh/cli"
"github.com/pkg/errors"
@@ -183,10 +184,13 @@ func (c *Command) Client(opt ...Option) (*api.Client, error) {
tokenName := "default"
switch {
case c.FlagRecoveryConfig != "":
wrapper, err := recovery.GetWrapper(c.Context, c.FlagRecoveryConfig)
wrapper, err := wrapper.GetWrapper(c.FlagRecoveryConfig, "recovery")
if err != nil {
return nil, err
}
if wrapper == nil {
return nil, errors.New(`No "kms" block with purpose "recovery" found`)
}
if err := wrapper.Init(c.Context); err != nil {
return nil, fmt.Errorf("Error initializing kms: %w", err)
}
@@ -284,11 +288,6 @@ func (c *Command) FlagSet(bit FlagSetBit) *FlagSets {
c.flagsOnce.Do(func() {
set := NewFlagSets(c.UI)
// These flag sets will apply to all leaf subcommands.
// TODO: Optional, but FlagSetHTTP can be safely removed from the individual
// Flags() subcommands.
bit = bit | FlagSetHTTP
if bit&FlagSetHTTP != 0 {
f := set.NewFlagSet("Connection Options")
+7 -1
View File
@@ -213,7 +213,13 @@ func (b *Server) PrintInfo(ui cli.Ui, mode string) {
}
// Server configuration output
padding := 36
padding := 0
for _, k := range b.InfoKeys {
currPadding := padding - len(k)
if currPadding < 2 {
padding = len(k) + 2
}
}
sort.Strings(b.InfoKeys)
ui.Output(fmt.Sprintf("==> Boundary %s configuration:\n", mode))
for _, k := range b.InfoKeys {
+2 -1
View File
@@ -144,12 +144,13 @@ func initCommands(ui, serverCmdUi cli.Ui, runOpts *RunOptions) {
"config encrypt": func() (cli.Command, error) {
return &config.EncryptDecryptCommand{
Command: base.NewCommand(ui),
Encrypt: true,
Func: "encrypt",
}, nil
},
"config decrypt": func() (cli.Command, error) {
return &config.EncryptDecryptCommand{
Command: base.NewCommand(ui),
Func: "decrypt",
}, nil
},
+15 -19
View File
@@ -1,8 +1,6 @@
package config
import (
"strings"
"github.com/hashicorp/boundary/internal/cmd/base"
"github.com/mitchellh/cli"
)
@@ -18,23 +16,21 @@ func (c *Command) Synopsis() string {
}
func (c *Command) Help() string {
helpText := `
Usage: boundary config <subcommand> [options] [args]
This command groups subcommands for operators interacting with Boundary's
config files. Here are a few examples of config commands:
Encrypt sensitive values in a config file:
$ boundary config encrypt config.hcl
Decrypt sensitive values in a config file:
$ boundary config decrypt config.hcl
Please see the individual subcommand help for detailed usage information.`
return strings.TrimSpace(helpText)
return base.WrapForHelpText([]string{
"Usage: boundary config <subcommand> [options] [args]",
"",
" This command groups subcommands for operators interacting with Boundary's config files. Here are a few examples of config commands:",
"",
" Encrypt sensitive values in a config file:",
"",
" $ boundary config encrypt config.hcl",
"",
" Decrypt sensitive values in a config file:",
"",
" $ boundary config decrypt config.hcl",
"",
" Please see the individual subcommand help for detailed usage information.",
})
}
func (c *Command) Run(args []string) int {
+93 -71
View File
@@ -3,12 +3,13 @@ package config
import (
"fmt"
"io/ioutil"
"net/textproto"
"os"
"strings"
"github.com/hashicorp/boundary/internal/cmd/base"
"github.com/hashicorp/boundary/internal/wrapper"
"github.com/hashicorp/shared-secure-libs/configutil"
"github.com/hashicorp/vault/sdk/helper/strutil"
"github.com/mitchellh/cli"
"github.com/posener/complete"
)
@@ -18,49 +19,82 @@ var _ cli.CommandAutocomplete = (*EncryptDecryptCommand)(nil)
type EncryptDecryptCommand struct {
*base.Command
Encrypt bool
Func string
flagConfig string
flagConfigKms string
flagOverwrite bool
flagStrip bool
}
func (c *EncryptDecryptCommand) Synopsis() string {
dir := "Decrypts"
if c.Encrypt {
dir = "Encrypts"
}
return fmt.Sprintf("%s sensitive values in Vault's configuration file", dir)
return fmt.Sprintf("%s sensitive values in Boundary's configuration file", textproto.CanonicalMIMEHeaderKey(c.Func))
}
func (c *EncryptDecryptCommand) Help() string {
subCmd := "Decrypt"
if c.Encrypt {
subCmd = "Encrypt"
}
helpText := `
Usage: boundary config %s [options] [args]
%s sensitive values in a Boundary's configuration file. These values must be marked
with {{%s()}} as appropriate. This can only be used with string parameters, and
the markers must be inside the quote marks delimiting the string; as an example:
foo = "{{encrypt(bar)}}"
By default this will print the new configuration out. To overwrite into the same
file use the -overwrite flag.
$ boundary config %s -overwrite config.hcl
`
helpText = fmt.Sprintf(helpText, strings.ToLower(subCmd), subCmd, strings.ToLower(subCmd), strings.ToLower(subCmd))
var args []string
args = append(args,
"Usage: boundary config {{func}} [options] [args]",
"",
" {{upperfunc}} sensitive values in a Boundary's configuration file. These values must be marked with {{{{func}}()}} as appropriate. Example:",
"",
` foo = "{{encrypt(bar)}}"`,
"",
" By default this will print out the new configuration. To overwrite into the same file use the -overwrite flag.",
"",
" $ boundary config {{func}} -overwrite config.hcl",
"",
` In order for this command to perform its task, a "kms" block must be defined within a configuration file. Example:`,
"",
` kms "aead" {`,
` purpose = "config"`,
` aead_type = "aes-gcm"`,
` key = "7xtkEoS5EXPbgynwd+dDLHopaCqK8cq0Rpep4eooaTs="`,
` }`,
"",
` The "kms" block can be defined in the configuration file or via the -config flag. If defined in the configuration file, only string parameters are supported, and the markers must be inside the quote marks delimiting the string. Additionally, if the block is defined inline, do NOT use an an "aead" block with the key defined in the configuration file as it provides no protection.`,
"",
"",
)
return strings.TrimSpace(helpText)
for i, line := range args {
args[i] =
strings.Replace(
strings.Replace(
line, "{{func}}", c.Func, -1,
),
"{{upperfunc}}", textproto.CanonicalMIMEHeaderKey(c.Func), -1,
)
}
return base.WrapForHelpText(args) + c.Flags().Help()
}
func (c *EncryptDecryptCommand) Flags() *base.FlagSets {
set := c.FlagSet(0)
set := c.FlagSet(base.FlagSetNone)
f := set.NewFlagSet("Command Options")
f.StringVar(&base.StringVar{
Name: "config-kms",
Target: &c.flagConfigKms,
Completion: complete.PredictOr(
complete.PredictFiles("*.hcl"),
complete.PredictFiles("*.json"),
),
Usage: `If specified, the given file will be parsed for a "kms" block with purpose "config" and will use it to perform the command. If not set, the command will expect a block inline with the configuration file, and will only be able to support quoted string parameters.`,
})
f.StringVar(&base.StringVar{
Name: "config",
Target: &c.flagConfig,
Completion: complete.PredictOr(
complete.PredictFiles("*.hcl"),
complete.PredictFiles("*.json"),
),
Usage: `The configuration file upon which to perform encryption or decryption`,
})
f.BoolVar(&base.BoolVar{
Name: "overwrite",
Target: &c.flagOverwrite,
@@ -85,54 +119,51 @@ func (c *EncryptDecryptCommand) AutocompleteFlags() complete.Flags {
}
func (c *EncryptDecryptCommand) Run(args []string) (ret int) {
op := "decrypt"
if c.Encrypt {
op = "encrypt"
}
f := c.Flags()
if err := f.Parse(args); err != nil {
c.UI.Error(err.Error())
return 1
}
path := ""
args = f.Args()
switch len(args) {
case 1:
path = strings.TrimSpace(args[0])
switch c.flagConfig {
case "":
c.UI.Error(`Missing required parameter -config`)
return 1
default:
c.UI.Error(fmt.Sprintf("Incorrect arguments (expected 1, got %d)", len(args)))
return 1
c.flagConfig = strings.TrimSpace(c.flagConfig)
}
if path == "" {
c.UI.Error("A configuration file must be specified")
return 1
kmsDefFile := c.flagConfig
switch c.flagConfigKms {
case "":
default:
kmsDefFile = strings.TrimSpace(c.flagConfigKms)
}
kmses, err := configutil.LoadConfigKMSes(path)
wrapper, err := wrapper.GetWrapper(kmsDefFile, "config")
if err != nil {
c.UI.Error(fmt.Errorf("Error loading configuration from %s: %w", path, err).Error())
c.UI.Error(err.Error())
return 1
}
if wrapper == nil {
c.UI.Error(`No wrapper with "config" purpose found"`)
return 1
}
var kms *configutil.KMS
for _, v := range kmses {
if strutil.StrListContains(v.Purpose, "config") {
if kms != nil {
c.UI.Error("Only one kms block marked for \"config\" purpose is allowed")
return 1
}
kms = v
if err := wrapper.Init(c.Context); err != nil {
c.UI.Error(fmt.Errorf("Error initializing KMS: %w", err).Error())
return 1
}
defer func() {
if err := wrapper.Finalize(c.Context); err != nil {
c.UI.Warn(fmt.Errorf("Error encountered when finalizing KMS: %w", err).Error())
}
}
if kms == nil {
c.UI.Error("No kms block with \"config\" purpose defined in the configuration file")
return 1
}
}()
d, err := ioutil.ReadFile(path)
d, err := ioutil.ReadFile(c.flagConfig)
if err != nil {
c.UI.Error(fmt.Errorf("Error reading config file: %w", err).Error())
return 1
@@ -140,18 +171,9 @@ func (c *EncryptDecryptCommand) Run(args []string) (ret int) {
raw := string(d)
wrapper, err := configutil.ConfigureWrapper(kms, nil, nil, nil)
raw, err = configutil.EncryptDecrypt(raw, c.Func == "decrypt", c.flagStrip, wrapper)
if err != nil {
c.UI.Error(fmt.Errorf("Error creating kms: %w", err).Error())
return 1
}
wrapper.Init(c.Context)
defer wrapper.Finalize(c.Context)
raw, err = configutil.EncryptDecrypt(raw, !c.Encrypt, c.flagStrip, wrapper)
if err != nil {
c.UI.Error(fmt.Errorf("Error %sing via kms: %w", op, err).Error())
c.UI.Error(fmt.Errorf("Error %sing via kms: %w", c.Func, err).Error())
return 1
}
@@ -160,7 +182,7 @@ func (c *EncryptDecryptCommand) Run(args []string) (ret int) {
return 0
}
file, err := os.Create(path)
file, err := os.Create(c.flagConfig)
if err != nil {
c.UI.Error(fmt.Errorf("Error opening file for writing: %w", err).Error())
return 1
@@ -182,5 +204,5 @@ func (c *EncryptDecryptCommand) Run(args []string) (ret int) {
c.UI.Error(fmt.Sprintf("Wrong number of bytes written to file, expected %d, wrote %d", len(raw), n))
}
return 0
return
}
@@ -15,31 +15,52 @@ import (
)
const (
configEncryptPath = "./fixtures/configEncrypt.hcl"
configDecryptPath = "./fixtures/configDecrypt.hcl"
configEncryptPath = "./fixtures/config_encrypt.hcl"
configDecryptPath = "./fixtures/config_decrypt.hcl"
configKmsPath = "./fixtures/config_kms.hcl"
configExtEncryptPath = "./fixtures/config_ext_encrypt.hcl"
configExtEncryptStrippedPath = "./fixtures/config_ext_encrypt_stripped.hcl"
configExtDecryptPath = "./fixtures/config_ext_decrypt.hcl"
)
func TestEncryptDecrypt(t *testing.T) {
cases := []struct {
encrypt bool
config string
exp string
f string
config string
configKms string
exp string
strip bool
}{
{
encrypt: true,
config: configEncryptPath,
exp: "",
f: "encrypt",
config: configEncryptPath,
},
{
encrypt: false,
config: configDecryptPath,
exp: configEncryptPath,
f: "decrypt",
config: configDecryptPath,
exp: configEncryptPath,
},
{
f: "encrypt-ext",
config: configExtEncryptPath,
configKms: configKmsPath,
},
{
f: "decrypt-ext",
config: configExtDecryptPath,
configKms: configKmsPath,
exp: configExtEncryptPath,
},
{
f: "decrypt-ext-strip",
config: configExtDecryptPath,
configKms: configKmsPath,
exp: configExtEncryptStrippedPath,
},
}
for _, c := range cases {
t.Run(fmt.Sprintf("Test encrypt %v", c.encrypt), func(t *testing.T) {
t.Run(fmt.Sprintf("Test encrypt %v", c.f), func(t *testing.T) {
var b bytes.Buffer
@@ -51,9 +72,17 @@ func TestEncryptDecrypt(t *testing.T) {
cmd := &EncryptDecryptCommand{
Command: base.NewCommand(ui),
Encrypt: c.encrypt}
Func: c.f,
}
if err := cmd.Run([]string{c.config}); err != 0 {
args := []string{"-config", c.config}
if c.configKms != "" {
args = append(args, "-config-kms", c.configKms)
}
if c.strip {
args = append(args, "-strip")
}
if err := cmd.Run(args); err != 0 {
assert.Equal(t, err, 0)
}
@@ -64,7 +93,7 @@ func TestEncryptDecrypt(t *testing.T) {
// If it's encrypting, then we can assume that it did the right thing since
// there are many tests on the underlying codebase for that. If it's not
// encrypting, compare it to the cleartext to verify because we can.
if !c.encrypt {
if c.f == "decrypt" {
expected, err := ioutil.ReadFile(c.exp)
assert.NoError(t, err)
@@ -0,0 +1,7 @@
int_val = {{decrypt(Ch7a69AX8R5w_cCZJUqLTQkWesuSHMrHxrRMMZnq53QqAA)}}
bool_val = {{decrypt(CiDURLrWUXLhEfkOemqqiQlcD_gsGsIx-kxVTIlVncN6-yoA)}}
kms "aead" {
purpose = "root"
aead_type = "aes-gcm"
key ="{{decrypt(CkiRTINwX19TnC3AB-zx5E133TXI9KzBWb8TxfVDrPb9m3Yfm9K99OkuJgRTj1rjmeMF-Kpl-0oouEc8_mNk6oPIqD8nUNvH3FYqAA)}}"
}
@@ -0,0 +1,7 @@
int_val = {{encrypt(20)}}
bool_val = {{encrypt(true)}}
kms "aead" {
purpose = "root"
aead_type = "aes-gcm"
key ="{{encrypt(aA1hxJo0JUAqcIATx/r0QTjAGD/btCPechEsukI2bt0=)}}"
}
@@ -0,0 +1,7 @@
int_val = 20
bool_val = true
kms "aead" {
purpose = "root"
aead_type = "aes-gcm"
key ="aA1hxJo0JUAqcIATx/r0QTjAGD/btCPechEsukI2bt0=)"
}
@@ -0,0 +1,5 @@
kms "aead" {
purpose = "config"
aead_type = "aes-gcm"
key = "c964AJj8VW8w4hKz/Jd8MvuLt0kkcjVuFqMiMvTvvN8="
}
+37 -19
View File
@@ -10,9 +10,10 @@ import (
"github.com/hashicorp/boundary/internal/cmd/base"
"github.com/hashicorp/boundary/internal/cmd/config"
"github.com/hashicorp/boundary/internal/servers/controller"
"github.com/hashicorp/boundary/internal/wrapper"
"github.com/hashicorp/go-hclog"
wrapping "github.com/hashicorp/go-kms-wrapping"
"github.com/hashicorp/go-multierror"
"github.com/hashicorp/shared-secure-libs/configutil"
"github.com/hashicorp/vault/sdk/helper/mlock"
"github.com/hashicorp/vault/sdk/helper/strutil"
"github.com/mitchellh/cli"
@@ -33,9 +34,10 @@ type Command struct {
Config *config.Config
controller *controller.Controller
configKMS *configutil.KMS
configWrapper wrapping.Wrapper
flagConfig string
flagConfigKms string
flagLogLevel string
flagLogFormat string
flagCombineLogs bool
@@ -78,7 +80,17 @@ func (c *Command) Flags() *base.FlagSets {
complete.PredictFiles("*.hcl"),
complete.PredictFiles("*.json"),
),
Usage: "Path to a configuration file.",
Usage: "Path to the configuration file.",
})
f.StringVar(&base.StringVar{
Name: "config-kms",
Target: &c.flagConfigKms,
Completion: complete.PredictOr(
complete.PredictFiles("*.hcl"),
complete.PredictFiles("*.json"),
),
Usage: `Path to a configuration file containing a "kms" block marked for "config" purpose, to perform decryption of the main configuration file. If not set, will look for such a block in the main configuration file, which has some drawbacks; see the help output for "boundary config encrypt -h" for details.`,
})
f.StringVar(&base.StringVar{
@@ -178,6 +190,14 @@ func (c *Command) Run(args []string) int {
return result
}
if c.configWrapper != nil {
defer func() {
if err := c.configWrapper.Finalize(c.Context); err != nil {
c.UI.Warn(fmt.Errorf("Error finalizing config kms: %w", err).Error())
}
}()
}
if err := c.SetupLogging(c.flagLogLevel, c.flagLogFormat, c.Config.LogLevel, c.Config.LogFormat); err != nil {
c.UI.Error(err.Error())
return 1
@@ -317,19 +337,20 @@ func (c *Command) ParseFlagsAndConfig(args []string) int {
return 1
}
// preload the KMS for encrypting/decrypting the config parameters
kmss, err := configutil.LoadConfigKMSes(c.flagConfig)
wrapperPath := c.flagConfig
if c.flagConfigKms != "" {
wrapperPath = c.flagConfigKms
}
wrapper, err := wrapper.GetWrapper(wrapperPath, "config")
if err != nil {
c.UI.Error("error loading KMS config: " + err.Error())
c.UI.Error(err.Error())
return 1
}
for _, kms := range kmss {
for _, purpose := range kms.Purpose {
if purpose == "config" {
c.configKMS = kms
break
}
if wrapper != nil {
c.configWrapper = wrapper
if err := wrapper.Init(c.Context); err != nil {
c.UI.Error(fmt.Errorf("Could not initialize kms: %w", err).Error())
return 1
}
}
@@ -351,7 +372,7 @@ func (c *Command) ParseFlagsAndConfig(args []string) int {
c.flagDevLoginName = ""
}
c.Config, err = config.LoadFile(c.flagConfig, c.configKMS)
c.Config, err = config.LoadFile(c.flagConfig, wrapper)
if err != nil {
c.UI.Error("Error parsing config: " + err.Error())
return 1
@@ -361,7 +382,7 @@ func (c *Command) ParseFlagsAndConfig(args []string) int {
if len(c.flagConfig) == 0 {
c.Config, err = config.DevController()
} else {
c.Config, err = config.LoadFile(c.flagConfig, c.configKMS)
c.Config, err = config.LoadFile(c.flagConfig, wrapper)
}
if err != nil {
c.UI.Error(fmt.Errorf("Error creating dev config: %w", err).Error())
@@ -468,7 +489,7 @@ func (c *Command) WaitForInterrupt() int {
goto RUNRELOADFUNCS
}
newConf, err = config.LoadFile(c.flagConfig, c.configKMS)
newConf, err = config.LoadFile(c.flagConfig, c.configWrapper)
if err != nil {
c.Logger.Error("could not reload config", "path", c.flagConfig, "error", err)
goto RUNRELOADFUNCS
@@ -480,9 +501,6 @@ func (c *Command) WaitForInterrupt() int {
goto RUNRELOADFUNCS
}
// Commented out until we need this
//controller.SetConfig(config)
if newConf.LogLevel != "" {
configLogLevel := strings.ToLower(strings.TrimSpace(newConf.LogLevel))
switch configLogLevel {
+36 -18
View File
@@ -9,9 +9,10 @@ import (
"github.com/hashicorp/boundary/internal/cmd/base"
"github.com/hashicorp/boundary/internal/cmd/config"
"github.com/hashicorp/boundary/internal/servers/worker"
"github.com/hashicorp/boundary/internal/wrapper"
"github.com/hashicorp/go-hclog"
wrapping "github.com/hashicorp/go-kms-wrapping"
"github.com/hashicorp/go-multierror"
"github.com/hashicorp/shared-secure-libs/configutil"
"github.com/hashicorp/vault/sdk/helper/mlock"
"github.com/mitchellh/cli"
"github.com/posener/complete"
@@ -33,9 +34,10 @@ type Command struct {
Config *config.Config
worker *worker.Worker
configKMS *configutil.KMS
configWrapper wrapping.Wrapper
flagConfig string
flagConfigKms string
flagLogLevel string
flagLogFormat string
flagDev bool
@@ -76,6 +78,16 @@ func (c *Command) Flags() *base.FlagSets {
Usage: "Path to a configuration file.",
})
f.StringVar(&base.StringVar{
Name: "config-kms",
Target: &c.flagConfigKms,
Completion: complete.PredictOr(
complete.PredictFiles("*.hcl"),
complete.PredictFiles("*.json"),
),
Usage: `Path to a configuration file containing a "kms" block marked for "config" purpose, to perform decryption of the main configuration file. If not set, will look for such a block in the main configuration file, which has some drawbacks; see the help output for "boundary config encrypt -h" for details.`,
})
f.StringVar(&base.StringVar{
Name: "log-level",
Target: &c.flagLogLevel,
@@ -135,6 +147,14 @@ func (c *Command) Run(args []string) int {
return result
}
if c.configWrapper != nil {
defer func() {
if err := c.configWrapper.Finalize(c.Context); err != nil {
c.UI.Warn(fmt.Errorf("Error finalizing config kms: %w", err).Error())
}
}()
}
if err := c.SetupLogging(c.flagLogLevel, c.flagLogFormat, c.Config.LogLevel, c.Config.LogFormat); err != nil {
c.UI.Error(err.Error())
return 1
@@ -206,19 +226,20 @@ func (c *Command) ParseFlagsAndConfig(args []string) int {
return 1
}
// preload the KMS for encrypting/decrypting the config parameters
kmss, err := configutil.LoadConfigKMSes(c.flagConfig)
wrapperPath := c.flagConfig
if c.flagConfigKms != "" {
wrapperPath = c.flagConfigKms
}
wrapper, err := wrapper.GetWrapper(wrapperPath, "config")
if err != nil {
c.UI.Error("error loading KMS config: " + err.Error())
c.UI.Error(err.Error())
return 1
}
for _, kms := range kmss {
for _, purpose := range kms.Purpose {
if purpose == "config" {
c.configKMS = kms
break
}
if wrapper != nil {
c.configWrapper = wrapper
if err := wrapper.Init(c.Context); err != nil {
c.UI.Error(fmt.Errorf("Could not initialize kms: %w", err).Error())
return 1
}
}
@@ -228,7 +249,7 @@ func (c *Command) ParseFlagsAndConfig(args []string) int {
c.UI.Error("Must supply a config file with -config")
return 1
}
c.Config, err = config.LoadFile(c.flagConfig, c.configKMS)
c.Config, err = config.LoadFile(c.flagConfig, wrapper)
if err != nil {
c.UI.Error("Error parsing config: " + err.Error())
return 1
@@ -238,7 +259,7 @@ func (c *Command) ParseFlagsAndConfig(args []string) int {
if len(c.flagConfig) == 0 {
c.Config, err = config.DevWorker()
} else {
c.Config, err = config.LoadFile(c.flagConfig, c.configKMS)
c.Config, err = config.LoadFile(c.flagConfig, wrapper)
}
if err != nil {
c.UI.Error(fmt.Errorf("Error creating dev config: %s", err).Error())
@@ -311,7 +332,7 @@ func (c *Command) WaitForInterrupt() int {
goto RUNRELOADFUNCS
}
newConf, err = config.LoadFile(c.flagConfig, c.configKMS)
newConf, err = config.LoadFile(c.flagConfig, c.configWrapper)
if err != nil {
c.Logger.Error("could not reload config", "path", c.flagConfig, "error", err)
goto RUNRELOADFUNCS
@@ -323,9 +344,6 @@ func (c *Command) WaitForInterrupt() int {
goto RUNRELOADFUNCS
}
// Commented out until we need this
//c.worker.SetConfig(config)
if newConf.LogLevel != "" {
configLogLevel := strings.ToLower(strings.TrimSpace(newConf.LogLevel))
switch configLogLevel {
+4 -16
View File
@@ -2,13 +2,13 @@ package config
import (
"bytes"
"context"
"crypto/rand"
"encoding/base64"
"fmt"
"io"
"io/ioutil"
wrapping "github.com/hashicorp/go-kms-wrapping"
"github.com/hashicorp/hcl"
"github.com/hashicorp/shared-secure-libs/configutil"
)
@@ -175,7 +175,7 @@ func New() *Config {
}
// LoadFile loads the configuration from the given file.
func LoadFile(path string, kms *configutil.KMS) (*Config, error) {
func LoadFile(path string, wrapper wrapping.Wrapper) (*Config, error) {
d, err := ioutil.ReadFile(path)
if err != nil {
return nil, err
@@ -183,8 +183,8 @@ func LoadFile(path string, kms *configutil.KMS) (*Config, error) {
raw := string(d)
if kms != nil {
raw, err = configDecrypt(raw, kms)
if wrapper != nil {
raw, err = configutil.EncryptDecrypt(raw, true, true, wrapper)
if err != nil {
return nil, err
}
@@ -235,15 +235,3 @@ func (c *Config) Sanitized() map[string]interface{} {
return result
}
func configDecrypt(raw string, kms *configutil.KMS) (string, error) {
wrapper, err := configutil.ConfigureWrapper(kms, nil, nil, nil)
if err != nil {
return raw, err
}
wrapper.Init(context.Background())
defer wrapper.Finalize(context.Background())
return configutil.EncryptDecrypt(raw, true, true, wrapper)
}
+36
View File
@@ -0,0 +1,36 @@
package wrapper
import (
"fmt"
wrapping "github.com/hashicorp/go-kms-wrapping"
"github.com/hashicorp/shared-secure-libs/configutil"
"github.com/hashicorp/vault/sdk/helper/strutil"
)
func GetWrapper(path, purpose string) (wrapping.Wrapper, error) {
kmses, err := configutil.LoadConfigKMSes(path)
if err != nil {
return nil, fmt.Errorf("Error parsing config file: %w", err)
}
var kms *configutil.KMS
for _, v := range kmses {
if strutil.StrListContains(v.Purpose, purpose) {
if kms != nil {
return nil, fmt.Errorf("Only one %q block marked for %q purpose is allowed", "kms", purpose)
}
kms = v
}
}
if kms == nil {
return nil, nil
}
wrapper, err := configutil.ConfigureWrapper(kms, nil, nil, nil)
if err != nil {
return nil, fmt.Errorf("Error configuring kms: %w", err)
}
return wrapper, nil
}
-29
View File
@@ -11,8 +11,6 @@ import (
wrapping "github.com/hashicorp/go-kms-wrapping"
"github.com/hashicorp/go-uuid"
"github.com/hashicorp/shared-secure-libs/configutil"
"github.com/hashicorp/vault/sdk/helper/strutil"
"google.golang.org/protobuf/proto"
)
@@ -30,33 +28,6 @@ type Info struct {
CreationTime time.Time `json:"creation_time"`
}
func GetWrapper(ctx context.Context, path string) (wrapping.Wrapper, error) {
kmses, err := configutil.LoadConfigKMSes(path)
if err != nil {
return nil, fmt.Errorf("Error parsing config file: %w", err)
}
var kms *configutil.KMS
for _, v := range kmses {
if strutil.StrListContains(v.Purpose, "recovery") {
if kms != nil {
return nil, fmt.Errorf("Only one %q block marked for %q purpose is allowed", "kms", "recovery")
}
kms = v
}
}
if kms == nil {
return nil, fmt.Errorf("No %q block marked for %q purpose is allowed", "kms", "recovery")
}
wrapper, err := configutil.ConfigureWrapper(kms, nil, nil, nil)
if err != nil {
return nil, fmt.Errorf("Error configuring kms: %w", err)
}
return wrapper, nil
}
func GenerateRecoveryToken(ctx context.Context, wrapper wrapping.Wrapper) (string, error) {
b, err := uuid.GenerateRandomBytes(nonceLength)
if err != nil {