Post

Encrypt Your Sensitive Information Before Storing It - Encrypting with Mozilla SOPS and AGE

Committing secrets to your Git Repo can expose information like passwords, access tokens, and other types of sensitive information.Some might think that committing secrets to a private Git Repo is OK, but I am here to tell you it’s not.If you’re going to commit secrets to a git repo, private or public, you should encrypt them first using Mozilla SOPS (Secret Operations) and AGE.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.Age is a simple, modern, and secure file encryption tool, format, and build using Go.It can encrypt and decrypt your files making then safe enough to commit to your Git repos!

A HUGE thanks to Datree for sponsoring this video!
Combat misconfigurations. Empower engineers. https://www.datree.io

📺 Watch Video

Install SOPS

You can install sops by following this guide.

test with

1
sops -v

should see

1
sops 3.7.3 (latest)

Install Age

You can install age by following this guide

test age with

1
 age -version

should see

1
v1.0.0

test age-keygen with

1
 age-keygen -version

should see

1
v1.0.0

configure keys

Now that we have age installed we need to create a public and private key

1
age-keygen -o key.txt

should see

1
2
age-keygen: warning: writing secret key to a world-readable file
Public key: age1epzmwwzw8n09slh0c7z0z52x43nnga7lkksx3qrh07tqz5v7lcys45428t

let’s look at the contents

1
cat key.txt

should see

1
2
3
# created: 2022-09-26T21:55:47-05:00
# public key: age1epzmwwzw8n09slh0c7z0z52x43nnga7lkksx3qrh07tqz5v7lcys45428t
AGE-SECRET-KEY-1HJCRJVK7EE3A5N8CRP8YSDUGZKNW90Y5UR2RGYAS8L279LFP6LCQU5ADNR

Remember this is a secret so keep this safe! Do not commit this!

move the file and add to our shell

1
2
mkdir ~/.sops
mv ./key.txt ~/.sops

add it to our shell

1
2
nano ~/.zshrc 
# or nano ~/.bashrc

add to the end of file

1
export SOPS_AGE_KEY_FILE=$HOME/.sops/key.txt

source our shell

1
2
source ~/.zshrc 
# or source ~/.bashrc

Now! Let’s encrypt

A few ways you can do this.You can encrypt in place or encrypt with an editor but we’re going to do an in place encryption.

YAML

This can be kubernetes secrets, helm values, or just plain old yaml

create a secret with the following contents

secret.yaml

1
2
3
4
5
6
7
8
9
---
apiVersion: v1
kind: Secret
metadata:
    name: mysql-secret
    namespace: default
stringData:
    MYSQL_USER: root
    MYSQL_PASSWORD: super-Secret-Password!!!!

to encrypt

1
sops --encrypt --age $(cat $SOPS_AGE_KEY_FILE |grep -oP "public key: \K(.*)") --encrypted-regex '^(data|stringData)$' --in-place ./secret.yaml

to decrypt

1
sops --decrypt --age $(cat $SOPS_AGE_KEY_FILE |grep -oP "public key: \K(.*)") --encrypted-regex '^(data|stringData)$' --in-place ./secret.yaml

Kubernetes

If you want to decrypt this secret on the fly and apply to kubernetes

encrypt first

1
sops --encrypt --age $(cat $SOPS_AGE_KEY_FILE |grep -oP "public key: \K(.*)") --encrypted-regex '^(data|stringData)$' --in-place ./secret.yaml

decrypt and pipe to kubectl

1
sops --decrypt --age $(cat $SOPS_AGE_KEY_FILE |grep -oP "public key: \K(.*)") --encrypted-regex '^(data|stringData)$' ./secret.yaml | kubectl apply -f -

check it with

1
k describe secrets mysql-secret-test

then

1
 kubectl get secret mysql-secret-test -o jsonpath='{.data}'

then

1
kubectl get secret mysql-secret-test -o jsonpath='{.data.MYSQL_PASSWORD}'  | base64 --decode

VSCode

install vscode extension

choose the beta for sops because that supports age + sops

don’t forget to add .decrypted~secret.yaml to .gitignore

encrypt .env files

make sure extension is installed

.ENV Files

create

secret.env

MYSQL_USER=superroot
MYSQL_PASSWORD="super-Secret-Password!!!!############"

encrypt

1
sops --encrypt --age $(cat $SOPS_AGE_KEY_FILE |grep -oP "public key: \K(.*)") -i .env

decrypt

1
sops --decrypt --age $(cat $SOPS_AGE_KEY_FILE |grep -oP "public key: \K(.*)") -i .env

don’t forget to add .decrypted~secret.env to your .gitignore

JSON Files

secret.json

1
2
3
4
{
    "mySqlUser": "superroot",
    "password": "super-Secret-Password!!!!#######"
}

encrypt

1
sops --encrypt --age $(cat $SOPS_AGE_KEY_FILE |grep -oP "public key: \K(.*)") -i secret.json

decrypt

1
sops --decrypt --age $(cat $SOPS_AGE_KEY_FILE |grep -oP "public key: \K(.*)") -i secret.json

don’t forget to add .decrypted~secret.json to your .gitignore

INI Files

secret.ini

1
2
3
[database]
user     = superroot
password = super-Secret-Password!!!!1223

encrypt

1
sops --encrypt --age $(cat $SOPS_AGE_KEY_FILE |grep -oP "public key: \K(.*)") -i secret.ini

decrypt

1
sops --decrypt --age $(cat $SOPS_AGE_KEY_FILE |grep -oP "public key: \K(.*)") -i secret.ini

don’t forget to add .decrypted~secret.ini to you .gitignore

Files

secret.sql

1
2
3
--- https://xkcd.com/327/
--- DO NOT USE
INSERT INTO Students VALUES ( 'Robert' );  DROP TABLE STUDENTS; --' )

encrypt

1
sops --encrypt --age $(cat $SOPS_AGE_KEY_FILE |grep -oP "public key: \K(.*)") --in-place ./secret.sql

decrypt

1
sops --decrypt --age $(cat $SOPS_AGE_KEY_FILE |grep -oP "public key: \K(.*)") --in-place ./secret.sql

Flux

If you’re thinking of doing GitOps with Flux, you can check out my video on this topic or see my documentation.You can do cluster decryption and fully automate decryption of secrets.

In cluster decryption with Flux

https://fluxcd.io/flux/guides/mozilla-sops/#configure-in-cluster-secrets-decryption

Join the conversation

⚙️ See all the hardware I recommend at https://l.technotim.live/gear

🚀 Don’t forget to check out the 🚀Launchpad repo with all of the quick start source files

This post is licensed under CC BY 4.0 by the author.