diff --git a/README.rst b/README.rst index 82cf622d4..c47ac6e63 100644 --- a/README.rst +++ b/README.rst @@ -323,7 +323,51 @@ Now you can encrypt a file using:: And decrypt it using:: - $ sops --decrypt test.enc.yaml + $ sops --decrypt test.enc.yaml + + +Encrypting and decrypting from other programs +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +When using ``sops`` in scripts or from other programs, there are often situations where you do not want to write +encrypted or decrypted data to disk. The best way to avoid this is to pass data to SOPS via stdin, and to let +SOPS write data to stdout. By default, the encrypt and decrypt operations write data to stdout already. To pass +data via stdin, you need to pass ``/dev/stdin`` as the input filename. Please note that this only works on +Unix-like operating systems such as macOS and Linux. On Windows, you have to use named pipes. + +To decrypt data, you can simply do: + +.. code:: sh + + $ cat encrypted-data | sops --decrypt /dev/stdin > decrypted-data + +To control the input and output format, pass ``--input-type`` and ``--output-type`` as appropriate. By default, +``sops`` determines the input and output format from the provided filename, which is ``/dev/stdin`` here, and +thus will use the binary store which expects JSON input and outputs binary data on decryption. + +For example, to decrypt YAML data and obtain the decrypted result as YAML, use: + +.. code:: sh + + $ cat encrypted-data | sops --input-type yaml --output-type yaml --decrypt /dev/stdin > decrypted-data + +To encrypt, it is important to note that SOPS also uses the filename to look up the correct creation rule from +``.sops.yaml``. Likely ``/dev/stdin`` will not match a creation rule, or only match the fallback rule without +``path_regex``, which is usually not what you want. For that, ``sops`` provides the ``--filename-override`` +parameter which allows you to tell SOPS which filename to use to match creation rules: + +.. code:: sh + + $ echo 'foo: bar' | sops --filename-override path/filename.sops.yaml --encrypt /dev/stdin > encrypted-data + +SOPS will find a matching creation rule for ``path/filename.sops.yaml`` in ``.sops.yaml`` and use that one to +encrypt the data from stdin. This filename will also be used to determine the input and output store. As always, +the input store type can be adjusted by passing ``--input-type``, and the output store type by passing +``--output-type``: + +.. code:: sh + + $ echo foo=bar | sops --filename-override path/filename.sops.yaml --input-type dotenv --encrypt /dev/stdin > encrypted-data Encrypting using Hashicorp Vault diff --git a/cmd/sops/main.go b/cmd/sops/main.go index 0b3b0b6ae..26e084c26 100644 --- a/cmd/sops/main.go +++ b/cmd/sops/main.go @@ -769,6 +769,10 @@ func main() { Name: "output", Usage: "Save the output after encryption or decryption to the file specified", }, + cli.StringFlag{ + Name: "filename-override", + Usage: "Use this filename instead of the provided argument for loading configuration, and for determining input type and output type", + }, }, keyserviceFlags...) app.Action = func(c *cli.Context) error { @@ -795,13 +799,17 @@ func main() { return common.NewExitError("Error: cannot operate on non-existent file", codes.NoFileSpecified) } } + fileNameOverride := c.String("filename-override") + if fileNameOverride == "" { + fileNameOverride = fileName + } unencryptedSuffix := c.String("unencrypted-suffix") encryptedSuffix := c.String("encrypted-suffix") encryptedRegex := c.String("encrypted-regex") unencryptedRegex := c.String("unencrypted-regex") macOnlyEncrypted := c.Bool("mac-only-encrypted") - conf, err := loadConfig(c, fileName, nil) + conf, err := loadConfig(c, fileNameOverride, nil) if err != nil { return toExitError(err) } @@ -847,19 +855,19 @@ func main() { unencryptedSuffix = sops.DefaultUnencryptedSuffix } - inputStore := inputStore(c, fileName) - outputStore := outputStore(c, fileName) + inputStore := inputStore(c, fileNameOverride) + outputStore := outputStore(c, fileNameOverride) svcs := keyservices(c) var output []byte if c.Bool("encrypt") { var groups []sops.KeyGroup - groups, err = keyGroups(c, fileName) + groups, err = keyGroups(c, fileNameOverride) if err != nil { return toExitError(err) } var threshold int - threshold, err = shamirThreshold(c, fileName) + threshold, err = shamirThreshold(c, fileNameOverride) if err != nil { return toExitError(err) } @@ -1015,12 +1023,12 @@ func main() { } else { // File doesn't exist, edit the example file instead var groups []sops.KeyGroup - groups, err = keyGroups(c, fileName) + groups, err = keyGroups(c, fileNameOverride) if err != nil { return toExitError(err) } var threshold int - threshold, err = shamirThreshold(c, fileName) + threshold, err = shamirThreshold(c, fileNameOverride) if err != nil { return toExitError(err) }