mirror of
https://github.com/getsops/sops.git
synced 2026-02-05 12:45:21 +01:00
Do not use DotEnv store for exec-env.
This avoids quoting problems, fixes #784, and also better handles various problems that can arise, like '=' in keys and non-string keys and values. Signed-off-by: Felix Fontein <felix@fontein.de>
This commit is contained in:
@@ -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,
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ type ExecOpts struct {
|
||||
Fifo bool
|
||||
User string
|
||||
Filename string
|
||||
Env []string
|
||||
}
|
||||
|
||||
func GetFile(dir, filename string) *os.File {
|
||||
@@ -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()
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user