• Home
  • History
  • Annotate
Name Date Size #Lines LOC

..03-May-2022-

.circleci/H14-Sep-2020-10391

aes/H14-Sep-2020-313274

audit/H14-Sep-2020-184134

azkv/H14-Sep-2020-406325

bin/ci/H14-Sep-2020-3423

cmd/sops/H14-Sep-2020-3,0592,646

config/H14-Sep-2020-780688

decrypt/H14-Sep-2020-13394

examples/H14-Sep-2020-489321

functional-tests/H14-Sep-2020-802740

gcpkms/H14-Sep-2020-191153

hcvault/H14-Sep-2020-444381

keys/H14-Sep-2020-1411

keyservice/H14-Sep-2020-1,2901,099

kms/H14-Sep-2020-4,1703,381

logging/H14-Sep-2020-4733

pgp/H14-Sep-2020-592532

publish/H14-Sep-2020-217165

shamir/H14-Sep-2020-1,113794

stores/H14-Sep-2020-2,5022,203

validation/H14-Sep-2020-154137

version/H14-Sep-2020-8770

.dockerignoreH A D14-Sep-202037 43

.gitignoreH A D14-Sep-202051 65

.sops.yamlH A D14-Sep-2020129 54

.travis.ymlH A D14-Sep-20201.7 KiB5648

CHANGELOG.rstH A D14-Sep-20207.3 KiB265177

CODE_OF_CONDUCT.mdH A D14-Sep-2020495 96

CONTRIBUTING.mdH A D14-Sep-20202 KiB3121

DockerfileH A D14-Sep-2020222 118

Dockerfile.alpineH A D14-Sep-2020342 1811

LICENSEH A D14-Sep-202016.3 KiB374293

MakefileH A D14-Sep-20203.4 KiB10378

README.rstH A D14-Sep-202062.3 KiB1,7081,241

example.iniH A D14-Sep-20203.1 KiB3226

example.jsonH A D14-Sep-20203.2 KiB4343

example.yamlH A D14-Sep-20205 KiB7067

go.modH A D14-Sep-20202.2 KiB5249

go.sumH A D14-Sep-202039.2 KiB409408

make_download_page.shH A D14-Sep-2020624 1210

sops.goH A D14-Sep-202023.6 KiB769604

sops_test.goH A D14-Sep-202013.9 KiB731696

test.shH A D14-Sep-2020271 139

usererrors.goH A D14-Sep-20204.3 KiB165142

README.rst

1SOPS: Secrets OPerationS
2========================
3
4**sops** is an editor of encrypted files that supports YAML, JSON, ENV, INI and BINARY
5formats and encrypts with AWS KMS, GCP KMS, Azure Key Vault and PGP.
6(`demo <https://www.youtube.com/watch?v=YTEVyLXFiq0>`_)
7
8.. image:: https://i.imgur.com/X0TM5NI.gif
9
10------------
11
12.. image:: https://godoc.org/go.mozilla.org/sops?status.svg
13	:target: https://godoc.org/go.mozilla.org/sops
14
15.. image:: https://travis-ci.org/mozilla/sops.svg?branch=master
16	:target: https://travis-ci.org/mozilla/sops
17
18Download
19--------
20
21Stable release
22~~~~~~~~~~~~~~
23Binaries and packages of the latest stable release are available at `https://github.com/mozilla/sops/releases <https://github.com/mozilla/sops/releases>`_.
24
25Development branch
26~~~~~~~~~~~~~~~~~~
27For the adventurous, unstable features are available in the `develop` branch, which you can install from source:
28
29.. code:: bash
30
31	$ go get -u go.mozilla.org/sops/v3/cmd/sops
32        $ cd $GOPATH/src/go.mozilla.org/sops/
33        $ git checkout develop
34        $ make install
35
36(requires Go >= 1.13)
37
38If you don't have Go installed, set it up with:
39
40.. code:: bash
41
42	$ {apt,yum,brew} install golang
43	$ echo 'export GOPATH=~/go' >> ~/.bashrc
44	$ source ~/.bashrc
45	$ mkdir $GOPATH
46
47Or whatever variation of the above fits your system and shell.
48
49To use **sops** as a library, take a look at the `decrypt package <https://godoc.org/go.mozilla.org/sops/decrypt>`_.
50
51**What happened to Python Sops?** We rewrote Sops in Go to solve a number of
52deployment issues, but the Python branch still exists under ``python-sops``. We
53will keep maintaining it for a while, and you can still ``pip install sops``,
54but we strongly recommend you use the Go version instead.
55
56.. sectnum::
57.. contents:: Table of Contents
58
59Usage
60-----
61
62For a quick presentation of Sops, check out this Youtube tutorial:
63
64.. image:: https://img.youtube.com/vi/V2PRhxphH2w/0.jpg
65   :target: https://www.youtube.com/watch?v=V2PRhxphH2w
66
67If you're using AWS KMS, create one or multiple master keys in the IAM console
68and export them, comma separated, in the **SOPS_KMS_ARN** env variable. It is
69recommended to use at least two master keys in different regions.
70
71.. code:: bash
72
73	export SOPS_KMS_ARN="arn:aws:kms:us-east-1:656532927350:key/920aff2e-c5f1-4040-943a-047fa387b27e,arn:aws:kms:ap-southeast-1:656532927350:key/9006a8aa-0fa6-4c14-930e-a2dfb916de1d"
74
75Your AWS credentials must be present in ``~/.aws/credentials``. sops uses aws-sdk-go.
76
77.. code::
78
79	$ cat ~/.aws/credentials
80	[default]
81	aws_access_key_id = AKI.....
82	aws_secret_access_key = mw......
83
84If you want to use PGP, export the fingerprints of the public keys, comma
85separated, in the **SOPS_PGP_FP** env variable.
86
87.. code:: bash
88
89	export SOPS_PGP_FP="85D77543B3D624B63CEA9E6DBC17301B491B3F21,E60892BB9BD89A69F759A1A0A3D652173B763E8F"
90
91Note: you can use both PGP and KMS simultaneously.
92
93Then simply call ``sops`` with a file path as argument. It will handle the
94encryption/decryption transparently and open the cleartext file in an editor
95
96.. code:: shell
97
98	$ sops mynewtestfile.yaml
99	mynewtestfile.yaml doesn't exist, creating it.
100	please wait while an encryption key is being generated and stored in a secure fashion
101	file written to mynewtestfile.yaml
102
103Editing will happen in whatever ``$EDITOR`` is set to, or, if it's not set, in vim.
104Keep in mind that sops will wait for the editor to exit, and then try to reencrypt
105the file. Some GUI editors (atom, sublime) spawn a child process and then exit
106immediately. They usually have an option to wait for the main editor window to be
107closed before exiting. See `#127 <https://github.com/mozilla/sops/issues/127>`_ for
108more information.
109
110The resulting encrypted file looks like this:
111
112.. code:: yaml
113
114    myapp1: ENC[AES256_GCM,data:Tr7o=,iv:1=,aad:No=,tag:k=]
115    app2:
116        db:
117            user: ENC[AES256_GCM,data:CwE4O1s=,iv:2k=,aad:o=,tag:w==]
118            password: ENC[AES256_GCM,data:p673w==,iv:YY=,aad:UQ=,tag:A=]
119        # private key for secret operations in app2
120        key: |-
121            ENC[AES256_GCM,data:Ea3kL5O5U8=,iv:DM=,aad:FKA=,tag:EA==]
122    an_array:
123    - ENC[AES256_GCM,data:v8jQ=,iv:HBE=,aad:21c=,tag:gA==]
124    - ENC[AES256_GCM,data:X10=,iv:o8=,aad:CQ=,tag:Hw==]
125    - ENC[AES256_GCM,data:KN=,iv:160=,aad:fI4=,tag:tNw==]
126    sops:
127        kms:
128        -   created_at: 1441570389.775376
129            enc: CiC....Pm1Hm
130            arn: arn:aws:kms:us-east-1:656532927350:key/920aff2e-c5f1-4040-943a-047fa387b27e
131        -   created_at: 1441570391.925734
132            enc: Ci...awNx
133            arn: arn:aws:kms:ap-southeast-1:656532927350:key/9006a8aa-0fa6-4c14-930e-a2dfb916de1d
134        pgp:
135        -   fp: 85D77543B3D624B63CEA9E6DBC17301B491B3F21
136            created_at: 1441570391.930042
137            enc: |
138                -----BEGIN PGP MESSAGE-----
139                hQIMA0t4uZHfl9qgAQ//UvGAwGePyHuf2/zayWcloGaDs0MzI+zw6CmXvMRNPUsA
140				...=oJgS
141                -----END PGP MESSAGE-----
142
143A copy of the encryption/decryption key is stored securely in each KMS and PGP
144block. As long as one of the KMS or PGP method is still usable, you will be able
145to access your data.
146
147To decrypt a file in a ``cat`` fashion, use the ``-d`` flag:
148
149.. code:: bash
150
151	$ sops -d mynewtestfile.yaml
152
153``sops`` encrypted files contain the necessary information to decrypt their content.
154All a user of ``sops`` needs is valid AWS credentials and the necessary
155permissions on KMS keys.
156
157Given that, the only command a ``sops`` user needs is:
158
159.. code:: bash
160
161	$ sops <file>
162
163`<file>` will be opened, decrypted, passed to a text editor (vim by default),
164encrypted if modified, and saved back to its original location. All of these
165steps, apart from the actual editing, are transparent to the user.
166
167Test with the dev PGP key
168~~~~~~~~~~~~~~~~~~~~~~~~~
169
170If you want to test **sops** without having to do a bunch of setup, you can use
171the example files and pgp key provided with the repository::
172
173	$ git clone https://github.com/mozilla/sops.git
174	$ cd sops
175	$ gpg --import pgp/sops_functional_tests_key.asc
176	$ sops example.yaml
177
178This last step will decrypt ``example.yaml`` using the test private key.
179
180
181Encrypting using GCP KMS
182~~~~~~~~~~~~~~~~~~~~~~~~
183GCP KMS uses `Application Default Credentials
184<https://developers.google.com/identity/protocols/application-default-credentials>`_.
185If you already logged in using
186
187.. code:: bash
188
189	$ gcloud auth login
190
191you can enable application default credentials using the sdk::
192
193	$ gcloud auth application-default login
194
195Encrypting/decrypting with GCP KMS requires a KMS ResourceID. You can use the
196cloud console the get the ResourceID or you can create one using the gcloud
197sdk:
198
199.. code:: bash
200
201	$ gcloud kms keyrings create sops --location global
202	$ gcloud kms keys create sops-key --location global --keyring sops --purpose encryption
203	$ gcloud kms keys list --location global --keyring sops
204
205	# you should see
206	NAME                                                                   PURPOSE          PRIMARY_STATE
207	projects/my-project/locations/global/keyRings/sops/cryptoKeys/sops-key ENCRYPT_DECRYPT  ENABLED
208
209Now you can encrypt a file using::
210
211	$ sops --encrypt --gcp-kms projects/my-project/locations/global/keyRings/sops/cryptoKeys/sops-key test.yaml > test.enc.yaml
212
213And decrypt it using::
214
215	 $ sops --decrypt test.enc.yaml
216
217Encrypting using Azure Key Vault
218~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
219
220The Azure Key Vault integration tries several authentication methods, in
221this order:
222
223  1. Client credentials
224  2. Client Certificate
225  3. Username Password
226  4. MSI
227  5. Azure CLI auth
228
229You can force a specific authentication method through the AZURE_AUTH_METHOD
230environment variable, which may be one of: clientcredentials, clientcertificate,
231usernamepassword, msi, or cli (default).
232
233For example, you can use service principals with the following environment variables:
234
235.. code:: bash
236
237	AZURE_TENANT_ID
238	AZURE_CLIENT_ID
239	AZURE_CLIENT_SECRET
240
241You can create a service principal using the cli like this:
242
243.. code:: bash
244
245	$ az ad sp create-for-rbac -n my-keyvault-sp
246
247	{
248		"appId": "<some-uuid>",
249		"displayName": "my-keyvault-sp",
250		"name": "http://my-keyvault-sp",
251		"password": "<some-uuid>",
252		"tenant": "<tenant-id>"
253	}
254
255The appId is the client id, and the password is the client secret.
256
257Encrypting/decrypting with Azure Key Vault requires the resource identifier for
258a key. This has the following form::
259
260	https://${VAULT_URL}/keys/${KEY_NAME}/${KEY_VERSION}
261
262To create a Key Vault and assign your service principal permissions on it
263from the commandline:
264
265.. code:: bash
266
267	# Create a resource group if you do not have one:
268	$ az group create --name sops-rg --location westeurope
269	# Key Vault names are globally unique, so generate one:
270	$ keyvault_name=sops-$(uuidgen | tr -d - | head -c 16)
271	# Create a Vault, a key, and give the service principal access:
272	$ az keyvault create --name $keyvault_name --resource-group sops-rg --location westeurope
273	$ az keyvault key create --name sops-key --vault-name $keyvault_name --protection software --ops encrypt decrypt
274	$ az keyvault set-policy --name $keyvault_name --resource-group sops-rg --spn $AZURE_CLIENT_ID \
275		--key-permissions encrypt decrypt
276	# Read the key id:
277	$ az keyvault key show --name sops-key --vault-name $keyvault_name --query key.kid
278
279	https://sops.vault.azure.net/keys/sops-key/some-string
280
281Now you can encrypt a file using::
282
283	$ sops --encrypt --azure-kv https://sops.vault.azure.net/keys/sops-key/some-string test.yaml > test.enc.yaml
284
285And decrypt it using::
286
287	 $ sops --decrypt test.enc.yaml
288
289
290Encrypting using Hashicorp Vault
291~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
292
293We assume you have an instance (or more) of Vault running and you have privileged access to it. For instructions on how to deploy a secure instance of Vault, refer to Hashicorp's official documentation.
294
295To easily deploy Vault locally: (DO NOT DO THIS FOR PRODUCTION!!!)
296
297.. code:: bash
298
299	$ docker run -d -p8200:8200 vault:1.2.0 server -dev -dev-root-token-id=toor
300
301
302.. code:: bash
303
304	$ # Substitute this with the address Vault is running on
305	$ export VAULT_ADDR=http://127.0.0.1:8200
306
307	$ # this may not be necessary in case you previously used `vault login` for production use
308	$ export VAULT_TOKEN=toor
309
310	$ # to check if Vault started and is configured correctly
311	$ vault status
312	Key             Value
313	---             -----
314	Seal Type       shamir
315	Initialized     true
316	Sealed          false
317	Total Shares    1
318	Threshold       1
319	Version         1.2.0
320	Cluster Name    vault-cluster-618cc902
321	Cluster ID      e532e461-e8f0-1352-8a41-fc7c11096908
322	HA Enabled      false
323
324	$ # It is required to enable a transit engine if not already done (It is suggested to create a transit engine specifically for sops, in which it is possible to have multiple keys with various permission levels)
325	$ vault secrets enable -path=sops transit
326	Success! Enabled the transit secrets engine at: sops/
327
328	$ # Then create one or more keys
329	$ vault write sops/keys/firstkey type=rsa-4096
330	Success! Data written to: sops/keys/firstkey
331
332	$ vault write sops/keys/secondkey type=rsa-2048
333	Success! Data written to: sops/keys/secondkey
334
335	$ vault write sops/keys/thirdkey type=chacha20-poly1305
336	Success! Data written to: sops/keys/thirdkey
337
338	$ sops --hc-vault-transit $VAULT_ADDR/v1/sops/keys/firstkey vault_example.yml
339
340	$ cat <<EOF > .sops.yaml
341	creation_rules:
342		- path_regex: \.dev\.yaml$
343		  hc_vault_transit_uri: "$VAULT_ADDR/v1/sops/keys/secondkey"
344		- path_regex: \.prod\.yaml$
345		  hc_vault_transit_uri: "$VAULT_ADDR/v1/sops/keys/thirdkey"
346	EOF
347
348	$ sops --verbose -e prod/raw.yaml > prod/encrypted.yaml
349
350Adding and removing keys
351~~~~~~~~~~~~~~~~~~~~~~~~
352
353When creating new files, ``sops`` uses the PGP, KMS and GCP KMS defined in the
354command line arguments ``--kms``, ``--pgp``, ``--gcp-kms`` or ``--azure-kv``, or from
355the environment variables ``SOPS_KMS_ARN``, ``SOPS_PGP_FP``, ``SOPS_GCP_KMS_IDS``,
356``SOPS_AZURE_KEYVAULT_URLS``. That information is stored in the file under the
357``sops`` section, such that decrypting files does not require providing those
358parameters again.
359
360Master PGP and KMS keys can be added and removed from a ``sops`` file in one of
361three ways::
362
3631. By using a .sops.yaml file and the ``updatekeys`` command.
364
3652. By using command line flags.
366
3673. By editing the file directly.
368
369The sops team recommends the ``updatekeys`` approach.
370
371
372``updatekeys`` command
373**********************
374
375The ``updatekeys`` command uses the `.sops.yaml <#29using-sopsyaml-conf-to-select-kmspgp-for-new-files>`_
376configuration file to update (add or remove) the corresponding secrets in the
377encrypted file. Note that the example below uses the
378`Block Scalar yaml construct <https://yaml-multiline.info/>`_ to build a space
379separated list.
380
381.. code:: yaml
382
383    creation_rules:
384        - pgp: >-
385            85D77543B3D624B63CEA9E6DBC17301B491B3F21,
386            FBC7B9E2A4F9289AC0C1D4843D16CEE4A27381B4
387
388.. code:: bash
389
390	$ sops updatekeys test.enc.yaml
391
392Sops will prompt you with the changes to be made. This interactivity can be
393disabled by supplying the ``-y`` flag.
394
395Command Line
396************
397
398Command line flag ``--add-kms``, ``--add-pgp``, ``--add-gcp-kms``, ``--add-azure-kv``,
399``--rm-kms``, ``--rm-pgp``, ``--rm-gcp-kms`` and ``--rm-azure-kv`` can be used to add
400and remove keys from a file.
401These flags use the comma separated syntax as the ``--kms``, ``--pgp``, ``--gcp-kms``
402and ``--azure-kv`` arguments when creating new files.
403
404Note that ``-r`` or ``--rotate`` is mandatory in this mode. Not specifying
405rotate will ignore the ``--add-*`` options. Use ``updatekeys`` if you want to
406add a key without rotating the data key.
407
408.. code:: bash
409
410	# add a new pgp key to the file and rotate the data key
411	$ sops -r -i --add-pgp 85D77543B3D624B63CEA9E6DBC17301B491B3F21 example.yaml
412
413	# remove a pgp key from the file and rotate the data key
414	$ sops -r -i --rm-pgp 85D77543B3D624B63CEA9E6DBC17301B491B3F21 example.yaml
415
416
417Direct Editing
418**************
419
420Alternatively, invoking ``sops`` with the flag **-s** will display the master keys
421while editing. This method can be used to add or remove kms or pgp keys under the
422sops section. Invoking ``sops`` with the **-i** flag will perform an in-place edit
423instead of redirecting output to ``stdout``.
424
425For example, to add a KMS master key to a file, add the following entry while
426editing:
427
428.. code:: yaml
429
430	sops:
431	    kms:
432	    - arn: arn:aws:kms:us-east-1:656532927350:key/920aff2e-c5f1-4040-943a-047fa387b27e
433
434And, similarly, to add a PGP master key, we add its fingerprint:
435
436.. code:: yaml
437
438	sops:
439	    pgp:
440	    - fp: 85D77543B3D624B63CEA9E6DBC17301B491B3F21
441
442When the file is saved, ``sops`` will update its metadata and encrypt the data key
443with the freshly added master keys. The removed entries are simply deleted from
444the file.
445
446When removing keys, it is recommended to rotate the data key using ``-r``,
447otherwise owners of the removed key may have add access to the data key in the
448past.
449
450KMS AWS Profiles
451~~~~~~~~~~~~~~~~
452
453If you want to use a specific profile, you can do so with `aws_profile`:
454
455.. code:: yaml
456
457	sops:
458	    kms:
459	    -	arn: arn:aws:kms:us-east-1:656532927350:key/920aff2e-c5f1-4040-943a-047fa387b27e
460	        aws_profile: foo
461
462If no AWS profile is set, default credentials will be used.
463
464Similarly the `--aws-profile` flag can be set with the command line with any of the KMS commands.
465
466
467Assuming roles and using KMS in various AWS accounts
468~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
469
470SOPS has the ability to use KMS in multiple AWS accounts by assuming roles in
471each account. Being able to assume roles is a nice feature of AWS that allows
472administrators to establish trust relationships between accounts, typically from
473the most secure account to the least secure one. In our use-case, we use roles
474to indicate that a user of the Master AWS account is allowed to make use of KMS
475master keys in development and staging AWS accounts. Using roles, a single file
476can be encrypted with KMS keys in multiple accounts, thus increasing reliability
477and ease of use.
478
479You can use keys in various accounts by tying each KMS master key to a role that
480the user is allowed to assume in each account. The `IAM roles
481<http://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use.html>`_
482documentation has full details on how this needs to be configured on AWS's side.
483
484From the point of view of ``sops``, you only need to specify the role a KMS key
485must assume alongside its ARN, as follows:
486
487.. code:: yaml
488
489	sops:
490	    kms:
491	    -	arn: arn:aws:kms:us-east-1:656532927350:key/920aff2e-c5f1-4040-943a-047fa387b27e
492	        role: arn:aws:iam::927034868273:role/sops-dev-xyz
493
494The role must have permission to call Encrypt and Decrypt using KMS. An example
495policy is shown below.
496
497.. code:: json
498
499	{
500	  "Sid": "Allow use of the key",
501	  "Effect": "Allow",
502	  "Action": [
503		"kms:Encrypt",
504		"kms:Decrypt",
505		"kms:ReEncrypt*",
506		"kms:GenerateDataKey*",
507		"kms:DescribeKey"
508	  ],
509	  "Resource": "*",
510	  "Principal": {
511		"AWS": [
512		  "arn:aws:iam::927034868273:role/sops-dev-xyz"
513		]
514	  }
515	}
516
517You can specify a role in the ``--kms`` flag and ``SOPS_KMS_ARN`` variable by
518appending it to the ARN of the master key, separated by a **+** sign::
519
520	<KMS ARN>+<ROLE ARN>
521	arn:aws:kms:us-west-2:927034868273:key/fe86dd69-4132-404c-ab86-4269956b4500+arn:aws:iam::927034868273:role/sops-dev-xyz
522
523AWS KMS Encryption Context
524~~~~~~~~~~~~~~~~~~~~~~~~~~
525
526SOPS has the ability to use `AWS KMS key policy and encryption context
527<http://docs.aws.amazon.com/kms/latest/developerguide/encryption-context.html>`_
528to refine the access control of a given KMS master key.
529
530When creating a new file, you can specify encryption context in the
531``--encryption-context`` flag by comma separated list of key-value pairs:
532
533.. code:: bash
534
535	$ sops --encryption-context Environment:production,Role:web-server test.dev.yaml
536
537The format of the Encrypt Context string is ``<EncryptionContext Key>:<EncryptionContext Value>,<EncryptionContext Key>:<EncryptionContext Value>,...``
538
539The encryption context will be stored in the file metadata and does
540not need to be provided at decryption.
541
542Encryption contexts can be used in conjunction with KMS Key Policies to define
543roles that can only access a given context. An example policy is shown below:
544
545.. code:: json
546
547    {
548      "Effect": "Allow",
549      "Principal": {
550        "AWS": "arn:aws:iam::111122223333:role/RoleForExampleApp"
551      },
552      "Action": "kms:Decrypt",
553      "Resource": "*",
554      "Condition": {
555        "StringEquals": {
556          "kms:EncryptionContext:AppName": "ExampleApp",
557          "kms:EncryptionContext:FilePath": "/var/opt/secrets/"
558        }
559      }
560    }
561
562Key Rotation
563~~~~~~~~~~~~
564
565It is recommended to renew the data key on a regular basis. ``sops`` supports key
566rotation via the ``-r`` flag. Invoking it on an existing file causes sops to
567reencrypt the file with a new data key, which is then encrypted with the various
568KMS and PGP master keys defined in the file.
569
570.. code:: bash
571
572	sops -r example.yaml
573
574Using .sops.yaml conf to select KMS/PGP for new files
575~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
576
577It is often tedious to specify the ``--kms`` ``--gcp-kms`` and ``--pgp`` parameters for creation
578of all new files. If your secrets are stored under a specific directory, like a
579``git`` repository, you can create a ``.sops.yaml`` configuration file at the root
580directory to define which keys are used for which filename.
581
582Let's take an example:
583
584* file named **something.dev.yaml** should use one set of KMS A
585* file named **something.prod.yaml** should use another set of KMS B
586* other files use a third set of KMS C
587* all live under **mysecretrepo/something.{dev,prod,gcp}.yaml**
588
589Under those circumstances, a file placed at **mysecretrepo/.sops.yaml**
590can manage the three sets of configurations for the three types of files:
591
592.. code:: yaml
593
594	# creation rules are evaluated sequentially, the first match wins
595	creation_rules:
596		# upon creation of a file that matches the pattern *.dev.yaml,
597		# KMS set A is used
598		- path_regex: \.dev\.yaml$
599		  kms: 'arn:aws:kms:us-west-2:927034868273:key/fe86dd69-4132-404c-ab86-4269956b4500,arn:aws:kms:us-west-2:361527076523:key/5052f06a-5d3f-489e-b86c-57201e06f31e+arn:aws:iam::361527076523:role/hiera-sops-prod'
600		  pgp: 'FBC7B9E2A4F9289AC0C1D4843D16CEE4A27381B4'
601
602		# prod files use KMS set B in the PROD IAM
603		- path_regex: \.prod\.yaml$
604		  kms: 'arn:aws:kms:us-west-2:361527076523:key/5052f06a-5d3f-489e-b86c-57201e06f31e+arn:aws:iam::361527076523:role/hiera-sops-prod,arn:aws:kms:eu-central-1:361527076523:key/cb1fab90-8d17-42a1-a9d8-334968904f94+arn:aws:iam::361527076523:role/hiera-sops-prod'
605		  pgp: 'FBC7B9E2A4F9289AC0C1D4843D16CEE4A27381B4'
606		  hc_vault_uris: "http://localhost:8200/v1/sops/keys/thirdkey"
607
608		# gcp files using GCP KMS
609		- path_regex: \.gcp\.yaml$
610		  gcp_kms: projects/mygcproject/locations/global/keyRings/mykeyring/cryptoKeys/thekey
611
612		# Finally, if the rules above have not matched, this one is a
613		# catchall that will encrypt the file using KMS set C
614		# The absence of a path_regex means it will match everything
615		- kms: 'arn:aws:kms:us-west-2:927034868273:key/fe86dd69-4132-404c-ab86-4269956b4500,arn:aws:kms:us-west-2:142069644989:key/846cfb17-373d-49b9-8baf-f36b04512e47,arn:aws:kms:us-west-2:361527076523:key/5052f06a-5d3f-489e-b86c-57201e06f31e'
616		  pgp: 'FBC7B9E2A4F9289AC0C1D4843D16CEE4A27381B4'
617
618When creating any file under **mysecretrepo**, whether at the root or under
619a subdirectory, sops will recursively look for a ``.sops.yaml`` file. If one is
620found, the filename of the file being created is compared with the filename
621regexes of the configuration file. The first regex that matches is selected,
622and its KMS and PGP keys are used to encrypt the file. It should be noted that
623the looking up of ``.sops.yaml`` is from the working directory (CWD) instead of
624the directory of the encrypting file (see `Issue 242 <https://github.com/mozilla/sops/issues/242>`_).
625
626The path_regex checks the full path of the encrypting file. Here is another example:
627
628* files located under directory **development** should use one set of KMS A
629* files located under directory **production** should use another set of KMS B
630* other files use a third set of KMS C
631
632.. code:: yaml
633
634    creation_rules:
635        # upon creation of a file under development,
636        # KMS set A is used
637        - path_regex: .*/development/.*
638          kms: 'arn:aws:kms:us-west-2:927034868273:key/fe86dd69-4132-404c-ab86-4269956b4500,arn:aws:kms:us-west-2:361527076523:key/5052f06a-5d3f-489e-b86c-57201e06f31e+arn:aws:iam::361527076523:role/hiera-sops-prod'
639          pgp: 'FBC7B9E2A4F9289AC0C1D4843D16CEE4A27381B4'
640
641        # prod files use KMS set B in the PROD IAM
642        - path_regex: .*/production/.*
643          kms: 'arn:aws:kms:us-west-2:361527076523:key/5052f06a-5d3f-489e-b86c-57201e06f31e+arn:aws:iam::361527076523:role/hiera-sops-prod,arn:aws:kms:eu-central-1:361527076523:key/cb1fab90-8d17-42a1-a9d8-334968904f94+arn:aws:iam::361527076523:role/hiera-sops-prod'
644          pgp: 'FBC7B9E2A4F9289AC0C1D4843D16CEE4A27381B4'
645
646        # other files use KMS set C
647        - kms: 'arn:aws:kms:us-west-2:927034868273:key/fe86dd69-4132-404c-ab86-4269956b4500,arn:aws:kms:us-west-2:142069644989:key/846cfb17-373d-49b9-8baf-f36b04512e47,arn:aws:kms:us-west-2:361527076523:key/5052f06a-5d3f-489e-b86c-57201e06f31e'
648          pgp: 'FBC7B9E2A4F9289AC0C1D4843D16CEE4A27381B4'
649
650Creating a new file with the right keys is now as simple as
651
652.. code:: bash
653
654	$ sops <newfile>.prod.yaml
655
656Note that the configuration file is ignored when KMS or PGP parameters are
657passed on the sops command line or in environment variables.
658
659Specify a different GPG executable
660~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
661
662``sops`` checks for the ``SOPS_GPG_EXEC`` environment variable. If specified,
663it will attempt to use the executable set there instead of the default
664of ``gpg``.
665
666Example: place the following in your ``~/.bashrc``
667
668.. code:: bash
669
670	SOPS_GPG_EXEC = 'your_gpg_client_wrapper'
671
672
673Specify a different GPG key server
674~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
675
676By default, ``sops`` uses the key server ``keys.openpgp.org`` to retrieve the GPG
677keys that are not present in the local keyring.
678This is no longer configurable. You can learn more about why from this write-up: [SKS Keyserver Network Under Attack](https://gist.github.com/rjhansen/67ab921ffb4084c865b3618d6955275f).
679
680Example: place the following in your ``~/.bashrc``
681
682.. code:: bash
683
684	SOPS_GPG_KEYSERVER = 'gpg.example.com'
685
686
687Key groups
688~~~~~~~~~~
689
690By default, ``sops`` encrypts the data key for a file with each of the master keys,
691such that if any of the master keys is available, the file can be decrypted.
692However, it is sometimes desirable to require access to multiple master keys
693in order to decrypt files. This can be achieved with key groups.
694
695When using key groups in sops, data keys are split into parts such that keys from
696multiple groups are required to decrypt a file. ``sops`` uses Shamir's Secret Sharing
697to split the data key such that each key group has a fragment, each key in the
698key group can decrypt that fragment, and a configurable number of fragments (threshold)
699are needed to decrypt and piece together the complete data key. When decrypting a
700file using multiple key groups, ``sops`` goes through key groups in order, and in
701each group, tries to recover the fragment of the data key using a master key from
702that group. Once the fragment is recovered, ``sops`` moves on to the next group,
703until enough fragments have been recovered to obtain the complete data key.
704
705By default, the threshold is set to the number of key groups. For example, if
706you have three key groups configured in your SOPS file and you don't override
707the default threshold, then one master key from each of the three groups will
708be required to decrypt the file.
709
710Management of key groups is done with the ``sops groups`` command.
711
712For example, you can add a new key group with 3 PGP keys and 3 KMS keys to the
713file ``my_file.yaml``:
714
715.. code:: bash
716
717    $ sops groups add --file my_file.yaml --pgp fingerprint1 --pgp fingerprint2 --pgp fingerprint3 --kms arn1 --kms arn2 --kms arn3
718
719Or you can delete the 1st group (group number 0, as groups are zero-indexed)
720from ``my_file.yaml``:
721
722.. code:: bash
723
724    $ sops groups delete --file my_file.yaml 0
725
726Key groups can also be specified in the ``.sops.yaml`` config file,
727like so:
728
729.. code:: yaml
730
731    creation_rules:
732        - path_regex: .*keygroups.*
733          key_groups:
734          # First key group
735          - pgp:
736            - fingerprint1
737            - fingerprint2
738            kms:
739            - arn: arn1
740              role: role1
741              context:
742                foo: bar
743            - arn: arn2
744          # Second key group
745          - pgp:
746            - fingerprint3
747            - fingerprint4
748            kms:
749            - arn: arn3
750            - arn: arn4
751          # Third key group
752          - pgp:
753            - fingerprint5
754
755Given this configuration, we can create a new encrypted file like we normally
756would, and optionally provide the ``--shamir-secret-sharing-threshold`` command line
757flag if we want to override the default threshold. ``sops`` will then split the data
758key into three parts (from the number of key groups) and encrypt each fragment with
759the master keys found in each group.
760
761For example:
762
763.. code:: bash
764
765    $ sops --shamir-secret-sharing-threshold 2 example.json
766
767Alternatively, you can configure the Shamir threshold for each creation rule in the ``.sops.yaml`` config
768with ``shamir_threshold``:
769
770.. code:: yaml
771
772    creation_rules:
773        - path_regex: .*keygroups.*
774          shamir_threshold: 2
775          key_groups:
776          # First key group
777          - pgp:
778            - fingerprint1
779            - fingerprint2
780            kms:
781            - arn: arn1
782              role: role1
783              context:
784                foo: bar
785            - arn: arn2
786          # Second key group
787          - pgp:
788            - fingerprint3
789            - fingerprint4
790            kms:
791            - arn: arn3
792            - arn: arn4
793          # Third key group
794          - pgp:
795            - fingerprint5
796
797And then run ``sops example.json``.
798
799The threshold (``shamir_threshold``) is set to 2, so this configuration will require
800master keys from two of the three different key groups in order to decrypt the file.
801You can then decrypt the file the same way as with any other SOPS file:
802
803.. code:: bash
804
805    $ sops -d example.json
806
807Key service
808~~~~~~~~~~~
809
810There are situations where you might want to run ``sops`` on a machine that
811doesn't have direct access to encryption keys such as PGP keys. The ``sops`` key
812service allows you to forward a socket so that ``sops`` can access encryption
813keys stored on a remote machine. This is similar to GPG Agent, but more
814portable.
815
816SOPS uses a client-server approach to encrypting and decrypting the data
817key. By default, SOPS runs a local key service in-process. SOPS uses a key
818service client to send an encrypt or decrypt request to a key service, which
819then performs the operation. The requests are sent using gRPC and Protocol
820Buffers. The requests contain an identifier for the key they should perform
821the operation with, and the plaintext or encrypted data key. The requests do
822not contain any cryptographic keys, public or private.
823
824**WARNING: the key service connection currently does not use any sort of
825authentication or encryption. Therefore, it is recommended that you make sure
826the connection is authenticated and encrypted in some other way, for example
827through an SSH tunnel.**
828
829Whenever we try to encrypt or decrypt a data key, SOPS will try to do so first
830with the local key service (unless it's disabled), and if that fails, it will
831try all other remote key services until one succeeds.
832
833You can start a key service server by running ``sops keyservice``.
834
835You can specify the key services the ``sops`` binary uses with ``--keyservice``.
836This flag can be specified more than once, so you can use multiple key
837services. The local key service can be disabled with
838``enable-local-keyservice=false``.
839
840For example, to decrypt a file using both the local key service and the key
841service exposed on the unix socket located in ``/tmp/sops.sock``, you can run:
842
843.. code:: bash
844
845    $ sops --keyservice unix:///tmp/sops.sock -d file.yaml`
846
847And if you only want to use the key service exposed on the unix socket located
848in ``/tmp/sops.sock`` and not the local key service, you can run:
849
850.. code:: bash
851
852    $ sops --enable-local-keyservice=false --keyservice unix:///tmp/sops.sock -d file.yaml
853
854Auditing
855~~~~~~~~
856
857Sometimes, users want to be able to tell what files were accessed by whom in an
858environment they control. For this reason, SOPS can generate audit logs to
859record activity on encrypted files. When enabled, SOPS will write a log entry
860into a pre-configured PostgreSQL database when a file is decrypted. The log
861includes a timestamp, the username SOPS is running as, and the file that was
862decrypted.
863
864In order to enable auditing, you must first create the database and credentials
865using the schema found in ``audit/schema.sql``. This schema defines the
866tables that store the audit events and a role named ``sops`` that only has
867permission to add entries to the audit event tables. The default password for
868the role ``sops`` is ``sops``. You should change this password.
869
870Once you have created the database, you have to tell SOPS how to connect to it.
871Because we don't want users of SOPS to be able to control auditing, the audit
872configuration file location is not configurable, and must be at
873``/etc/sops/audit.yaml``. This file should have strict permissions such
874that only the root user can modify it.
875
876For example, to enable auditing to a PostgreSQL database named ``sops`` running
877on localhost, using the user ``sops`` and the password ``sops``,
878``/etc/sops/audit.yaml`` should have the following contents:
879
880.. code:: yaml
881
882    backends:
883        postgres:
884            - connection_string: "postgres://sops:sops@localhost/sops?sslmode=verify-full"
885
886
887You can find more information on the ``connection_string`` format in the
888`PostgreSQL docs <https://www.postgresql.org/docs/current/static/libpq-connect.html#libpq-connstring>`_.
889
890Under the ``postgres`` map entry in the above YAML is a list, so one can
891provide more than one backend, and SOPS will log to all of them:
892
893.. code:: yaml
894
895    backends:
896        postgres:
897            - connection_string: "postgres://sops:sops@localhost/sops?sslmode=verify-full"
898            - connection_string: "postgres://sops:sops@remotehost/sops?sslmode=verify-full"
899
900Saving Output to a File
901~~~~~~~~~~~~~~~~~~~~~~~
902By default ``sops`` just dumps all the output to the standard output. We can use the
903``--output`` flag followed by a filename to save the output to the file specified.
904Beware using both ``--in-place`` and ``--output`` flags will result in an error.
905
906Passing Secrets to Other Processes
907~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
908In addition to writing secrets to standard output and to files on disk, ``sops``
909has two commands for passing decrypted secrets to a new process: ``exec-env``
910and ``exec-file``. These commands will place all output into the environment of
911a child process and into a temporary file, respectively. For example, if a
912program looks for credentials in its environment, ``exec-env`` can be used to
913ensure that the decrypted contents are available only to this process and never
914written to disk.
915
916.. code:: bash
917
918   # print secrets to stdout to confirm values
919   $ sops -d out.json
920   {
921           "database_password": "jf48t9wfw094gf4nhdf023r",
922           "AWS_ACCESS_KEY_ID": "AKIAIOSFODNN7EXAMPLE",
923           "AWS_SECRET_KEY": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
924   }
925
926   # decrypt out.json and run a command
927   # the command prints the environment variable and runs a script that uses it
928   $ sops exec-env out.json 'echo secret: $database_password; ./database-import'
929   secret: jf48t9wfw094gf4nhdf023r
930
931   # launch a shell with the secrets available in its environment
932   $ sops exec-env out.json 'sh'
933   sh-3.2# echo $database_password
934   jf48t9wfw094gf4nhdf023r
935
936   # the secret is not accessible anywhere else
937   sh-3.2$ exit
938   $ echo your password: $database_password
939   your password:
940
941
942If the command you want to run only operates on files, you can use ``exec-file``
943instead. By default ``sops`` will use a FIFO to pass the contents of the
944decrypted file to the new program. Using a FIFO, secrets are only passed in
945memory which has two benefits: the plaintext secrets never touch the disk, and
946the child process can only read the secrets once. In contexts where this won't
947work, eg platforms like Windows where FIFOs unavailable or secret files that need
948to be available to the child process longer term, the ``--no-fifo`` flag can be
949used to instruct ``sops`` to use a traditional temporary file that will get cleaned
950up once the process is finished executing. ``exec-file`` behaves similar to
951``find(1)`` in that ``{}`` is used as a placeholder in the command which will be
952substituted with the temporary file path (whether a FIFO or an actual file).
953
954.. code:: bash
955
956   # operating on the same file as before, but as a file this time
957   $ sops exec-file out.json 'echo your temporary file: {}; cat {}'
958   your temporary file: /tmp/.sops894650499/tmp-file
959   {
960           "database_password": "jf48t9wfw094gf4nhdf023r",
961           "AWS_ACCESS_KEY_ID": "AKIAIOSFODNN7EXAMPLE",
962           "AWS_SECRET_KEY": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
963   }
964
965   # launch a shell with a variable TMPFILE pointing to the temporary file
966   $ sops exec-file --no-fifo out.json 'TMPFILE={} sh'
967   sh-3.2$ echo $TMPFILE
968   /tmp/.sops506055069/tmp-file291138648
969   sh-3.2$ cat $TMPFILE
970   {
971           "database_password": "jf48t9wfw094gf4nhdf023r",
972           "AWS_ACCESS_KEY_ID": "AKIAIOSFODNN7EXAMPLE",
973           "AWS_SECRET_KEY": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
974   }
975   sh-3.2$ ./program --config $TMPFILE
976   sh-3.2$ exit
977
978   # try to open the temporary file from earlier
979   $ cat /tmp/.sops506055069/tmp-file291138648
980   cat: /tmp/.sops506055069/tmp-file291138648: No such file or directory
981
982Additionally, on unix-like platforms, both ``exec-env`` and ``exec-file``
983support dropping privileges before executing the new program via the
984``--user <username>`` flag. This is particularly useful in cases where the
985encrypted file is only readable by root, but the target program does not
986need root privileges to function. This flag should be used where possible
987for added security.
988
989.. code:: bash
990
991   # the encrypted file can't be read by the current user
992   $ cat out.json
993   cat: out.json: Permission denied
994
995   # execute sops as root, decrypt secrets, then drop privileges
996   $ sudo sops exec-env --user nobody out.json 'sh'
997   sh-3.2$ echo $database_password
998   jf48t9wfw094gf4nhdf023r
999
1000   # dropped privileges, still can't load the original file
1001   sh-3.2$ id
1002   uid=4294967294(nobody) gid=4294967294(nobody) groups=4294967294(nobody)
1003   sh-3.2$ cat out.json
1004   cat: out.json: Permission denied
1005
1006Using the publish command
1007~~~~~~~~~~~~~~~~~~~~~~~~~
1008``sops publish $file`` publishes a file to a pre-configured destination (this lives in the sops
1009config file). Additionally, support re-encryption rules that work just like the creation rules.
1010
1011This command requires a ``.sops.yaml`` configuration file. Below is an example:
1012
1013.. code:: yaml
1014
1015   destination_rules:
1016      - s3_bucket: "sops-secrets"
1017        path_regex: s3/*
1018        recreation_rule:
1019           pgp: F69E4901EDBAD2D1753F8C67A64535C4163FB307
1020      - gcs_bucket: "sops-secrets"
1021        path_regex: gcs/*
1022        recreation_rule:
1023           pgp: F69E4901EDBAD2D1753F8C67A64535C4163FB307
1024      - vault_path: "sops/"
1025        vault_kv_mount_name: "secret/" # default
1026        vault_kv_version: 2 # default
1027        path_regex: vault/*
1028        omit_extensions: true
1029
1030The above configuration will place all files under ``s3/*`` into the S3 bucket ``sops-secrets``,
1031all files under ``gcs/*`` into the GCS bucket ``sops-secrets``, and the contents of all files under
1032``vault/*`` into Vault's KV store under the path ``secrets/sops/``. For the files that will be
1033published to S3 and GCS, it will decrypt them and re-encrypt them using the
1034``F69E4901EDBAD2D1753F8C67A64535C4163FB307`` pgp key.
1035
1036You would deploy a file to S3 with a command like: ``sops publish s3/app.yaml``
1037
1038To publish all files in selected directory recursively, you need to specify ``--recursive`` flag.
1039
1040If you don't want file extension to appear in destination secret path, use ``--omit-extensions``
1041flag or ``omit_extensions: true`` in the destination rule in ``.sops.yaml``.
1042
1043Publishing to Vault
1044*******************
1045
1046There are a few settings for Vault that you can place in your destination rules. The first
1047is ``vault_path``, which is required. The others are optional, and they are
1048``vault_address``, ``vault_kv_mount_name``, ``vault_kv_version``.
1049
1050``sops`` uses the official Vault API provided by Hashicorp, which makes use of `environment
1051variables <https://www.vaultproject.io/docs/commands/#environment-variables>`_ for
1052configuring the client.
1053
1054``vault_kv_mount_name`` is used if your Vault KV is mounted somewhere other than ``secret/``.
1055``vault_kv_version`` supports ``1`` and ``2``, with ``2`` being the default.
1056
1057If destination secret path already exists in Vault and contains same data as the source file, it
1058will be skipped.
1059
1060Below is an example of publishing to Vault (using token auth with a local dev instance of Vault).
1061
1062.. code:: bash
1063
1064   $ export VAULT_TOKEN=...
1065   $ export VAULT_ADDR='http://127.0.0.1:8200'
1066   $ sops -d vault/test.yaml
1067   example_string: bar
1068   example_number: 42
1069   example_map:
1070       key: value
1071   $ sops publish vault/test.yaml
1072   uploading /home/user/sops_directory/vault/test.yaml to http://127.0.0.1:8200/v1/secret/data/sops/test.yaml ? (y/n): y
1073   $ vault kv get secret/sops/test.yaml
1074   ====== Metadata ======
1075   Key              Value
1076   ---              -----
1077   created_time     2019-07-11T03:32:17.074792017Z
1078   deletion_time    n/a
1079   destroyed        false
1080   version          3
1081
1082   ========= Data =========
1083   Key               Value
1084   ---               -----
1085   example_map       map[key:value]
1086   example_number    42
1087   example_string    bar
1088
1089
1090Important information on types
1091------------------------------
1092
1093YAML and JSON type extensions
1094~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1095
1096``sops`` uses the file extension to decide which encryption method to use on the file
1097content. ``YAML``, ``JSON``, ``ENV``, and ``INI`` files are treated as trees of data, and key/values are
1098extracted from the files to only encrypt the leaf values. The tree structure is also
1099used to check the integrity of the file.
1100
1101Therefore, if a file is encrypted using a specific format, it need to be decrypted
1102in the same format. The easiest way to achieve this is to conserve the original file
1103extension after encrypting a file. For example:
1104
1105.. code:: bash
1106
1107	$ sops -e -i myfile.json
1108	$ sops -d myfile.json
1109
1110If you want to change the extension of the file once encrypted, you need to provide
1111sops with the ``--input-type`` flag upon decryption. For example:
1112
1113.. code:: bash
1114
1115	$ sops -e myfile.json > myfile.json.enc
1116
1117	$ sops -d --input-type json myfile.json.enc
1118
1119When operating on stdin, use the ``--input-type`` and ``--output-type`` flags as follows:
1120
1121.. code:: bash
1122
1123    $ cat myfile.json | sops --input-type json --output-type json -d /dev/stdin
1124
1125YAML anchors
1126~~~~~~~~~~~~
1127``sops`` only supports a subset of ``YAML``'s many types. Encrypting YAML files that
1128contain strings, numbers and booleans will work fine, but files that contain anchors
1129will not work, because the anchors redefine the structure of the file at load time.
1130
1131This file will not work in ``sops``:
1132
1133.. code:: yaml
1134
1135	bill-to:  &id001
1136	    street: |
1137	        123 Tornado Alley
1138	        Suite 16
1139	    city:   East Centerville
1140	    state:  KS
1141
1142	ship-to:  *id001
1143
1144``sops`` uses the path to a value as additional data in the AEAD encryption, and thus
1145dynamic paths generated by anchors break the authentication step.
1146
1147JSON and TEXT file types do not support anchors and thus have no such limitation.
1148
1149YAML Streams
1150~~~~~~~~~~~~
1151
1152``YAML`` supports having more than one "document" in a single file, while
1153formats like ``JSON`` do not. ``sops`` is able to handle both. This means the
1154following multi-document will be encrypted as expected:
1155
1156.. code:: yaml
1157
1158	---
1159	data: foo
1160	---
1161	data: bar
1162
1163Note that the ``sops`` metadata, i.e. the hash, etc, is computed for the physical
1164file rather than each internal "document".
1165
1166Top-level arrays
1167~~~~~~~~~~~~~~~~
1168``YAML`` and ``JSON`` top-level arrays are not supported, because ``sops``
1169needs a top-level ``sops`` key to store its metadata.
1170
1171This file will not work in sops:
1172
1173.. code:: yaml
1174
1175	---
1176	  - some
1177	  - array
1178	  - elements
1179
1180But this one will because because the ``sops`` key can be added at the same level as the
1181``data`` key.
1182
1183.. code:: yaml
1184
1185	data:
1186	  - some
1187	  - array
1188	  - elements
1189
1190Similarly, with ``JSON`` arrays, this document will not work:
1191
1192.. code:: json
1193
1194	[
1195	  "some",
1196	  "array",
1197	  "elements"
1198	]
1199
1200
1201But this one will work just fine:
1202
1203.. code:: json
1204
1205	{
1206	  "data": [
1207	    "some",
1208	    "array",
1209	    "elements"
1210	  ]
1211	}
1212
1213
1214Examples
1215--------
1216
1217Take a look into the `examples <https://github.com/mozilla/sops/tree/master/examples>`_ folder for detailed use cases of sops in a CI environment. The section below describes specific tips for common use cases.
1218
1219Creating a new file
1220~~~~~~~~~~~~~~~~~~~
1221
1222The command below creates a new file with a data key encrypted by KMS and PGP.
1223
1224.. code:: bash
1225
1226	$ sops --kms "arn:aws:kms:us-west-2:927034868273:key/fe86dd69-4132-404c-ab86-4269956b4500" --pgp C9CAB0AF1165060DB58D6D6B2653B624D620786D /path/to/new/file.yaml
1227
1228Encrypting an existing file
1229~~~~~~~~~~~~~~~~~~~~~~~~~~~
1230
1231Similar to the previous command, we tell sops to use one KMS and one PGP key.
1232The path points to an existing cleartext file, so we give sops flag ``-e`` to
1233encrypt the file, and redirect the output to a destination file.
1234
1235.. code:: bash
1236
1237	$ export SOPS_KMS_ARN="arn:aws:kms:us-west-2:927034868273:key/fe86dd69-4132-404c-ab86-4269956b4500"
1238	$ export SOPS_PGP_FP="C9CAB0AF1165060DB58D6D6B2653B624D620786D"
1239	$ sops -e /path/to/existing/file.yaml > /path/to/new/encrypted/file.yaml
1240
1241Decrypt the file with ``-d``.
1242
1243.. code:: bash
1244
1245	$ sops -d /path/to/new/encrypted/file.yaml
1246
1247Encrypt or decrypt a file in place
1248~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1249
1250Rather than redirecting the output of ``-e`` or ``-d``, sops can replace the
1251original file after encrypting or decrypting it.
1252
1253.. code:: bash
1254
1255	# file.yaml is in cleartext
1256	$ sops -e -i /path/to/existing/file.yaml
1257	# file.yaml is now encrypted
1258	$ sops -d -i /path/to/existing/file.yaml
1259	# file.yaml is back in cleartext
1260
1261Encrypting binary files
1262~~~~~~~~~~~~~~~~~~~~~~~
1263
1264``sops`` primary use case is encrypting YAML and JSON configuration files, but it
1265also has the ability to manage binary files. When encrypting a binary, sops will
1266read the data as bytes, encrypt it, store the encrypted base64 under
1267``tree['data']`` and write the result as JSON.
1268
1269Note that the base64 encoding of encrypted data can actually make the encrypted
1270file larger than the cleartext one.
1271
1272In-place encryption/decryption also works on binary files.
1273
1274.. code::
1275
1276	$ dd if=/dev/urandom of=/tmp/somerandom bs=1024
1277	count=512
1278	512+0 records in
1279	512+0 records out
1280	524288 bytes (524 kB) copied, 0.0466158 s, 11.2 MB/s
1281
1282	$ sha512sum /tmp/somerandom
1283	9589bb20280e9d381f7a192000498c994e921b3cdb11d2ef5a986578dc2239a340b25ef30691bac72bdb14028270828dad7e8bd31e274af9828c40d216e60cbe /tmp/somerandom
1284
1285	$ sops -e -i /tmp/somerandom
1286	please wait while a data encryption key is being generated and stored securely
1287
1288	$ sops -d -i /tmp/somerandom
1289
1290	$ sha512sum /tmp/somerandom
1291	9589bb20280e9d381f7a192000498c994e921b3cdb11d2ef5a986578dc2239a340b25ef30691bac72bdb14028270828dad7e8bd31e274af9828c40d216e60cbe /tmp/somerandom
1292
1293Extract a sub-part of a document tree
1294~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1295
1296``sops`` can extract a specific part of a YAML or JSON document, by provided the
1297path in the ``--extract`` command line flag. This is useful to extract specific
1298values, like keys, without needing an extra parser.
1299
1300.. code:: bash
1301
1302	$ sops -d --extract '["app2"]["key"]' ~/git/svc/sops/example.yaml
1303	-----BEGIN RSA PRIVATE KEY-----
1304	MIIBPAIBAAJBAPTMNIyHuZtpLYc7VsHQtwOkWYobkUblmHWRmbXzlAX6K8tMf3Wf
1305	ImcbNkqAKnELzFAPSBeEMhrBN0PyOC9lYlMCAwEAAQJBALXD4sjuBn1E7Y9aGiMz
1306	bJEBuZJ4wbhYxomVoQKfaCu+kH80uLFZKoSz85/ySauWE8LgZcMLIBoiXNhDKfQL
1307	vHECIQD6tCG9NMFWor69kgbX8vK5Y+QL+kRq+9HK6yZ9a+hsLQIhAPn4Ie6HGTjw
1308	fHSTXWZpGSan7NwTkIu4U5q2SlLjcZh/AiEA78NYRRBwGwAYNUqzutGBqyXKUl4u
1309	Erb0xAEyVV7e8J0CIQC8VBY8f8yg+Y7Kxbw4zDYGyb3KkXL10YorpeuZR4LuQQIg
1310	bKGPkMM4w5blyE1tqGN0T7sJwEx+EUOgacRNqM2ljVA=
1311	-----END RSA PRIVATE KEY-----
1312
1313The tree path syntax uses regular python dictionary syntax, without the
1314variable name. Extract keys by naming them, and array elements by numbering
1315them.
1316
1317.. code:: bash
1318
1319	$ sops -d --extract '["an_array"][1]' ~/git/svc/sops/example.yaml
1320	secretuser2
1321
1322Set a sub-part in a document tree
1323~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1324
1325``sops`` can set a specific part of a YAML or JSON document, by providing
1326the path and value in the ``--set`` command line flag. This is useful to
1327set specific values, like keys, without needing an editor.
1328
1329.. code:: bash
1330
1331	$ sops --set '["app2"]["key"] "app2keystringvalue"'  ~/git/svc/sops/example.yaml
1332
1333The tree path syntax uses regular python dictionary syntax, without the
1334variable name. Set to keys by naming them, and array elements by
1335numbering them.
1336
1337.. code:: bash
1338
1339	$ sops --set '["an_array"][1] "secretuser2"' ~/git/svc/sops/example.yaml
1340
1341The value must be formatted as json.
1342
1343.. code:: bash
1344
1345	$ sops --set '["an_array"][1] {"uid1":null,"uid2":1000,"uid3":["bob"]}' ~/git/svc/sops/example.yaml
1346
1347Using sops as a library in a python script
1348~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1349
1350You can import sops as a module and use it in your python program.
1351
1352.. code:: python
1353
1354	import sops
1355
1356	pathtype = sops.detect_filetype(path)
1357	tree = sops.load_file_into_tree(path, pathtype)
1358	sops_key, tree = sops.get_key(tree)
1359	tree = sops.walk_and_decrypt(tree, sops_key)
1360	sops.write_file(tree, path=path, filetype=pathtype)
1361
1362Note: this uses the previous implementation of `sops` written in python,
1363
1364and so doesn't support newer features such as GCP-KMS.
1365To use the current version, call out to ``sops`` using ``subprocess.run``
1366
1367Showing diffs in cleartext in git
1368~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1369
1370You most likely want to store encrypted files in a version controlled repository.
1371Sops can be used with git to decrypt files when showing diffs between versions.
1372This is very handy for reviewing changes or visualizing history.
1373
1374To configure sops to decrypt files during diff, create a ``.gitattributes`` file
1375at the root of your repository that contains a filter and a command.
1376
1377.. code::
1378
1379	*.yaml diff=sopsdiffer
1380
1381Here we only care about YAML files. ``sopsdiffer`` is an arbitrary name that we map
1382to a sops command in the git configuration file of the repository.
1383
1384.. code:: bash
1385
1386	$ git config diff.sopsdiffer.textconv "sops -d"
1387
1388	$ grep -A 1 sopsdiffer .git/config
1389	[diff "sopsdiffer"]
1390		textconv = "sops -d"
1391
1392With this in place, calls to ``git diff`` will decrypt both previous and current
1393versions of the target file prior to displaying the diff. And it even works with
1394git client interfaces, because they call git diff under the hood!
1395
1396Encrypting only parts of a file
1397~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1398
1399Note: this only works on YAML and JSON files, not on BINARY files.
1400
1401By default, ``sops`` encrypts all the values of a YAML or JSON file and leaves the
1402keys in cleartext. In some instances, you may want to exclude some values from
1403being encrypted. This can be accomplished by adding the suffix **_unencrypted**
1404to any key of a file. When set, all values underneath the key that set the
1405**_unencrypted** prefix will be left in cleartext.
1406
1407Note that, while in cleartext, unencrypted content is still added to the
1408checksum of the file, and thus cannot be modified outside of sops without
1409breaking the file integrity check.
1410
1411The unencrypted suffix can be set to a different value using the
1412``--unencrypted-suffix`` option.
1413
1414Conversely, you can opt in to only encrypt some values in a YAML or JSON file,
1415by adding a chosen suffix to those keys and passing it to the ``--encrypted-suffix`` option.
1416
1417A third method is to use the ``--encrypted-regex`` which will only encrypt values under
1418keys that match the supplied regular expression.  For example, this command:
1419
1420.. code:: bash
1421
1422	$ sops --encrypt --encrypted-regex '^(data|stringData)$' k8s-secrets.yaml
1423
1424will encrypt the values under the ``data`` and ``stringData`` keys in a YAML file
1425containing kubernetes secrets.  It will not encrypt other values that help you to
1426navigate the file, like ``metadata`` which contains the secrets' names.
1427
1428Conversely, you can opt in to only left certain keys without encrypting by using the
1429``--unencrypted-regex`` option, which will leave the values unencrypted of those keys
1430that match the supplied regular expression. For example, this command:
1431
1432.. code:: bash
1433
1434  $ sops --encrypt --unencrypted-regex '^(description|metadata)$' k8s-secrets.yaml
1435
1436will not encrypt the values under the ``description`` and ``metadata`` keys in a YAML file
1437containing kubernetes secrets, while encrypting everything else.
1438
1439You can also specify these options in the ``.sops.yaml`` config file.
1440
1441Note: these four options ``--unencrypted-suffix``, ``--encrypted-suffix``, ``--encrypted-regex`` and ``--unencrypted-regex`` are
1442mutually exclusive and cannot all be used in the same file.
1443
1444Encryption Protocol
1445-------------------
1446
1447When sops creates a file, it generates a random 256 bit data key and asks each
1448KMS and PGP master key to encrypt the data key. The encrypted version of the data
1449key is stored in the ``sops`` metadata under ``sops.kms`` and ``sops.pgp``.
1450
1451For KMS:
1452
1453.. code:: yaml
1454
1455    sops:
1456        kms:
1457        -   enc: CiC6yCOtzsnFhkfdIslYZ0bAf//gYLYCmIu87B3sy/5yYxKnAQEBAQB4usgjrc7JxYZH3SLJWGdGwH//4GC2ApiLvOwd7Mv+cmMAAAB+MHwGCSqGSIb3DQEHBqBvMG0CAQAwaAYJKoZIhvcNAQcBMB4GCWCGSAFlAwQBLjARBAyGdRODuYMHbA8Ozj8CARCAO7opMolPJUmBXd39Zlp0L2H9fzMKidHm1vvaF6nNFq0ClRY7FlIZmTm4JfnOebPseffiXFn9tG8cq7oi
1458            enc_ts: 1439568549.245995
1459            arn: arn:aws:kms:us-east-1:656532927350:key/920aff2e-c5f1-4040-943a-047fa387b27e
1460
1461For PGP:
1462
1463.. code:: yaml
1464
1465    sops:
1466        pgp:
1467        -   fp: 85D77543B3D624B63CEA9E6DBC17301B491B3F21
1468            created_at: 1441570391.930042
1469            enc: |
1470                -----BEGIN PGP MESSAGE-----
1471                Version: GnuPG v1
1472
1473                hQIMA0t4uZHfl9qgAQ//UvGAwGePyHuf2/zayWcloGaDs0MzI+zw6CmXvMRNPUsA
1474                pAgRKczJmDu4+XzN+cxX5Iq9xEWIbny9B5rOjwTXT3qcUYZ4Gkzbq4MWkjuPp/Iv
1475                qO4MJaYzoH5YxC4YORQ2LvzhA2YGsCzYnljmatGEUNg01yJ6r5mwFwDxl4Nc80Cn
1476                RwnHuGExK8j1jYJZu/juK1qRbuBOAuruIPPWVdFB845PA7waacG1IdUW3ZtBkOy3
1477                O0BIfG2ekRg0Nik6sTOhDUA+l2bewCcECI8FYCEjwHm9Sg5cxmP2V5m1mby+uKAm
1478                kewaoOyjbmV1Mh3iI1b/AQMr+/6ZE9MT2KnsoWosYamFyjxV5r1ZZM7cWKnOT+tu
1479                KOvGhTV1TeOfVpajNTNwtV/Oyh3mMLQ0F0HgCTqomQVqw5+sj7OWAASuD3CU/dyo
1480                pcmY5Qe0TNL1JsMNEH8LJDqSh+E0hsUxdY1ouVsg3ysf6mdM8ciWb3WRGxih1Vmf
1481                unfLy8Ly3V7ZIC8EHV8aLJqh32jIZV4i2zXIoO4ZBKrudKcECY1C2+zb/TziVAL8
1482                qyPe47q8gi1rIyEv5uirLZjgpP+JkDUgoMnzlX334FZ9pWtQMYW4Y67urAI4xUq6
1483                /q1zBAeHoeeeQK+YKDB7Ak/Y22YsiqQbNp2n4CKSKAE4erZLWVtDvSp+49SWmS/S
1484                XgGi+13MaXIp0ecPKyNTBjF+NOw/I3muyKr8EbDHrd2XgIT06QXqjYLsCb1TZ0zm
1485                xgXsOTY3b+ONQ2zjhcovanDp7/k77B+gFitLYKg4BLZsl7gJB12T8MQnpfSmRT4=
1486                =oJgS
1487                -----END PGP MESSAGE-----
1488
1489``sops`` then opens a text editor on the newly created file. The user adds data to the
1490file and saves it when done.
1491
1492Upon save, sops browses the entire file as a key/value tree. Every time sops
1493encounters a leaf value (a value that does not have children), it encrypts the
1494value with AES256_GCM using the data key and a 256 bit random initialization
1495vector.
1496
1497Each file uses a single data key to encrypt all values of a document, but each
1498value receives a unique initialization vector and has unique authentication data.
1499
1500Additional data is used to guarantee the integrity of the encrypted data
1501and of the tree structure: when encrypting the tree, key names are concatenated
1502into a byte string that is used as AEAD additional data (aad) when encrypting
1503values. We expect that keys do not carry sensitive information, and
1504keeping them in cleartext allows for better diff and overall readability.
1505
1506Any valid KMS or PGP master key can later decrypt the data key and access the
1507data.
1508
1509Multiple master keys allow for sharing encrypted files without sharing master
1510keys, and provide a disaster recovery solution. The recommended way to use sops
1511is to have two KMS master keys in different regions and one PGP public key with
1512the private key stored offline. If, by any chance, both KMS master keys are
1513lost, you can always recover the encrypted data using the PGP private key.
1514
1515Message Authentication Code
1516~~~~~~~~~~~~~~~~~~~~~~~~~~~
1517
1518In addition to authenticating branches of the tree using keys as additional
1519data, sops computes a MAC on all the values to ensure that no value has been
1520added or removed fraudulently. The MAC is stored encrypted with AES_GCM and
1521the data key under tree->`sops`->`mac`.
1522
1523Motivation
1524----------
1525
1526Automating the distribution of secrets and credentials to components of an
1527infrastructure is a hard problem. We know how to encrypt secrets and share them
1528between humans, but extending that trust to systems is difficult. Particularly
1529when these systems follow devops principles and are created and destroyed
1530without human intervention. The issue boils down to establishing the initial
1531trust of a system that just joined the infrastructure, and providing it access
1532to the secrets it needs to configure itself.
1533
1534The initial trust
1535~~~~~~~~~~~~~~~~~
1536
1537In many infrastructures, even highly dynamic ones, the initial trust is
1538established by a human. An example is seen in Puppet by the way certificates are
1539issued: when a new system attempts to join a Puppetmaster, an administrator
1540must, by default, manually approve the issuance of the certificate the system
1541needs. This is cumbersome, and many puppetmasters are configured to auto-sign
1542new certificates to work around that issue. This is obviously not recommended
1543and far from ideal.
1544
1545AWS provides a more flexible approach to trusting new systems. It uses a
1546powerful mechanism of roles and identities. In AWS, it is possible to verify
1547that a new system has been granted a specific role at creation, and it is
1548possible to map that role to specific resources. Instead of trusting new systems
1549directly, the administrator trusts the AWS permission model and its automation
1550infrastructure. As long as AWS keys are safe, and the AWS API is secure, we can
1551assume that trust is maintained and systems are who they say they are.
1552
1553KMS, Trust and secrets distribution
1554~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1555
1556Using the AWS trust model, we can create fine grained access controls to
1557Amazon's Key Management Service (KMS). KMS is a service that encrypts and
1558decrypts data with AES_GCM, using keys that are never visible to users of the
1559service. Each KMS master key has a set of role-based access controls, and
1560individual roles are permitted to encrypt or decrypt using the master key. KMS
1561helps solve the problem of distributing keys, by shifting it into an access
1562control problem that can be solved using AWS's trust model.
1563
1564Operational requirements
1565~~~~~~~~~~~~~~~~~~~~~~~~
1566
1567When Mozilla's Services Operations team started revisiting the issue of
1568distributing secrets to EC2 instances, we set a goal to store these secrets
1569encrypted until the very last moment, when they need to be decrypted on target
1570systems. Not unlike many other organizations that operate sufficiently complex
1571automation, we found this to be a hard problem with a number of prerequisites:
1572
15731. Secrets must be stored in YAML files for easy integration into hiera
1574
15752. Secrets must be stored in GIT, and when a new CloudFormation stack is
1576   built, the current HEAD is pinned to the stack. (This allows secrets to
1577   be changed in GIT without impacting the current stack that may
1578   autoscale).
1579
15803. Entries must be encrypted separately. Encrypting entire files as blobs makes
1581   git conflict resolution almost impossible. Encrypting each entry
1582   separately is much easier to manage.
1583
15844. Secrets must always be encrypted on disk (admin laptop, upstream
1585   git repo, jenkins and S3) and only be decrypted on the target
1586   systems
1587
1588SOPS can be used to encrypt YAML, JSON and BINARY files. In BINARY mode, the
1589content of the file is treated as a blob, the same way PGP would encrypt an
1590entire file. In YAML and JSON modes, however, the content of the file is
1591manipulated as a tree where keys are stored in cleartext, and values are
1592encrypted. hiera-eyaml does something similar, and over the years we learned
1593to appreciate its benefits, namely:
1594
1595* diffs are meaningful. If a single value of a file is modified, only that
1596  value will show up in the diff. The diff is still limited to only showing
1597  encrypted data, but that information is already more granular that
1598  indicating that an entire file has changed.
1599
1600* conflicts are easier to resolve. If multiple users are working on the
1601  same encrypted files, as long as they don't modify the same values,
1602  changes are easy to merge. This is an improvement over the PGP
1603  encryption approach where unsolvable conflicts often happen when
1604  multiple users work on the same file.
1605
1606OpenPGP integration
1607~~~~~~~~~~~~~~~~~~~
1608
1609OpenPGP gets a lot of bad press for being an outdated crypto protocol, and while
1610true, what really made us look for alternatives is the difficulty of managing and
1611distributing keys to systems. With KMS, we manage permissions to an API, not keys,
1612and that's a lot easier to do.
1613
1614But PGP is not dead yet, and we still rely on it heavily as a backup solution:
1615all our files are encrypted with KMS and with one PGP public key, with its
1616private key stored securely for emergency decryption in the event that we lose
1617all our KMS master keys.
1618
1619SOPS can be used without KMS entirely, the same way you would use an encrypted
1620PGP file: by referencing the pubkeys of each individual who has access to the file.
1621It can easily be done by providing sops with a comma-separated list of public keys
1622when creating a new file:
1623
1624.. code:: bash
1625
1626	$ sops --pgp "E60892BB9BD89A69F759A1A0A3D652173B763E8F,84050F1D61AF7C230A12217687DF65059EF093D3,85D77543B3D624B63CEA9E6DBC17301B491B3F21" mynewfile.yaml
1627
1628Threat Model
1629------------
1630
1631The security of the data stored using sops is as strong as the weakest
1632cryptographic mechanism. Values are encrypted using AES256_GCM which is the
1633strongest symmetric encryption algorithm known today. Data keys are encrypted
1634in either KMS, which also uses AES256_GCM, or PGP which uses either RSA or
1635ECDSA keys.
1636
1637Going from the most likely to the least likely, the threats are as follows:
1638
1639Compromised AWS credentials grant access to KMS master key
1640~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1641
1642An attacker with access to an AWS console can grant itself access to one of
1643the KMS master keys used to encrypt a sops data key. This threat should be
1644mitigated by protecting AWS accesses with strong controls, such as multi-factor
1645authentication, and also by performing regular audits of permissions granted
1646to AWS users.
1647
1648Compromised PGP key
1649~~~~~~~~~~~~~~~~~~~
1650
1651PGP keys are routinely mishandled, either because owners copy them from
1652machine to machine, or because the key is left forgotten on an unused machine
1653an attacker gains access to. When using PGP encryption, sops users should take
1654special care of PGP private keys, and store them on smart cards or offline
1655as often as possible.
1656
1657Factorized RSA key
1658~~~~~~~~~~~~~~~~~~
1659
1660sops doesn't apply any restriction on the size or type of PGP keys. A weak PGP
1661keys, for example 512 bits RSA, could be factorized by an attacker to gain
1662access to the private key and decrypt the data key. Users of sops should rely
1663on strong keys, such as 2048+ bits RSA keys, or 256+ bits ECDSA keys.
1664
1665Weak AES cryptography
1666~~~~~~~~~~~~~~~~~~~~~
1667
1668A vulnerability in AES256_GCM could potentially leak the data key or the KMS
1669master key used by a sops encrypted file. While no such vulnerability exists
1670today, we recommend that users keep their encrypted files reasonably private.
1671
1672Backward compatibility
1673----------------------
1674
1675``sops`` will remain backward compatible on the major version, meaning that all
1676improvements brought to the 1.X and 2.X branches (current) will maintain the
1677file format introduced in **1.0**.
1678
1679Security
1680--------
1681
1682Please report security issues to jvehent at mozilla dot com, or by using one
1683of the contact method available on keybase: `https://keybase.io/jvehent <https://keybase.io/jvehent>`_
1684
1685License
1686-------
1687Mozilla Public License Version 2.0
1688
1689Authors
1690-------
1691
1692The core team is composed of:
1693
1694* Adrian Utrilla @autrilla
1695* Julien Vehent @jvehent
1696* AJ Banhken @ajvb
1697
1698And a whole bunch of `contributors <https://github.com/mozilla/sops/graphs/contributors>`_
1699
1700Credits
1701-------
1702
1703`sops` was inspired by `hiera-eyaml <https://github.com/TomPoulton/hiera-eyaml>`_,
1704`credstash <https://github.com/LuminalOSS/credstash>`_ ,
1705`sneaker <https://github.com/codahale/sneaker>`_,
1706`password store <http://www.passwordstore.org/>`_ and too many years managing
1707PGP encrypted files by hand...
1708