Skip to content

Instantly share code, notes, and snippets.

@autrilla
Created July 17, 2019 19:50
Show Gist options
  • Select an option

  • Save autrilla/58402d9cdda972bffbda6fd7fcfe49e5 to your computer and use it in GitHub Desktop.

Select an option

Save autrilla/58402d9cdda972bffbda6fd7fcfe49e5 to your computer and use it in GitHub Desktop.

SOPS: Secrets OPerationS

sops is a secrets management solution and editor of encrypted files that supports a variety of file formats and encryption providers.

Here is a quick demo of sops in action:

SOPS in action

A more in-depth overview is available as part of Julien Vehent's Securing DevOps Show & Tell:

<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/V2PRhxphH2w" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

If you want to use SOPS as a Go library, take a look at the decrypt package.

Questions? Ping ulfr and autrilla in #security on irc.mozilla.org (you can use a web client like mibbit).

What happened to Python SOPS? We rewrote sops in Go to solve a number of deployment issues, but the Python branch still exists under python-sops. We will keep maintaining it for a while, and you can still pip install sops, but we strongly recommend you use the Go version instead.

Backward compatibility

We strive to make as few backwards-incompatible changes as possible to the sops command line tool. We follow Semantic Versioning, so in the rare occurence that we break compatibility on the CLI, you'll know.

The file format will always be backwards compatible: this means that newer versions of SOPS will be able to load files created with older versions of SOPS.

Security

Please report security issues to jvehent at mozilla dot com, or by using one of the contact method available on keybase: https://keybase.io/jvehent

License

Mozilla Public License Version 2.0

Authors

The core team is composed of:

And a whole bunch of contributors.

Credits

SOPS was inspired by hiera-eyaml, credstash, sneaker, password store, and too many years managing PGP encrypted files by hand.

Decrypting files

Suppose you have an encrypted SOPS file, and would like to decrypt it. As an example, let's use the file from Encrypting files:

$ cat my_file.enc
{
	"data": "ENC[AES256_GCM,data:2jQNm13QiRfVWf/nEk8=,iv:s7vZVoMFcQ32TvhQixVc6ZxC5EevnTBG3UxlQ8lD1iM=,tag:sa6j6Im4tQDCqt2oHCWXjg==,type:str]",
	"sops": {
		"kms": null,
		"gcp_kms": null,
		"azure_kv": null,
		"lastmodified": "2019-07-17T19:12:15Z",
		"mac": "ENC[AES256_GCM,data:5uvzX7kRrFCL5a58js1ls4ALltUtqqi5ZhoQGMbXDZdTDxYaCLkoFTg4PCOil7133g1uaye6f9AjPgvEUGpPFONWg6g9k6k7fN/AsgSiYSZUHD1yCQZhyiKIVhxrnFV+0v0fH5Zwm7bZAqrUrzaH3YGpo6ces9iBSsHMCEHDGdc=,iv:7LX+irD4XrmuHsCYKJvd4BsP5TMkWeLSc6I+heg+c0s=,tag:33WZIPkU5LOMny0L7cx6fg==,type:str]",
		"pgp": [
			{
				"created_at": "2019-07-17T19:12:15Z",
				"enc": "-----BEGIN PGP MESSAGE-----\n\nwYwDEEVDpnzXnMABBACsHmqe5BT4S4O684E39czJrmGkRTSMYX9YCnSVNUVMkwNY\n+JL6FmuLC13320weeO3xL9CCDJIKAGixTehi5JDVY1rK9bCuUTQrjN8NMEHPAZn8\nRvB/W0hKkqaOOpAjq2syp2RjTnNOn8cqkP80Jo9w3BXIJJitBJuKC850Vh0FJdLg\nAeTzXWkhERBsxwJ4ADawDWCU4XPi4M7gDOHmiOAa4shf6zjgwOU5PFnDtDG0kLCl\n49NAKBboOSyEx9sFA4on3j7GLXnroOCj5OwgcsBqIjxerkXizChBS1ziKXEME+Gc\neAA=\n=snqD\n-----END PGP MESSAGE-----",
				"fp": "1022470DE3F0BC54BC6AB62DE05550BC07FB1A0A"
			}
		],
		"unencrypted_suffix": "_unencrypted",
		"version": "3.3.1"
	}
}

Let's decrypt it:

$ sops --decrypt my_file.enc
hello, world!

As expected, the original file contents are returned and printed to standard output.

Editing files

Existing files

Suppose you have an encrypted SOPS file, and would like to edit it. As an example, let's use the file from Encrypting files:

$ cat my_file.enc
{
	"data": "ENC[AES256_GCM,data:2jQNm13QiRfVWf/nEk8=,iv:s7vZVoMFcQ32TvhQixVc6ZxC5EevnTBG3UxlQ8lD1iM=,tag:sa6j6Im4tQDCqt2oHCWXjg==,type:str]",
	"sops": {
		"kms": null,
		"gcp_kms": null,
		"azure_kv": null,
		"lastmodified": "2019-07-17T19:12:15Z",
		"mac": "ENC[AES256_GCM,data:5uvzX7kRrFCL5a58js1ls4ALltUtqqi5ZhoQGMbXDZdTDxYaCLkoFTg4PCOil7133g1uaye6f9AjPgvEUGpPFONWg6g9k6k7fN/AsgSiYSZUHD1yCQZhyiKIVhxrnFV+0v0fH5Zwm7bZAqrUrzaH3YGpo6ces9iBSsHMCEHDGdc=,iv:7LX+irD4XrmuHsCYKJvd4BsP5TMkWeLSc6I+heg+c0s=,tag:33WZIPkU5LOMny0L7cx6fg==,type:str]",
		"pgp": [
			{
				"created_at": "2019-07-17T19:12:15Z",
				"enc": "-----BEGIN PGP MESSAGE-----\n\nwYwDEEVDpnzXnMABBACsHmqe5BT4S4O684E39czJrmGkRTSMYX9YCnSVNUVMkwNY\n+JL6FmuLC13320weeO3xL9CCDJIKAGixTehi5JDVY1rK9bCuUTQrjN8NMEHPAZn8\nRvB/W0hKkqaOOpAjq2syp2RjTnNOn8cqkP80Jo9w3BXIJJitBJuKC850Vh0FJdLg\nAeTzXWkhERBsxwJ4ADawDWCU4XPi4M7gDOHmiOAa4shf6zjgwOU5PFnDtDG0kLCl\n49NAKBboOSyEx9sFA4on3j7GLXnroOCj5OwgcsBqIjxerkXizChBS1ziKXEME+Gc\neAA=\n=snqD\n-----END PGP MESSAGE-----",
				"fp": "1022470DE3F0BC54BC6AB62DE05550BC07FB1A0A"
			}
		],
		"unencrypted_suffix": "_unencrypted",
		"version": "3.3.1"
	}
}

Let's edit it:

$ sops my_file.enc

This will open the decrypted, plain-text file in your editor. You can then make any changes you desire, save the file, and exit your editor. The encrypted file will be updated with the modifications you made.

New files

sops lets you create new encrypted files directly as well. You will be shown an example file for whichever storage format you are using. You can edit that example file and save, and your changes will be encrypted and persisted in the file.

Advantages over manually decrypting, editing, and then reencrypting a file

Editing files directly through sops has a big advantage: the data key and other cryptographic values are preserved. For formats that have some sort of key-value structure, this allows sops to leave encrypted values that were not modified completely unchanged, which in turn allows users to get an idea of what was modified in a file by using version control systems and differs, even if they do not have access to the plain-text decrypted data at all.

What editor will sops use?

sops uses the EDITOR environment variable to decide what editor to use. If the variable is not set, sops will then try a few common editors found on most systems.

GUI Editors (Sublime, Atom, et al.)

Some editors, especially GUI editors, spawn a new process and then immediately exit when executed. sops relies on your editor exiting to know when you're done editing the file. Because those editors exit immediately, sops will always think you haven't modified the file at all.

To work around this, consult your editor's documentation for an option that will make it wait until it is closed for the process to exit. This is sometimes offered as a command line flag. In that case, you will need to wrap your editor in a script that passes a command line flag, since the EDITOR environment variable does not accept arguments. For example, for Atom:

#!/bin/bash
atom -w

Make that script executable and then set EDITOR to its location.

Encrypting files

Suppose you already have a plain-text, unencrypted file, and would like sops to encrypt it:

$ cat my_file
hello, world!

You can do so as follows:

$ sops --encrypt my_file
{
	"data": "ENC[AES256_GCM,data:45IFIHXi0pogtNwIE90=,iv:Lu7aGNAHCvwi3VMyJewjhj+pxYCi05gdTpYC1DKFmg8=,tag:YlRb8za8o1lJ4XiTj/KxfA==,type:str]",
	"sops": {
		"kms": null,
		"gcp_kms": null,
		"azure_kv": null,
		"lastmodified": "2019-07-17T18:59:59Z",
		"mac": "ENC[AES256_GCM,data:bYHCF4z/wxIwUBDEEvyCwqUu2v+LWxRikYnI9fC2OVnwcIDadH/xhK1zIrRxq0HugeQYSar5GsCjgy4jhiaxfG1RlQZnkL2Iz/wT+ZdxwY4yeLJ+4/tRwjxCqhrmq2uTihskP7RFVLp6TqM9r/JAyCzqDHxScPmAMVydDTieYaU=,iv:jD4yvBNS075aCbv+OvRdFXjOD13etsux01XL2d5F2cw=,tag:vxm/paFnCtEmIgqkv4h+OQ==,type:str]",
		"pgp": [
			{
				"created_at": "2019-07-17T18:59:58Z",
				"enc": "-----BEGIN PGP MESSAGE-----\n\nwYwDEEVDpnzXnMABBAClqG2V54awfbG/6CuIlnawf5FnFizG4lCV9iXHHeth/r1W\n+1ejBKY9EcrnW/o59adGFmknDsIDAmJaQE3V9fruOdtMixr9MjkNqUfT90c/mCZ9\nV+yA4UfDoZuNzRk3Bkb/7PuT02X9eASdn4V3ShbGmbdMk37NQPel9QXcuAVlqtLg\nAeRzhNVGICGVGpLuzCnvP4DN4XZR4IfghuEe2eD14lmfIRLg7+VDb4IMf81bpomg\ndqXmTpbTsV/5gQxjdijsvh5QRDO2duDe5LTwyRWkZgxtkMee0XZKCVLi5gmRNeFO\n8gA=\n=Udaa\n-----END PGP MESSAGE-----",
				"fp": "1022470DE3F0BC54BC6AB62DE05550BC07FB1A0A"
			}
		],
		"unencrypted_suffix": "_unencrypted",
		"version": "3.3.1"
	}
}

!> You need at least one master key available to encrypt a file.

The encrypted file is written to standard output. If you want to save it permanentely, you can either use your shell to redirect the output to a file, or you can operate on the file in-place.

Installation

Stable release

Binaries and packages of the latest stable release are available here.

Development branch

For the adventurous, unstable features are available in the develop branch, which you can install from source:

$ go get -u go.mozilla.org/sops/cmd/sops
$ cd $GOPATH/src/go.mozilla.org/sops/
$ git checkout develop
$ make install

Requires Go 1.12 or newer. If you don't have Go installed, refer to the official Go documentation.

Quick Start

Now that you've have the sops binary installed, you should be able to run the binary:

$ sops -v
sops 3.3.1 (latest)

For simplicity, we will use PGP as an encryption provider. We assume you already have a PGP key, but if you don't, Github's documentation explains how you can create one. Take note of your public key's fingerprint, as you'll need it later.

?> Tip: you can find your key's fingerprint by running gpg --list-keys. The fingerprint is a long string (typically 40 characters) of hexadecimal characters.

In my case, the PGP fingerprint is 1022470DE3F0BC54BC6AB62DE05550BC07FB1A0A, so I will be using that for the rest of the quick start. Replace it with your own fingerprint whenever I use it. This is used by the SOPS project for testing infrastructure. If you struggle generating your own key, you can use this fingerprint as well, as sops will try to download the key from the Internet if it is not available locally.

!> If you use the SOPS testing infrastructure key, you won't be able to decrypt files unless you also download and import the private key. It is available here. Download it and then import it with gpg --import sops_functional_tests_key.asc.

Now that we have our PGP key set up, let's create a new SOPS encrypted file:

$ sops --pgp 1022470DE3F0BC54BC6AB62DE05550BC07FB1A0A quickstart.yaml

Upon running this, you should be taken to an editor and be shown an example file:

hello: Welcome to SOPS! Edit this file as you please!
example_key: example_value
# Example comment
example_array:
- example_value1
- example_value2
example_number: 1234.5679
example_booleans:
- true
- false

Make some edits to the file, for example, add some data to the end of the file, so it looks like this:

hello: Welcome to SOPS! Edit this file as you please!
example_key: example_value
# Example comment
example_array:
- example_value1
- example_value2
example_number: 1234.5679
example_booleans:
- true
- false
some_more_data:
  hello: world

Save the file. Let's see what it looks like:

$ cat quickstart.yaml
hello: ENC[AES256_GCM,data:r8pcvLb9EZyZFdy/Q1S0lI6JNxsZuf1QM9ZUw7n/A8QkBf1e9B7yOcI1BbzjcQ==,iv:mI5g/blnelhbr75h/yhxyrExPDPaEProWyh9Q0OItv4=,tag:w8ixFTZkRtc+OVSyZOPlrw==,type:str]
example_key: ENC[AES256_GCM,data:87zFG19/7ooxavTFHA==,iv:E3po1Pf4vvqfOaZtfNMPA6BnUCxs1FHu95AVVv3zbrc=,tag:gM7hn6jlXn9QKYPalUkL1g==,type:str]
#ENC[AES256_GCM,data:eJZ9g+Ikh1ijDuwADlbksg==,iv:k8yO0gFoFkpWX/dTZ5IsNvh0ld/cxSkiE0kgyVegZs8=,tag:7qB7CANMs4ZndzfAqrmNiA==,type:comment]
example_array:
- ENC[AES256_GCM,data:rDGwfQzcPB7MWWj+ks8=,iv:LEKN7Yq2KXpukQJcEFG9VJAJ4vSs+2r3QlljHYbsIuA=,tag:JG4WyZOqUzzPkAlPAo/bnQ==,type:str]
- ENC[AES256_GCM,data:TdLQadOzpSTZ4dMqSG0=,iv:AUE5L4VMy+N6tw/aeyZhQcckFxjQgTI3UyI6p6o2HOE=,tag:AAh+WQpO/jSvGvbEH5/QPw==,type:str]
example_number: ENC[AES256_GCM,data:vZkNkTjce/tC,iv:8FlC3NF+AJpHJ6JGtl1oMgw+8btxsKlZqCbXlhQ60Ss=,tag:2AaHYIC7OSYU27JxQTlhXQ==,type:float]
example_booleans:
- ENC[AES256_GCM,data:4oWlWw==,iv:YxEiZ+uweb8rLZBY5nvtt/8LpCl9q+TTCJEyyu6gzhE=,tag:pcZl3mh0y+Uyo/bRePXohg==,type:bool]
- ENC[AES256_GCM,data:FBeNQA4=,iv:dQOSHy8Tgs8f2lsRmUiIZdACfyL+R1OqA+DS7vxuyeI=,tag:Dy3+kQl+vBY8GLObY/qqDw==,type:bool]
some_more_data:
    hello: ENC[AES256_GCM,data:UKybdeY=,iv:SyP3DdAFPOOXZkAkHtKiauH5t0T/lUZbGdo+SI9g80k=,tag:4mgLyrtWWdbNbXolho2v2A==,type:str]
sops:
    kms: []
    gcp_kms: []
    azure_kv: []
    lastmodified: '2019-07-17T15:52:25Z'
    mac: ENC[AES256_GCM,data:CURHSaJhLt4l9yQQqUtkrXZNDCj00SMYM6eal4U/u2XbitH1mR0nsLsRlePo2KPu7NbrJ7P46nqIwuvBbWrF2MGKa3ucTdY1pyJJCWD0+OK1+lV3P8T47/ZxN7r+aCDHVue8StRIcufvtLbtZ/01pDeg3gviSH1JwtP3VaCeihc=,iv:OQ0imfPs9JtAB2Np3V+WXbA+LwhUdQzZaIz6ZwJ3glU=,tag:HAHjEXsaPDvw2zW+d9WFCg==,type:str]
    pgp:
    -   created_at: '2019-07-17T15:51:36Z'
        enc: |-
            -----BEGIN PGP MESSAGE-----

            wYwDEEVDpnzXnMABBAB/NzaqcAN5K1JEC3RTCZcQZ/9GfZ8gnxIeVWArH1S7qN1m
            6y+m7/oYM/xEH76abBdE85lLdoFHsuKEzMcfhdYiyjjwy2zJHkzzb3NMwFqgBeeu
            ok9L3xn4LswDNxRgM+OhQqvkg2+i5QgXUcDNxEBLsNIEhyR1eZnIUafeRX3ht9Lg
            AeTRLKmYvzSNcsTLFEXGVs2w4bi14KjgzOGiNuCJ4o6QJ9DgUuW8SVR1ytG0Mj+e
            FoUTmga/cV996OasIPD/iUqOgJCFD+Cj5AtclYK8JbSoPIJYpc2CGAbi6bZ6LOGQ
            sgA=
            =O39v
            -----END PGP MESSAGE-----
        fp: 1022470DE3F0BC54BC6AB62DE05550BC07FB1A0A
    unencrypted_suffix: _unencrypted
    version: 3.3.1

None of the values in our plain text YAML file are visible, they've all been encrypted! We can make some further edits to the file by running sops quickstart.yaml. We don't need to specify our PGP key fingerprint again, as the SOPS file format stores this information already.

For more ways to use sops, please consult the rest of the documentation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment