Skip to content

Commit

Permalink
Do not use DotEnv store for exec-env.
Browse files Browse the repository at this point in the history
This avoids quoting problems, fixes getsops#784, and also better handles
various problems that can arise, like '=' in keys and non-string
keys and values.

Signed-off-by: Felix Fontein <[email protected]>
  • Loading branch information
felixfontein committed Jun 15, 2024
1 parent 67aab01 commit daabd14
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 8 deletions.
13 changes: 11 additions & 2 deletions cmd/sops/decrypt.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ type decryptOpts struct {
DecryptionOrder []string
}

func decrypt(opts decryptOpts) (decryptedFile []byte, err error) {
tree, err := common.LoadEncryptedFileWithBugFixes(common.GenericDecryptOpts{
func decryptTree(opts decryptOpts) (tree *sops.Tree, err error) {
tree, err = common.LoadEncryptedFileWithBugFixes(common.GenericDecryptOpts{
Cipher: opts.Cipher,
InputStore: opts.InputStore,
InputPath: opts.InputPath,
Expand All @@ -48,6 +48,15 @@ func decrypt(opts decryptOpts) (decryptedFile []byte, err error) {
return nil, err
}

return tree, nil
}

func decrypt(opts decryptOpts) (decryptedFile []byte, err error) {
tree, err := decryptTree(opts)
if err != nil {
return nil, err
}

if len(opts.Extract) > 0 {
return extract(tree, opts.Extract, opts.OutputStore)
}
Expand Down
27 changes: 25 additions & 2 deletions cmd/sops/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -192,17 +192,40 @@ func main() {
log.Warn("exec-env's --background option is deprecated and will be removed in a future version of sops")
}

output, err := decrypt(opts)
tree, err := decryptTree(opts)
if err != nil {
return toExitError(err)
}

var env []string
for _, item := range tree.Branches[0] {
if dotenv.IsComplexValue(item.Value) {
return cli.NewExitError(fmt.Errorf("cannot use complex value in environment: %s", item.Value), codes.ErrorGeneric)
}
if _, ok := item.Key.(sops.Comment); ok {
continue
}
key, ok := item.Key.(string)
if !ok {
return cli.NewExitError(fmt.Errorf("cannot use non-string keys in environment, got %T", item.Key), codes.ErrorGeneric)
}
if strings.Contains(key, "=") {
return cli.NewExitError(fmt.Errorf("cannot use keys with '=' in environment: %s", key), codes.ErrorGeneric)
}
value, ok := item.Value.(string)
if !ok {
return cli.NewExitError(fmt.Errorf("cannot use non-string values in environment, got %T", item.Value), codes.ErrorGeneric)
}
env = append(env, fmt.Sprintf("%s=%s", key, value))
}

if err := exec.ExecWithEnv(exec.ExecOpts{
Command: command,
Plaintext: output,
Plaintext: []byte{},
Background: c.Bool("background"),
Pristine: c.Bool("pristine"),
User: c.String("user"),
Env: env,
}); err != nil {
return toExitError(err)
}
Expand Down
11 changes: 10 additions & 1 deletion cmd/sops/subcommand/exec/exec.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ type ExecOpts struct {
Fifo bool
User string
Filename string
Env []string
}

func GetFile(dir, filename string) *os.File {
Expand Down Expand Up @@ -88,9 +89,15 @@ func ExecWithFile(opts ExecOpts) error {
filename = handle.Name()
}

var env []string
if !opts.Pristine {
env = os.Environ()
}
env = append(env, opts.Env...)

placeholdered := strings.Replace(opts.Command, "{}", filename, -1)
cmd := BuildCommand(placeholdered)
cmd.Env = os.Environ()
cmd.Env = env

if opts.Background {
return cmd.Start()
Expand Down Expand Up @@ -125,6 +132,8 @@ func ExecWithEnv(opts ExecOpts) error {
env = append(env, string(line))
}

env = append(env, opts.Env...)

cmd := BuildCommand(opts.Command)
cmd.Env = env

Expand Down
2 changes: 1 addition & 1 deletion functional-tests/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -902,7 +902,7 @@ echo -E "${bar}"
String::from_utf8_lossy(&output.stdout),
String::from_utf8_lossy(&output.stderr)
);
assert_eq!(String::from_utf8_lossy(&output.stdout), "baz\\nbam\n");
assert_eq!(String::from_utf8_lossy(&output.stdout), "baz\nbam\n");
}

#[test]
Expand Down
4 changes: 2 additions & 2 deletions stores/dotenv/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ func (store *Store) EmitEncryptedFile(in sops.Tree) ([]byte, error) {
func (store *Store) EmitPlainFile(in sops.TreeBranches) ([]byte, error) {
buffer := bytes.Buffer{}
for _, item := range in[0] {
if isComplexValue(item.Value) {
if IsComplexValue(item.Value) {
return nil, fmt.Errorf("cannot use complex value in dotenv file: %s", item.Value)
}
var line string
Expand Down Expand Up @@ -166,7 +166,7 @@ func (store *Store) EmitExample() []byte {
return bytes
}

func isComplexValue(v interface{}) bool {
func IsComplexValue(v interface{}) bool {
switch v.(type) {
case []interface{}:
return true
Expand Down

0 comments on commit daabd14

Please sign in to comment.