Share sensitive data with Git and cryptography

 

All projects require a certain amount of data that must remain secret and private.

 

This includes external API keys, identifiers to third-party services, certificates and SSH private keys.

 

The real problem is that the more the projects progress, the more secrets we have to share to run the application.

 

TLDR;

Don’t use environment variables for API keys and other secrets instead save them in an encrypted JSON file.

  • Use Kourou to encrypt/decrypt the files containing your secrets
  • Use Kuzzle Vault to load those secrets in your application memory

Before, we had environment variables

 

The simplest and most common way to share secrets is via environment variables.

 

The problem is that you can quickly find yourself with a dozen different API keys and other secrets.

 

Multiplied by the number of target deployment environments, you quickly end up with too many environment variables to manage.

 

The problem is that it is necessary to provide this set of variables to each person who will have to work on the project.

 

SENTRY_DSN=********** AWS_S3_KEY_ID=******** AWS_S3_SECRET_KEY=********* SENDGRID_API_KEY=******** TWILIO_API_KEY=******** KUZZLE_VAULT_KEY=******** ABEEWAY_TOKEN=********* WIREPAS_PASSWORD=******* CLOUDINARY_API_KEY=********* STRIPE_TOKEN=******* node server.js

 

And we're not even talking about the work needed by our dear Devops to maintain all these variables for several deployment environments (production, staging, development, etc).

Embrace cryptography

 

One solution is to keep all these secrets in a file that we will add to the repository and commit like any other file.

 

The only difference is that we will encrypt this file with AES 256 to make sure that nobody will be able to get their hands on the secrets.

 

This way there is only one secret that you have to share with your teams: the encryption key.

Encrypt with Kourou, the Kuzzle CLI

At Kuzzle we decided to take matters into our own hands and develop our secure secret sharing system.

 

So we're going to write all our secrets in a JSON file.

This file will of course NEVER be committed in the repository since it contains the secrets in clear text.

 

{
  "sentryDsn": "sentry dsn here",
  "aws": {
    "keyId": "access key id",
    "secretKey": "secret key id"
  },
  "sendgridApiKey": "sendgrid api key",
  "twillioApiKey": "twillio api key",
  "abeewayToken": "abeeway token",
  "wirepasToken": "wirepas token",
  "cloudinaryApiKey": "cloudinary api key",
  "stripeToken": "strip token"
}

 

Then we're going to encrypt that file.

However we will only encrypt the values so we can always read its contents.

 

It is this encrypted file that we will save and commit in the project repository.

 

You can use Kourou for this:

 

$ kourou vault:encrypt secrets.json --vault-key my-secret-password
 
 πŸš€ Kourou - Encrypts an entire file.
 
 [βœ”] Secrets were successfully encrypted into the file secrets.enc.json

 

The generated file is similar to the original JSON file except that all values have been encrypted with AES 256.

 

{
  "sentryDsn": "d7a909787d18f2770d2844e7fe87d8cf.7a0bfad57e75c31d507a5c24aa1c95b7",
  "aws": {
    "keyId": "a9de2d8b425bf16cd2fa6bf8cdb4d3c9.b24aa1cc24c8e6249451aaf3f277a46a",
    "secretKey": "659ac90b460f9dd8e6c58ae2dd1b7cc4.892dfa8083c983e37501ed0489f64955"
  },
  "sendgridApiKey": "6ff4edb98a7fc74f98c0779c097db151bc462d51a190c3043b1fc8af4b1facfb.da38762a2cf31bcc9bc6fab04affa14b",
  "twillioApiKey": "6a97379c4fd5f421c538af6b3b80c016.87d3dd3d483608751e9c4a0ef82f2b99",
  "abeewayToken": "63947d7df667089533bd022989515467.ff002b2c0910d600d1502db9443c8f8e",
  "wirepasToken": "32b8002023a6005812c79f08fa1a78f0.d093b40744f56be06af71fe9fed68064",
  "cloudinaryApiKey": "f145b52b7f2376839766d789e81d9d817503e6dc04184e82ce4167cbb6f5cef1.227483c5614a9629e9efffe5b7fdae6f",
  "stripeToken": "a19cb45d7185b58a3e9f589c55c59c14.0c2c1253c3e0b98cfb07b6bf4cd10dc6"
}

Decrypt in your application with Kuzzle Vault

Once we have our file containing the encrypted secrets, we will be able to use it in our application using the Kuzzle Vault.

 

The Kuzzle Vault is a simple NPM package with no dependencies that allows to decrypt and use the secrets in an application.

 

import { Vault } from 'kuzzle-vault';

const vault = new Vault('my-secret-password');
vault.decrypt('config/prod/secrets.enc.json');

// decrypted secrets are now loaded in memory
vault.secrets.aws.keyId

 

So we can now share and then load all the secrets needed to run the application directly and securely from the file system.

 

If you have different secrets according to your deployment environments, this is the time to save them all in different files so that they can be used automatically by your Continuous Integration system at the time of deployment.

 

config
β”œβ”€β”€ local
β”‚   └── secrets.enc.json
β”œβ”€β”€ production
β”‚   └── secrets.enc.json
└── staging
    └── secrets.enc.json

 

Go further

Kourou has many methods for managing encrypted secret files.

 

For example it is possible to add a new secret to an existing file or to display the value of a secret:

 

$ kourou vault:add config/secrets.enc.json aws.s3 aws-secret-key

$ kourou vault:show config/secrets.enc.json aws.s3

 

If you need to encrypt a regular file, you can also use Kourou:

 

$ kourou file:encrypt id_rsa -o id_rsa.enc

 

You can browse the complete list of Kuzzle Vault related commands in Kourou on Github.

 

Finally, you can also develop your own tools using the same cryptographic primitives.

If you are interested, you can take a look at the Cryptonomicon class of the kuzzle-vault package.

Closing words

Encryption is difficult, and it's even more complicated to implement it securely in a team development environment with continuous integration.

 

However, if it is managed correctly and easily, it's an undeniable advantage in facilitating the entire development and deployment process.

 

The tools described in this article are like Kuzzle and the rest of our projects: open source and freely usable.

Open source is even more important when it comes to cryptography because you have to trust programs to handle sensitive data.

 

You can take our word for it or even better, you can go and have a look at the code yourself ;-)

 

If you have any questions or you just want to discuss, you can join us on the Kuzzle official Discord

Adrien Maret

Related posts