Files
threshold/internal/cmd/commands/config/encryptdecrypt.go
T
dependabot[bot]andJohan Brandhorst-Satzkorn 959fe3ebd3 chore(deps): bump the go group across 7 directories with 5 updates (#6035)
* chore(deps): bump the go group across 7 directories with 5 updates

Bumps the go group with 4 updates in the / directory: [github.com/coder/websocket](https://github.com/coder/websocket), [github.com/docker/docker](https://github.com/docker/docker), [github.com/prometheus/client_golang](https://github.com/prometheus/client_golang) and [mvdan.cc/gofumpt](https://github.com/mvdan/gofumpt).
Bumps the go group with 2 updates in the /api directory: [github.com/coder/websocket](https://github.com/coder/websocket) and [github.com/hashicorp/boundary/sdk](https://github.com/hashicorp/boundary).
Bumps the go group with 1 update in the /plugins/boundary/mains/aws directory: [github.com/hashicorp/boundary/sdk](https://github.com/hashicorp/boundary).
Bumps the go group with 1 update in the /plugins/boundary/mains/azure directory: [github.com/hashicorp/boundary/sdk](https://github.com/hashicorp/boundary).
Bumps the go group with 1 update in the /plugins/boundary/mains/gcp directory: [github.com/hashicorp/boundary/sdk](https://github.com/hashicorp/boundary).
Bumps the go group with 1 update in the /plugins/boundary/mains/minio directory: [github.com/hashicorp/boundary/sdk](https://github.com/hashicorp/boundary).
Bumps the go group with 1 update in the /sdk directory: [github.com/coder/websocket](https://github.com/coder/websocket).

Updates `github.com/coder/websocket` from 1.8.13 to 1.8.14
- [Release notes](https://github.com/coder/websocket/releases)
- [Commits](https://github.com/coder/websocket/compare/v1.8.13...v1.8.14)

Updates `github.com/docker/docker` from 28.3.3+incompatible to 28.4.0+incompatible
- [Release notes](https://github.com/docker/docker/releases)
- [Commits](https://github.com/docker/docker/compare/v28.3.3...v28.4.0)

Updates `github.com/prometheus/client_golang` from 1.23.0 to 1.23.2
- [Release notes](https://github.com/prometheus/client_golang/releases)
- [Changelog](https://github.com/prometheus/client_golang/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prometheus/client_golang/compare/v1.23.0...v1.23.2)

Updates `mvdan.cc/gofumpt` from 0.8.0 to 0.9.0
- [Release notes](https://github.com/mvdan/gofumpt/releases)
- [Changelog](https://github.com/mvdan/gofumpt/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mvdan/gofumpt/compare/v0.8.0...v0.9.0)

Updates `github.com/coder/websocket` from 1.8.13 to 1.8.14
- [Release notes](https://github.com/coder/websocket/releases)
- [Commits](https://github.com/coder/websocket/compare/v1.8.13...v1.8.14)

Updates `github.com/hashicorp/boundary/sdk` from 0.0.54 to 0.0.55
- [Release notes](https://github.com/hashicorp/boundary/releases)
- [Changelog](https://github.com/hashicorp/boundary/blob/main/CHANGELOG.md)
- [Commits](https://github.com/hashicorp/boundary/compare/api/v0.0.54...api/v0.0.55)

Updates `github.com/hashicorp/boundary/sdk` from 0.0.54 to 0.0.55
- [Release notes](https://github.com/hashicorp/boundary/releases)
- [Changelog](https://github.com/hashicorp/boundary/blob/main/CHANGELOG.md)
- [Commits](https://github.com/hashicorp/boundary/compare/api/v0.0.54...api/v0.0.55)

Updates `github.com/hashicorp/boundary/sdk` from 0.0.54 to 0.0.55
- [Release notes](https://github.com/hashicorp/boundary/releases)
- [Changelog](https://github.com/hashicorp/boundary/blob/main/CHANGELOG.md)
- [Commits](https://github.com/hashicorp/boundary/compare/api/v0.0.54...api/v0.0.55)

Updates `github.com/hashicorp/boundary/sdk` from 0.0.54 to 0.0.55
- [Release notes](https://github.com/hashicorp/boundary/releases)
- [Changelog](https://github.com/hashicorp/boundary/blob/main/CHANGELOG.md)
- [Commits](https://github.com/hashicorp/boundary/compare/api/v0.0.54...api/v0.0.55)

Updates `github.com/hashicorp/boundary/sdk` from 0.0.54 to 0.0.55
- [Release notes](https://github.com/hashicorp/boundary/releases)
- [Changelog](https://github.com/hashicorp/boundary/blob/main/CHANGELOG.md)
- [Commits](https://github.com/hashicorp/boundary/compare/api/v0.0.54...api/v0.0.55)

Updates `github.com/coder/websocket` from 1.8.13 to 1.8.14
- [Release notes](https://github.com/coder/websocket/releases)
- [Commits](https://github.com/coder/websocket/compare/v1.8.13...v1.8.14)

---
updated-dependencies:
- dependency-name: github.com/coder/websocket
  dependency-version: 1.8.14
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: go
- dependency-name: github.com/docker/docker
  dependency-version: 28.4.0+incompatible
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go
- dependency-name: github.com/prometheus/client_golang
  dependency-version: 1.23.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: go
- dependency-name: mvdan.cc/gofumpt
  dependency-version: 0.9.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go
- dependency-name: github.com/coder/websocket
  dependency-version: 1.8.14
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: go
- dependency-name: github.com/hashicorp/boundary/sdk
  dependency-version: 0.0.55
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: go
- dependency-name: github.com/hashicorp/boundary/sdk
  dependency-version: 0.0.55
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: go
- dependency-name: github.com/hashicorp/boundary/sdk
  dependency-version: 0.0.55
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: go
- dependency-name: github.com/hashicorp/boundary/sdk
  dependency-version: 0.0.55
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: go
- dependency-name: github.com/hashicorp/boundary/sdk
  dependency-version: 0.0.55
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: go
- dependency-name: github.com/coder/websocket
  dependency-version: 1.8.14
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: go
...

Signed-off-by: dependabot[bot] <support@github.com>

* Format files with latest gofumpt

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Johan Brandhorst-Satzkorn <johan.brandhorst@gmail.com>
2025-09-08 15:17:46 -04:00

240 lines
6.9 KiB
Go

// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package config
import (
"context"
"errors"
"fmt"
"net/textproto"
"os"
"strings"
"github.com/hashicorp/boundary/globals"
"github.com/hashicorp/boundary/internal/cmd/base"
kms_plugin_assets "github.com/hashicorp/boundary/plugins/kms"
"github.com/hashicorp/boundary/sdk/wrapper"
"github.com/hashicorp/go-hclog"
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/mitchellh/cli"
"github.com/posener/complete"
)
var (
_ cli.Command = (*EncryptDecryptCommand)(nil)
_ cli.CommandAutocomplete = (*EncryptDecryptCommand)(nil)
)
type EncryptDecryptCommand struct {
*base.Command
Func string
flagConfig string
flagConfigKms string
flagOverwrite bool
flagStrip bool
}
func (c *EncryptDecryptCommand) Synopsis() string {
return fmt.Sprintf("%s sensitive values in Boundary's configuration file", textproto.CanonicalMIMEHeaderKey(c.Func))
}
func (c *EncryptDecryptCommand) Help() string {
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.`,
"",
"",
)
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(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,
Usage: "Overwrite the existing file.",
})
f.BoolVar(&base.BoolVar{
Name: "strip",
Target: &c.flagStrip,
Usage: "Strip the declarations from the file afterwards.",
})
return set
}
func (c *EncryptDecryptCommand) AutocompleteArgs() complete.Predictor {
return complete.PredictAnything
}
func (c *EncryptDecryptCommand) AutocompleteFlags() complete.Flags {
return c.Flags().Completions()
}
func (c *EncryptDecryptCommand) Run(args []string) (ret int) {
f := c.Flags()
if err := f.Parse(args); err != nil {
c.UI.Error(err.Error())
return base.CommandUserError
}
switch c.flagConfig {
case "":
c.UI.Error(`Missing required parameter -config`)
return base.CommandUserError
default:
c.flagConfig = strings.TrimSpace(c.flagConfig)
}
kmsDefFile := c.flagConfig
switch c.flagConfigKms {
case "":
default:
kmsDefFile = strings.TrimSpace(c.flagConfigKms)
}
wrapper, cleanupFunc, err := wrapper.GetWrapperFromPath(
c.Context,
kmsDefFile,
globals.KmsPurposeConfig,
configutil.WithPluginOptions(
pluginutil.WithPluginsMap(kms_plugin_assets.BuiltinKmsPlugins()),
pluginutil.WithPluginsFilesystem(kms_plugin_assets.KmsPluginPrefix, kms_plugin_assets.FileSystem()),
),
// TODO: How would we want to expose this kind of log to users when
// using recovery configs? Generally with normal CLI commands we
// don't print out all of these logs. We may want a logger with a
// custom writer behind our existing gate where we print nothing
// unless there is an error, then dump all of it.
configutil.WithLogger(hclog.NewNullLogger()),
)
if err != nil {
c.UI.Error(err.Error())
return base.CommandUserError
}
if wrapper == nil {
c.UI.Error(`No wrapper with "config" purpose found"`)
return base.CommandUserError
}
if cleanupFunc != nil {
defer func() {
if err := cleanupFunc(); err != nil {
c.UI.Warn(fmt.Errorf("Error cleaning up KMS wrapper: %w", err).Error())
}
}()
}
if ifWrapper, ok := wrapper.(wrapping.InitFinalizer); ok {
if err := ifWrapper.Init(c.Context); err != nil && !errors.Is(err, wrapping.ErrFunctionNotImplemented) {
c.UI.Error(fmt.Errorf("Error initializing KMS: %w", err).Error())
return base.CommandUserError
}
defer func() {
if err := ifWrapper.Finalize(context.Background()); err != nil && !errors.Is(err, wrapping.ErrFunctionNotImplemented) {
c.UI.Warn(fmt.Errorf("Error encountered when finalizing KMS: %w", err).Error())
}
}()
}
d, err := os.ReadFile(c.flagConfig)
if err != nil {
c.UI.Error(fmt.Errorf("Error reading config file: %w", err).Error())
return base.CommandUserError
}
raw := string(d)
raw, err = configutil.EncryptDecrypt(raw, c.Func == "decrypt", c.flagStrip, wrapper)
if err != nil {
c.UI.Error(fmt.Errorf("Error %sing via kms: %w", c.Func, err).Error())
return base.CommandCliError
}
if !c.flagOverwrite {
c.UI.Output(raw)
return base.CommandSuccess
}
file, err := os.Create(c.flagConfig)
if err != nil {
c.UI.Error(fmt.Errorf("Error opening file for writing: %w", err).Error())
return base.CommandCliError
}
defer func() {
if err := file.Close(); err != nil {
c.UI.Error(fmt.Errorf("Error closing file after writing: %w", err).Error())
ret = base.CommandCliError
}
}()
n, err := file.WriteString(raw)
if err != nil {
c.UI.Error(fmt.Errorf("Error writing to file: %w", err).Error())
return base.CommandCliError
}
if n != len(raw) {
c.UI.Error(fmt.Sprintf("Wrong number of bytes written to file, expected %d, wrote %d", len(raw), n))
}
return ret
}