Skip to content

Mozilla SOPS

Overview

In the broadest terms SOPS is an editor of encrypted files that supports YAML, JSON, ENV, INI and BINARY formats and encrypts with AWS KMS, GCP KMS, Azure Key Vault, age, and PGP.

One trick of SOPS is that statement of supported file formats. It natively understands how to encrypt data, but keep the keys in plain-text.

This allows us to store our secrets in git without exposing the plaintext, but keeping meaningful capabilities such as diff, etc.

Example file

Let's encrypt an example, using age.

If we start with the following secret;

apiVersion: v1
kind: Secret
metadata:
  name: mysecret
data:
  email_username: ZW1haWx1c2VybmFtZQ==
  email_password: QWN0aXZlVGhpcnRlZW5XaWxkZm93bERhbmRlckRpbmdvQW50aXRydXN0
  secret_key: Q3ViYnlob2xlUmVjbGluZXJBcHBlYWxpbmdTYXVjaW5lc3NNYWx0R3JhdGlmeQ==
  cookie_domain: bXlkb21haW4=
  email_host: bWFpbGwubXlkb21haW4=
  email_from: ZW1haWx1c2VybmFtZUBteWRvbWFpbg==

We can see it would be a bad idea to store this directly in git as base64 encoding is not safe enough. Let's encrypt to an age public key and see the results:

Encrypting

sops --encrypt --age age1jktzcd9xnqrlejxltljh4j5fdly0hr8yg4z08qlkspyx7946cudsapr3df secrets.yaml | tee secrets.enc.yaml
This above command will write the encrypted file to secrets.enc.yaml, and display to stdout

apiVersion: ENC[AES256_GCM,data:mgo=,iv:jtZQuqQB8UEGGxgq543OgU72k0A30Jiu8mVG2v3aYCU=,tag:vDL3C1kmHVLJCBFBj3dpkQ==,type:str]
kind: ENC[AES256_GCM,data:Ij0wgW7h,iv:KHYyf3b4xe4lwfuRDb03ngoKjd9vR+SBUe8wjVbrEUk=,tag:M0n7Rm2bXdmTgFZEmw9nFA==,type:str]
metadata:
    name: ENC[AES256_GCM,data:IKscS2EadQ8=,iv:ywySZ+pE+sDYPp7Jj9c5z47Xw1JhlV6Bu1HSIevwTl4=,tag:K+TBZkwuZMABjSx9e5DWFA==,type:str]
data:
    email_username: ENC[AES256_GCM,data:bA38D6vm/hssRcMPku6fBGjcVvA=,iv:hR2n6mdu1D7axx5EuvtAXCvtP9+6SyQT9ag02eZFcLc=,tag:aiB882AxrMONDvgolyVdxA==,type:str]
    email_password: ENC[AES256_GCM,data:2/QIgbGBnzR+dOTzm2E80TNknCONbRQYwMhdy7zKZYq0akIJhwz8ucU9Z49yAEYDqVjDnYLnv0w=,iv:X/ODB11+KjlIPa6Z3SeIGVyUNYtg3/q3w5WF4BdrPfE=,tag:3qyqH12GthJCvegXnxnEqg==,type:str]
    secret_key: ENC[AES256_GCM,data:P9NfXL//cnZpkwrxtVRhVug9nIkzpSHVpoN24rO36I0yNlxYp4fNlsZjyfy9aXqGMu5NzxTmmRumNbJxHKWsNw==,iv:8YLtE+7cxq96Pg072TjuI4NFj6FAaIw4AV6zwdmzbgk=,tag:YTobqYT8OpTJBiH/i/19rg==,type:str]
    cookie_domain: ENC[AES256_GCM,data:nFs7TaN8RaQrVHL0,iv:APCZVvp51U7dBtgw1uC9GH6ZrPSI5vqol5jFyzUXFWs=,tag:2onB2seYnvWV92Oa/I2OAA==,type:str]
    email_host: ENC[AES256_GCM,data:jepu2umzeE9/TfVSgJXcxTpNMqw=,iv:tRynuPfbXGLU0Uq9k4y78Z1of92VI4K+ZKv7Qp5Hnmc=,tag:fjXjVDELDktO30pG23uKEQ==,type:str]
    email_from: ENC[AES256_GCM,data:NX/l1PPwcFYN3IA7L5Ruk80H7lfmfkf3tp6mzj+Td9Y=,iv:gbIJA9+E/fG4pVF7WAfjrTEDBsJGTOFmcETe3ZbbvI0=,tag:oU9Y+pxlZ9Gp/S3Ccqh7uQ==,type:str]
sops:
    kms: []
    gcp_kms: []
    azure_kv: []
    hc_vault: []
    age:
        - recipient: age1jktzcd9xnqrlejxltljh4j5fdly0hr8yg4z08qlkspyx7946cudsapr3df
          enc: |
            -----BEGIN AGE ENCRYPTED FILE-----
            YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBZTzVHZk5TZ2JvMFlDZnhC
            eXJwWG9UUFM3VUhTSEJYdjhDaE94djhPNmt3CnBUTlZBeVV0eDdFUm9PZEJTR0Za
            SE5vVDkxU3lHenQrWFhKaU5yNUlTSlkKLS0tIDRid2VMUk9HQVpZNnJxTUwzNkJt
            ZWZDTFRxeDhYR3pyTkYwRUJ4bkIrdmsKd69nPaklFYzpnKve6DtofD8RofI+V8Ik
            9GUqNLE3zk7MIOTPXu18yzbl6AdL8BIQ1i0uVsS1bhWvv+JMPHg+XQ==
            -----END AGE ENCRYPTED FILE-----
    lastmodified: "2024-03-13T23:10:13Z"
    mac: ENC[AES256_GCM,data:6WVDyXTv5X6aNmr2Gf8TdvmiKPYBw5ET0pcO2VMfv+ErgyjloyhS132lvPOQFRUN7MZ59kTVCzDGx2VJ1w7DWWJCd3/plISKxUPVKZapKCOPrBeUHPjPGgKBVIzA3K2w98C2j3AQWtNxY6iEl0TUcbBW4tmlUYVJbqZeYgeiBE0=,iv:uzT3F3EizSgAM3IuBsvorrevOXZItNF4IyQhwa51Amg=,tag:M2gRJXdRBokhtcYhGF2qVw==,type:str]
    pgp: []
    unencrypted_suffix: _unencrypted
    version: 3.8.1
We can see the unencrypted keys, but each value itself is encrypted. We can also see in the file the meta-data around what keys it is encrypted to, file versions and more.

You can edit the file directly with the sops $filename command from now on. Make sure you delete the original, and from now on only commit the .enc.yaml files via git. Tools like trufflehog can help here.

Decrypting and applying

If you wanted to apply this secret directly to kubernetes without writing the plain-text to disk you could do something like the following:

sops --decrypt secrets.enc.yaml | kubectl apply -f -

Next Steps

SOPS can do a lot more, including publishing directly to vault or S3. For that, and more including key management, key rotation, audit loggings see SOPS