1
0
mirror of https://github.com/getsops/sops.git synced 2026-02-05 12:45:21 +01:00

Add and use encrypt and decrypt subcommands.

Signed-off-by: Felix Fontein <felix@fontein.de>
This commit is contained in:
Felix Fontein
2023-11-05 16:15:28 +01:00
parent 4ca66e5a75
commit 2ae16f5457
7 changed files with 402 additions and 69 deletions

View File

@@ -154,7 +154,7 @@ To decrypt a file in a ``cat`` fashion, use the ``-d`` flag:
.. code:: sh
$ sops -d mynewtestfile.yaml
$ sops decrypt mynewtestfile.yaml
SOPS encrypted files contain the necessary information to decrypt their content.
All a user of SOPS needs is valid AWS credentials and the necessary
@@ -200,7 +200,7 @@ the ``--age`` option or the **SOPS_AGE_RECIPIENTS** environment variable:
.. code:: sh
$ sops --encrypt --age age1yt3tfqlfrwdwx0z0ynwplcr6qxcxfaqycuprpmy89nr83ltx74tqdpszlw test.yaml > test.enc.yaml
$ sops encrypt --age age1yt3tfqlfrwdwx0z0ynwplcr6qxcxfaqycuprpmy89nr83ltx74tqdpszlw test.yaml > test.enc.yaml
When decrypting a file with the corresponding identity, SOPS will look for a
text file name ``keys.txt`` located in a ``sops`` subdirectory of your user
@@ -250,11 +250,11 @@ sdk:
Now you can encrypt a file using::
$ sops --encrypt --gcp-kms projects/my-project/locations/global/keyRings/sops/cryptoKeys/sops-key test.yaml > test.enc.yaml
$ sops encrypt --gcp-kms projects/my-project/locations/global/keyRings/sops/cryptoKeys/sops-key test.yaml > test.enc.yaml
And decrypt it using::
$ sops --decrypt test.enc.yaml
$ sops decrypt test.enc.yaml
Encrypting using Azure Key Vault
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -324,11 +324,11 @@ from the commandline:
Now you can encrypt a file using::
$ sops --encrypt --azure-kv https://sops.vault.azure.net/keys/sops-key/some-string test.yaml > test.enc.yaml
$ sops encrypt --azure-kv https://sops.vault.azure.net/keys/sops-key/some-string test.yaml > test.enc.yaml
And decrypt it using::
$ sops --decrypt test.enc.yaml
$ sops decrypt test.enc.yaml
Encrypting and decrypting from other programs
@@ -344,7 +344,7 @@ To decrypt data, you can simply do:
.. code:: sh
$ cat encrypted-data | sops --decrypt /dev/stdin > decrypted-data
$ 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
@@ -354,7 +354,7 @@ 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
$ cat encrypted-data | sops decrypt --input-type yaml --output-type yaml /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
@@ -363,7 +363,7 @@ parameter which allows you to tell SOPS which filename to use to match creation
.. code:: sh
$ echo 'foo: bar' | sops --filename-override path/filename.sops.yaml --encrypt /dev/stdin > encrypted-data
$ echo 'foo: bar' | sops encrypt --filename-override path/filename.sops.yaml /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,
@@ -372,7 +372,7 @@ the input store type can be adjusted by passing ``--input-type``, and the output
.. code:: sh
$ echo foo=bar | sops --filename-override path/filename.sops.yaml --input-type dotenv --encrypt /dev/stdin > encrypted-data
$ echo foo=bar | sops encrypt --filename-override path/filename.sops.yaml --input-type dotenv /dev/stdin > encrypted-data
Encrypting using Hashicorp Vault
@@ -423,7 +423,7 @@ To easily deploy Vault locally: (DO NOT DO THIS FOR PRODUCTION!!!)
$ vault write sops/keys/thirdkey type=chacha20-poly1305
Success! Data written to: sops/keys/thirdkey
$ sops --encrypt --hc-vault-transit $VAULT_ADDR/v1/sops/keys/firstkey vault_example.yml
$ sops encrypt --hc-vault-transit $VAULT_ADDR/v1/sops/keys/firstkey vault_example.yml
$ cat <<EOF > .sops.yaml
creation_rules:
@@ -433,7 +433,7 @@ To easily deploy Vault locally: (DO NOT DO THIS FOR PRODUCTION!!!)
hc_vault_transit_uri: "$VAULT_ADDR/v1/sops/keys/thirdkey"
EOF
$ sops --verbose -e prod/raw.yaml > prod/encrypted.yaml
$ sops encrypt --verbose prod/raw.yaml > prod/encrypted.yaml
Adding and removing keys
~~~~~~~~~~~~~~~~~~~~~~~~
@@ -888,7 +888,7 @@ You can then decrypt the file the same way as with any other SOPS file:
.. code:: sh
$ sops -d example.json
$ sops decrypt example.json
Key service
~~~~~~~~~~~
@@ -928,14 +928,14 @@ service exposed on the unix socket located in ``/tmp/sops.sock``, you can run:
.. code:: sh
$ sops --keyservice unix:///tmp/sops.sock -d file.yaml`
$ sops decrypt --keyservice unix:///tmp/sops.sock file.yaml`
And if you only want to use the key service exposed on the unix socket located
in ``/tmp/sops.sock`` and not the local key service, you can run:
.. code:: sh
$ sops --enable-local-keyservice=false --keyservice unix:///tmp/sops.sock -d file.yaml
$ sops decrypt --enable-local-keyservice=false --keyservice unix:///tmp/sops.sock file.yaml
Auditing
~~~~~~~~
@@ -1002,7 +1002,7 @@ written to disk.
.. code:: sh
# print secrets to stdout to confirm values
$ sops -d out.json
$ sops decrypt out.json
{
"database_password": "jf48t9wfw094gf4nhdf023r",
"AWS_ACCESS_KEY_ID": "AKIAIOSFODNN7EXAMPLE",
@@ -1152,7 +1152,7 @@ Below is an example of publishing to Vault (using token auth with a local dev in
$ export VAULT_TOKEN=...
$ export VAULT_ADDR='http://127.0.0.1:8200'
$ sops -d vault/test.yaml
$ sops decrypt vault/test.yaml
example_string: bar
example_number: 42
example_map:
@@ -1193,23 +1193,23 @@ extension after encrypting a file. For example:
.. code:: sh
$ sops -e -i myfile.json
$ sops -d myfile.json
$ sops encrypt -i myfile.json
$ sops decrypt myfile.json
If you want to change the extension of the file once encrypted, you need to provide
``sops`` with the ``--input-type`` flag upon decryption. For example:
.. code:: sh
$ sops -e myfile.json > myfile.json.enc
$ sops encrypt myfile.json > myfile.json.enc
$ sops -d --input-type json myfile.json.enc
$ sops decrypt --input-type json myfile.json.enc
When operating on stdin, use the ``--input-type`` and ``--output-type`` flags as follows:
.. code:: sh
$ cat myfile.json | sops --input-type json --output-type json -d /dev/stdin
$ cat myfile.json | sops decrypt --input-type json --output-type json /dev/stdin
JSON and JSON_binary indentation
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -1361,13 +1361,13 @@ encrypt the file, and redirect the output to a destination file.
$ export SOPS_KMS_ARN="arn:aws:kms:us-west-2:927034868273:key/fe86dd69-4132-404c-ab86-4269956b4500"
$ export SOPS_PGP_FP="C9CAB0AF1165060DB58D6D6B2653B624D620786D"
$ sops -e /path/to/existing/file.yaml > /path/to/new/encrypted/file.yaml
$ sops encrypt /path/to/existing/file.yaml > /path/to/new/encrypted/file.yaml
Decrypt the file with ``-d``.
.. code:: sh
$ sops -d /path/to/new/encrypted/file.yaml
$ sops decrypt /path/to/new/encrypted/file.yaml
Encrypt or decrypt a file in place
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -1378,9 +1378,9 @@ original file after encrypting or decrypting it.
.. code:: sh
# file.yaml is in cleartext
$ sops -e -i /path/to/existing/file.yaml
$ sops encrypt -i /path/to/existing/file.yaml
# file.yaml is now encrypted
$ sops -d -i /path/to/existing/file.yaml
$ sops decrypt -i /path/to/existing/file.yaml
# file.yaml is back in cleartext
Encrypting binary files
@@ -1407,10 +1407,10 @@ In-place encryption/decryption also works on binary files.
$ sha512sum /tmp/somerandom
9589bb20280e9d381f7a192000498c994e921b3cdb11d2ef5a986578dc2239a340b25ef30691bac72bdb14028270828dad7e8bd31e274af9828c40d216e60cbe /tmp/somerandom
$ sops -e -i /tmp/somerandom
$ sops encrypt -i /tmp/somerandom
please wait while a data encryption key is being generated and stored securely
$ sops -d -i /tmp/somerandom
$ sops decrypt -i /tmp/somerandom
$ sha512sum /tmp/somerandom
9589bb20280e9d381f7a192000498c994e921b3cdb11d2ef5a986578dc2239a340b25ef30691bac72bdb14028270828dad7e8bd31e274af9828c40d216e60cbe /tmp/somerandom
@@ -1424,7 +1424,7 @@ values, like keys, without needing an extra parser.
.. code:: sh
$ sops -d --extract '["app2"]["key"]' ~/git/svc/sops/example.yaml
$ sops decrypt --extract '["app2"]["key"]' ~/git/svc/sops/example.yaml
-----BEGIN RSA PRIVATE KEY-----
MIIBPAIBAAJBAPTMNIyHuZtpLYc7VsHQtwOkWYobkUblmHWRmbXzlAX6K8tMf3Wf
ImcbNkqAKnELzFAPSBeEMhrBN0PyOC9lYlMCAwEAAQJBALXD4sjuBn1E7Y9aGiMz
@@ -1441,7 +1441,7 @@ them.
.. code:: sh
$ sops -d --extract '["an_array"][1]' ~/git/svc/sops/example.yaml
$ sops decrypt --extract '["an_array"][1]' ~/git/svc/sops/example.yaml
secretuser2
Set a sub-part in a document tree
@@ -1488,11 +1488,11 @@ to a SOPS command in the git configuration file of the repository.
.. code:: sh
$ git config diff.sopsdiffer.textconv "sops -d"
$ git config diff.sopsdiffer.textconv "sops decrypt"
$ grep -A 1 sopsdiffer .git/config
[diff "sopsdiffer"]
textconv = "sops -d"
textconv = "sops decrypt"
With this in place, calls to ``git diff`` will decrypt both previous and current
versions of the target file prior to displaying the diff. And it even works with
@@ -1527,7 +1527,7 @@ keys that match the supplied regular expression. For example, this command:
.. code:: sh
$ sops --encrypt --encrypted-regex '^(data|stringData)$' k8s-secrets.yaml
$ sops encrypt --encrypted-regex '^(data|stringData)$' k8s-secrets.yaml
will encrypt the values under the ``data`` and ``stringData`` keys in a YAML file
containing kubernetes secrets. It will not encrypt other values that help you to
@@ -1539,7 +1539,7 @@ that match the supplied regular expression. For example, this command:
.. code:: sh
$ sops --encrypt --unencrypted-regex '^(description|metadata)$' k8s-secrets.yaml
$ sops encrypt --unencrypted-regex '^(description|metadata)$' k8s-secrets.yaml
will not encrypt the values under the ``description`` and ``metadata`` keys in a YAML file
containing kubernetes secrets, while encrypting everything else.

View File

@@ -128,7 +128,7 @@ func main() {
The -p, -k, --gcp-kms, --hc-vault-transit, and --azure-kv flags are only
used to encrypt new documents. Editing or decrypting existing documents
can be done with "sops file" or "sops -d file" respectively. The KMS and
can be done with "sops file" or "sops decrypt file" respectively. The KMS and
PGP keys listed in the encrypted documents are used then. To manage master
keys in existing documents, use the "add-{kms,pgp,gcp-kms,azure-kv,hc-vault-transit}"
and "rm-{kms,pgp,gcp-kms,azure-kv,hc-vault-transit}" flags with --rotate
@@ -622,6 +622,282 @@ func main() {
return nil
},
},
{
Name: "decrypt",
Usage: "decrypt a file, and output the results to stdout",
ArgsUsage: `file`,
Flags: append([]cli.Flag{
cli.BoolFlag{
Name: "in-place, i",
Usage: "write output back to the same file instead of stdout",
},
cli.StringFlag{
Name: "extract",
Usage: "extract a specific key or branch from the input document. Example: --extract '[\"somekey\"][0]'",
},
cli.StringFlag{
Name: "output",
Usage: "Save the output after decryption to the file specified",
},
cli.StringFlag{
Name: "input-type",
Usage: "currently json, yaml, dotenv and binary are supported. If not set, sops will use the file's extension to determine the type",
},
cli.StringFlag{
Name: "output-type",
Usage: "currently json, yaml, dotenv and binary are supported. If not set, sops will use the input file's extension to determine the output format",
},
cli.BoolFlag{
Name: "ignore-mac",
Usage: "ignore Message Authentication Code during decryption",
},
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",
},
cli.StringFlag{
Name: "decryption-order",
Usage: "comma separated list of decryption key types",
EnvVar: "SOPS_DECRYPTION_ORDER",
},
}, keyserviceFlags...),
Action: func(c *cli.Context) error {
if c.Bool("verbose") {
logging.SetLevel(logrus.DebugLevel)
}
if c.NArg() < 1 {
return common.NewExitError("Error: no file specified", codes.NoFileSpecified)
}
warnMoreThanOnePositionalArgument(c)
if c.Bool("in-place") && c.String("output") != "" {
return common.NewExitError("Error: cannot operate on both --output and --in-place", codes.ErrorConflictingParameters)
}
fileName, err := filepath.Abs(c.Args()[0])
if err != nil {
return toExitError(err)
}
if _, err := os.Stat(fileName); os.IsNotExist(err) {
return common.NewExitError("Error: cannot operate on non-existent file", codes.NoFileSpecified)
}
fileNameOverride := c.String("filename-override")
if fileNameOverride == "" {
fileNameOverride = fileName
}
inputStore := inputStore(c, fileNameOverride)
outputStore := outputStore(c, fileNameOverride)
svcs := keyservices(c)
order, err := decryptionOrder(c.String("decryption-order"))
if err != nil {
return toExitError(err)
}
var extract []interface{}
extract, err = parseTreePath(c.String("extract"))
if err != nil {
return common.NewExitError(fmt.Errorf("error parsing --extract path: %s", err), codes.InvalidTreePathFormat)
}
output, err := decrypt(decryptOpts{
OutputStore: outputStore,
InputStore: inputStore,
InputPath: fileName,
Cipher: aes.NewCipher(),
Extract: extract,
KeyServices: svcs,
DecryptionOrder: order,
IgnoreMAC: c.Bool("ignore-mac"),
})
if err != nil {
return toExitError(err)
}
// We open the file *after* the operations on the tree have been
// executed to avoid truncating it when there's errors
if c.Bool("in-place") {
file, err := os.Create(fileName)
if err != nil {
return common.NewExitError(fmt.Sprintf("Could not open in-place file for writing: %s", err), codes.CouldNotWriteOutputFile)
}
defer file.Close()
_, err = file.Write(output)
if err != nil {
return toExitError(err)
}
log.Info("File written successfully")
return nil
}
outputFile := os.Stdout
if c.String("output") != "" {
file, err := os.Create(c.String("output"))
if err != nil {
return common.NewExitError(fmt.Sprintf("Could not open output file for writing: %s", err), codes.CouldNotWriteOutputFile)
}
defer file.Close()
outputFile = file
}
_, err = outputFile.Write(output)
return toExitError(err)
},
},
{
Name: "encrypt",
Usage: "encrypt a file, and output the results to stdout",
ArgsUsage: `file`,
Flags: append([]cli.Flag{
cli.BoolFlag{
Name: "in-place, i",
Usage: "write output back to the same file instead of stdout",
},
cli.StringFlag{
Name: "output",
Usage: "Save the output after decryption to the file specified",
},
cli.StringFlag{
Name: "kms, k",
Usage: "comma separated list of KMS ARNs",
EnvVar: "SOPS_KMS_ARN",
},
cli.StringFlag{
Name: "aws-profile",
Usage: "The AWS profile to use for requests to AWS",
},
cli.StringFlag{
Name: "gcp-kms",
Usage: "comma separated list of GCP KMS resource IDs",
EnvVar: "SOPS_GCP_KMS_IDS",
},
cli.StringFlag{
Name: "azure-kv",
Usage: "comma separated list of Azure Key Vault URLs",
EnvVar: "SOPS_AZURE_KEYVAULT_URLS",
},
cli.StringFlag{
Name: "hc-vault-transit",
Usage: "comma separated list of vault's key URI (e.g. 'https://vault.example.org:8200/v1/transit/keys/dev')",
EnvVar: "SOPS_VAULT_URIS",
},
cli.StringFlag{
Name: "pgp, p",
Usage: "comma separated list of PGP fingerprints",
EnvVar: "SOPS_PGP_FP",
},
cli.StringFlag{
Name: "age, a",
Usage: "comma separated list of age recipients",
EnvVar: "SOPS_AGE_RECIPIENTS",
},
cli.StringFlag{
Name: "input-type",
Usage: "currently json, yaml, dotenv and binary are supported. If not set, sops will use the file's extension to determine the type",
},
cli.StringFlag{
Name: "output-type",
Usage: "currently json, yaml, dotenv and binary are supported. If not set, sops will use the input file's extension to determine the output format",
},
cli.StringFlag{
Name: "unencrypted-suffix",
Usage: "override the unencrypted key suffix.",
},
cli.StringFlag{
Name: "encrypted-suffix",
Usage: "override the encrypted key suffix. When empty, all keys will be encrypted, unless otherwise marked with unencrypted-suffix.",
},
cli.StringFlag{
Name: "unencrypted-regex",
Usage: "set the unencrypted key regex. When specified, only keys matching the regex will be left unencrypted.",
},
cli.StringFlag{
Name: "encrypted-regex",
Usage: "set the encrypted key regex. When specified, only keys matching the regex will be encrypted.",
},
cli.StringFlag{
Name: "encryption-context",
Usage: "comma separated list of KMS encryption context key:value pairs",
},
cli.IntFlag{
Name: "shamir-secret-sharing-threshold",
Usage: "the number of master keys required to retrieve the data key with shamir",
},
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...),
Action: func(c *cli.Context) error {
if c.Bool("verbose") {
logging.SetLevel(logrus.DebugLevel)
}
if c.NArg() < 1 {
return common.NewExitError("Error: no file specified", codes.NoFileSpecified)
}
warnMoreThanOnePositionalArgument(c)
if c.Bool("in-place") && c.String("output") != "" {
return common.NewExitError("Error: cannot operate on both --output and --in-place", codes.ErrorConflictingParameters)
}
fileName, err := filepath.Abs(c.Args()[0])
if err != nil {
return toExitError(err)
}
if _, err := os.Stat(fileName); os.IsNotExist(err) {
return common.NewExitError("Error: cannot operate on non-existent file", codes.NoFileSpecified)
}
fileNameOverride := c.String("filename-override")
if fileNameOverride == "" {
fileNameOverride = fileName
}
inputStore := inputStore(c, fileNameOverride)
outputStore := outputStore(c, fileNameOverride)
svcs := keyservices(c)
encConfig, err := getEncryptConfig(c, fileNameOverride)
if err != nil {
return toExitError(err)
}
output, err := encrypt(encryptOpts{
OutputStore: outputStore,
InputStore: inputStore,
InputPath: fileName,
Cipher: aes.NewCipher(),
KeyServices: svcs,
encryptConfig: encConfig,
})
if err != nil {
return toExitError(err)
}
// We open the file *after* the operations on the tree have been
// executed to avoid truncating it when there's errors
if c.Bool("in-place") {
file, err := os.Create(fileName)
if err != nil {
return common.NewExitError(fmt.Sprintf("Could not open in-place file for writing: %s", err), codes.CouldNotWriteOutputFile)
}
defer file.Close()
_, err = file.Write(output)
if err != nil {
return toExitError(err)
}
log.Info("File written successfully")
return nil
}
outputFile := os.Stdout
if c.String("output") != "" {
file, err := os.Create(c.String("output"))
if err != nil {
return common.NewExitError(fmt.Sprintf("Could not open output file for writing: %s", err), codes.CouldNotWriteOutputFile)
}
defer file.Close()
outputFile = file
}
_, err = outputFile.Write(output)
return toExitError(err)
},
},
}
app.Flags = append([]cli.Flag{
cli.BoolFlag{

View File

@@ -42,7 +42,7 @@ In both development and production, we will be storing the secrets file unencryp
As peace of mind, think about this:
- Unencrypted on disk is fine because if the attacker ever gains access to the server, then they can run ``sops --decrypt`` as well.
- Unencrypted on disk is fine because if the attacker ever gains access to the server, then they can run ``sops decrypt`` as well.
Files
-----
@@ -69,7 +69,7 @@ For testing in a public CI, we can copy ``secret.enc.json`` to ``secret.json``.
..
For convenience, we can run ``CONFIG_COPY_ONLY=TRUE bin/decrypt-config.sh`` which will use ``cp`` rather than ``sops --decrypt``.
For convenience, we can run ``CONFIG_COPY_ONLY=TRUE bin/decrypt-config.sh`` which will use ``cp`` rather than ``sops decrypt``.
For testing in a private CI where we need private information, see the `Production instructions <#production>`_.

View File

@@ -17,6 +17,6 @@ for file in $secret_files; do
cp "$src_file" "$target_file"
# Otherwise, decrypt it
else
sops --decrypt "$src_file" > "$target_file"
sops decrypt "$src_file" > "$target_file"
fi
done

View File

@@ -47,7 +47,7 @@ In both development and production, we will be storing the secrets file unencryp
As peace of mind, think about this:
- Unencrypted on disk is fine because if the attacker ever gains access to the server, then they can run ``sops --decrypt`` as well.
- Unencrypted on disk is fine because if the attacker ever gains access to the server, then they can run ``sops decrypt`` as well.
Files
-----
@@ -78,7 +78,7 @@ For testing in a public CI, we can copy ``config.enc`` to ``config``. The secret
..
For convenience, we can run ``CONFIG_COPY_ONLY=TRUE bin/decrypt-config.sh`` which will use ``ln -s`` rather than ``sops --decrypt``.
For convenience, we can run ``CONFIG_COPY_ONLY=TRUE bin/decrypt-config.sh`` which will use ``ln -s`` rather than ``sops decrypt``.
For testing in a private CI where we need private information, see the `Production instructions <#production>`_.

View File

@@ -25,7 +25,7 @@ for src_file in config.enc/*; do
# If the file is our secret, then decrypt it
if echo "$src_filename" | grep -E "${secret_ext}$" &&
test "$CONFIG_COPY_ONLY" != "TRUE"; then
sops --decrypt "$src_file" > "$target_file"
sops decrypt "$src_file" > "$target_file"
# Otherwise, symlink to the original file
else
ln -s "../$src_file" "$target_file"

View File

@@ -60,7 +60,7 @@ mod tests {
}",
);
let output = Command::new(SOPS_BINARY_PATH)
.arg("-e")
.arg("encrypt")
.arg(file_path.clone())
.output()
.expect("Error running sops");
@@ -92,7 +92,7 @@ mod tests {
);
assert!(
Command::new(SOPS_BINARY_PATH)
.arg("-e")
.arg("encrypt")
.arg("-i")
.arg(file_path.clone())
.output()
@@ -127,7 +127,7 @@ mod tests {
);
assert!(
Command::new(SOPS_BINARY_PATH)
.arg("-e")
.arg("encrypt")
.arg("-i")
.arg(file_path.clone())
.output()
@@ -162,7 +162,7 @@ mod tests {
);
assert!(
Command::new(SOPS_BINARY_PATH)
.arg("-e")
.arg("encrypt")
.arg("-i")
.arg(file_path.clone())
.output()
@@ -201,9 +201,9 @@ mod tests {
);
let output = Command::new(SOPS_BINARY_PATH)
.arg("encrypt")
.arg("--kms")
.arg(kms_arn)
.arg("-e")
.arg(file_path.clone())
.output()
.expect("Error running sops");
@@ -231,7 +231,7 @@ mod tests {
bar: baz",
);
let output = Command::new(SOPS_BINARY_PATH)
.arg("-e")
.arg("encrypt")
.arg(file_path.clone())
.output()
.expect("Error running sops");
@@ -257,7 +257,7 @@ bar: baz",
prepare_temp_file("test_set_update.json", r#"{"a": 2, "b": "ba"}"#.as_bytes());
assert!(
Command::new(SOPS_BINARY_PATH)
.arg("-e")
.arg("encrypt")
.arg("-i")
.arg(file_path.clone())
.output()
@@ -300,7 +300,7 @@ bar: baz",
prepare_temp_file("test_set_insert.json", r#"{"a": 2, "b": "ba"}"#.as_bytes());
assert!(
Command::new(SOPS_BINARY_PATH)
.arg("-e")
.arg("encrypt")
.arg("-i")
.arg(file_path.clone())
.output()
@@ -347,7 +347,7 @@ b: ba"#
);
assert!(
Command::new(SOPS_BINARY_PATH)
.arg("-e")
.arg("encrypt")
.arg("-i")
.arg(file_path.clone())
.output()
@@ -394,7 +394,7 @@ b: ba"#
);
assert!(
Command::new(SOPS_BINARY_PATH)
.arg("-e")
.arg("encrypt")
.arg("-i")
.arg(file_path.clone())
.output()
@@ -436,6 +436,63 @@ b: ba"#
let file_path = prepare_temp_file(
"test_set_string.yaml",
r#"a: 2
b: ba"#
.as_bytes(),
);
assert!(
Command::new(SOPS_BINARY_PATH)
.arg("encrypt")
.arg("-i")
.arg(file_path.clone())
.output()
.expect("Error running sops")
.status
.success(),
"sops didn't exit successfully"
);
assert!(
Command::new(SOPS_BINARY_PATH)
.arg("--set")
.arg(r#"["a"] "aaa""#)
.arg("-i")
.arg(file_path.clone())
.output()
.expect("Error running sops")
.status
.success(),
"sops didn't exit successfully"
);
let output = Command::new(SOPS_BINARY_PATH)
.arg("decrypt")
.arg("-i")
.arg(file_path.clone())
.output()
.expect("Error running sops");
assert!(output.status.success(), "sops didn't exit successfully");
println!(
"stdout: {}, stderr: {}",
String::from_utf8_lossy(&output.stdout),
String::from_utf8_lossy(&output.stderr)
);
let mut s = String::new();
File::open(file_path)
.unwrap()
.read_to_string(&mut s)
.unwrap();
let data: Value = serde_yaml::from_str(&s).expect("Error parsing sops's YAML output");
if let Value::Mapping(data) = data {
let a = data.get(&Value::String("a".to_owned())).unwrap();
assert_eq!(a, &Value::String("aaa".to_owned()));
} else {
panic!("Output JSON does not have the expected structure");
}
}
#[test]
fn set_yaml_file_string_compat() {
let file_path = prepare_temp_file(
"test_set_string_compat.yaml",
r#"a: 2
b: ba"#
.as_bytes(),
);
@@ -496,7 +553,7 @@ b: ba"#
);
assert!(
!Command::new(SOPS_BINARY_PATH)
.arg("-d")
.arg("decrypt")
.arg(file_path.clone())
.output()
.expect("Error running sops")
@@ -507,7 +564,7 @@ b: ba"#
assert!(
Command::new(SOPS_BINARY_PATH)
.arg("-d")
.arg("decrypt")
.arg("--ignore-mac")
.arg(file_path.clone())
.output()
@@ -522,7 +579,7 @@ b: ba"#
fn encrypt_comments() {
let file_path = "res/comments.yaml";
let output = Command::new(SOPS_BINARY_PATH)
.arg("-e")
.arg("encrypt")
.arg(file_path.clone())
.output()
.expect("Error running sops");
@@ -541,7 +598,7 @@ b: ba"#
fn encrypt_comments_list() {
let file_path = "res/comments_list.yaml";
let output = Command::new(SOPS_BINARY_PATH)
.arg("-e")
.arg("encrypt")
.arg(file_path.clone())
.output()
.expect("Error running sops");
@@ -560,7 +617,7 @@ b: ba"#
fn decrypt_comments() {
let file_path = "res/comments.enc.yaml";
let output = Command::new(SOPS_BINARY_PATH)
.arg("-d")
.arg("decrypt")
.arg(file_path.clone())
.output()
.expect("Error running sops");
@@ -579,7 +636,7 @@ b: ba"#
fn decrypt_comments_unencrypted_comments() {
let file_path = "res/comments_unencrypted_comments.yaml";
let output = Command::new(SOPS_BINARY_PATH)
.arg("-d")
.arg("decrypt")
.arg(file_path.clone())
.output()
.expect("Error running sops");
@@ -599,8 +656,8 @@ b: ba"#
// The .sops.yaml file ensures this file is encrypted with two key groups, each with one GPG key
let file_path = prepare_temp_file("test_roundtrip_keygroups.yaml", "a: secret".as_bytes());
let output = Command::new(SOPS_BINARY_PATH)
.arg("encrypt")
.arg("-i")
.arg("-e")
.arg(file_path.clone())
.output()
.expect("Error running sops");
@@ -609,7 +666,7 @@ b: ba"#
"SOPS failed to encrypt a file with Shamir Secret Sharing"
);
let output = Command::new(SOPS_BINARY_PATH)
.arg("-d")
.arg("decrypt")
.arg(file_path.clone())
.output()
.expect("Error running sops");
@@ -629,8 +686,8 @@ b: ba"#
"a: secret".as_bytes(),
);
let output = Command::new(SOPS_BINARY_PATH)
.arg("encrypt")
.arg("-i")
.arg("-e")
.arg(file_path.clone())
.output()
.expect("Error running sops");
@@ -639,7 +696,7 @@ b: ba"#
"SOPS failed to encrypt a file with Shamir Secret Sharing"
);
let output = Command::new(SOPS_BINARY_PATH)
.arg("-d")
.arg("decrypt")
.arg(file_path.clone())
.output()
.expect("Error running sops");
@@ -656,7 +713,7 @@ b: ba"#
include_bytes!("../res/multiple_keys.yaml"),
);
let output = Command::new(SOPS_BINARY_PATH)
.arg("-d")
.arg("decrypt")
.arg(file_path.clone())
.output()
.expect("Error running sops");
@@ -673,16 +730,16 @@ b: ba"#
"multiline: |\n multi\n line".as_bytes(),
);
let output = Command::new(SOPS_BINARY_PATH)
.arg("encrypt")
.arg("-i")
.arg("-e")
.arg(file_path.clone())
.output()
.expect("Error running sops");
assert!(output.status.success(), "SOPS failed to encrypt a file");
let output = Command::new(SOPS_BINARY_PATH)
.arg("decrypt")
.arg("--extract")
.arg("[\"multiline\"]")
.arg("-d")
.arg(file_path.clone())
.output()
.expect("Error running sops");
@@ -696,8 +753,8 @@ b: ba"#
let data = b"\"\"{}this_is_binary_data";
let file_path = prepare_temp_file("test.binary", data);
let output = Command::new(SOPS_BINARY_PATH)
.arg("encrypt")
.arg("-i")
.arg("-e")
.arg(file_path.clone())
.output()
.expect("Error running sops");
@@ -706,7 +763,7 @@ b: ba"#
"SOPS failed to encrypt a binary file"
);
let output = Command::new(SOPS_BINARY_PATH)
.arg("-d")
.arg("decrypt")
.arg(file_path.clone())
.output()
.expect("Error running sops");
@@ -732,19 +789,19 @@ b: ba"#
);
let output = Command::new(SOPS_BINARY_PATH)
.arg("encrypt")
.arg("--kms")
.arg(kms_arn)
.arg("--encryption-context")
.arg("foo:bar,one:two")
.arg("-i")
.arg("-e")
.arg(file_path.clone())
.output()
.expect("Error running sops");
assert!(output.status.success(), "sops didn't exit successfully");
let output = Command::new(SOPS_BINARY_PATH)
.arg("-d")
.arg("decrypt")
.arg(file_path.clone())
.output()
.expect("Error running sops");
@@ -761,9 +818,9 @@ b: ba"#
let input_path = prepare_temp_file("test_output_flag.binary", b"foo");
let output_path = Path::join(TMP_DIR.path(), "output_flag.txt");
let output = Command::new(SOPS_BINARY_PATH)
.arg("encrypt")
.arg("--output")
.arg(&output_path)
.arg("-e")
.arg(input_path.clone())
.output()
.expect("Error running sops");