Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1069,6 +1069,11 @@ written to disk.
$ echo your password: $database_password
your password:

If you want process signals to be sent to the command, for example if you are
running ``exec-env`` to launch a server and your server handles SIGTERM, then the
``--same-process`` flag can be used to instruct ``sops`` to start your command in
the same process instead of a child process. This uses the ``execve`` system call
and is supported on Unix-like systems.

If the command you want to run only operates on files, you can use ``exec-file``
instead. By default, SOPS will use a FIFO to pass the contents of the
Expand Down
21 changes: 15 additions & 6 deletions cmd/sops/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,10 @@ func main() {
Name: "user",
Usage: "the user to run the command as",
},
cli.BoolFlag{
Name: "same-process",
Usage: "run command in the current process instead of in a child process",
},
}, keyserviceFlags...),
Action: func(c *cli.Context) error {
if c.NArg() != 2 {
Expand Down Expand Up @@ -195,6 +199,10 @@ func main() {

if c.Bool("background") {
log.Warn("exec-env's --background option is deprecated and will be removed in a future version of sops")

if c.Bool("same-process") {
return common.NewExitError("Error: The --same-process flag cannot be used with --background", codes.ErrorConflictingParameters)
}
}

tree, err := decryptTree(opts)
Expand Down Expand Up @@ -225,12 +233,13 @@ func main() {
}

if err := exec.ExecWithEnv(exec.ExecOpts{
Command: command,
Plaintext: []byte{},
Background: c.Bool("background"),
Pristine: c.Bool("pristine"),
User: c.String("user"),
Env: env,
Command: command,
Plaintext: []byte{},
Background: c.Bool("background"),
Pristine: c.Bool("pristine"),
User: c.String("user"),
SameProcess: c.Bool("same-process"),
Env: env,
}); err != nil {
return toExitError(err)
}
Expand Down
31 changes: 23 additions & 8 deletions cmd/sops/subcommand/exec/exec.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package exec

import (
"bytes"
"fmt"
"os"
"path/filepath"
"runtime"
Expand All @@ -23,14 +24,15 @@ func init() {
}

type ExecOpts struct {
Command string
Plaintext []byte
Background bool
Pristine bool
Fifo bool
User string
Filename string
Env []string
Command string
Plaintext []byte
Background bool
SameProcess bool
Pristine bool
Fifo bool
User string
Filename string
Env []string
}

func GetFile(dir, filename string) *os.File {
Expand Down Expand Up @@ -115,6 +117,10 @@ func ExecWithEnv(opts ExecOpts) error {
SwitchUser(opts.User)
}

if runtime.GOOS == "windows" && opts.SameProcess {
return fmt.Errorf("The --same-process flag is not supported on Windows")
}

var env []string

if !opts.Pristine {
Expand All @@ -134,6 +140,15 @@ func ExecWithEnv(opts ExecOpts) error {

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

if opts.SameProcess {
if opts.Background {
log.Fatal("background is not supported for same-process")
}

// Note that the call does NOT return, unless an error happens.
return ExecSyscall(opts.Command, env)
}

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

Expand Down
4 changes: 4 additions & 0 deletions cmd/sops/subcommand/exec/exec_unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ import (
"syscall"
)

func ExecSyscall(command string, env []string) error {
return syscall.Exec("/bin/sh", []string{"/bin/sh", "-c", command}, env)
}

func BuildCommand(command string) *exec.Cmd {
return exec.Command("/bin/sh", "-c", command)
}
Expand Down
5 changes: 5 additions & 0 deletions cmd/sops/subcommand/exec/exec_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ import (
"os/exec"
)

func ExecSyscall(command string, env []string) error {
log.Fatal("same-process not available on windows")
return nil
}

func BuildCommand(command string) *exec.Cmd {
return exec.Command("cmd.exe", "/C", command)
}
Expand Down
Loading