Loading repository data…
Loading repository data…
adrienkohlbecker / repository
ejson-kms is a utility for managing a collection of secrets in source control using AWS KMS.
A transparent discovery signal based on current public GitHub metadata.
This score does not audit code, security, maintainers, documentation quality, or suitability. Verify the repository and its current documentation before adoption.
ejson-kms is a utility for managing a collection of secrets in source control using AWS KMS.
The secrets are encrypted using secret-key cryptography (NaCl Secretbox: [XSalsa20][XSalsa20] + [Poly1305][Poly1305]), using key wrapping with a master key stored on HSM-backed storage at AWS. Encrypted secrets are stored in a JSON file that can easily be shared and versioned.
ejson-kms init --kms-key-id="alias/MyKMSKey"ejson-kms add secreteval "$(ejson-kms export)"Software systems often need access to some shared credential. For example, your web application needs access to a database password, or an API key for some third party service.
ejson-kms is a simple tool that provides secure credential storage using a JSON file stored and versioned with your project, while delegating the security of your credentials to AWS KMS.
The main benefits provided by ejson-kms are:
Secrets are stored in a JSON file with the following schema:
{
"kms_key_id": "arn:aws:kms:eu-west-1:000123456789:alias/ejson-kms",
"version": 1,
"encryption_context": {
"KEY": "VALUE"
},
"secrets": [
{
"name": "secret",
"description": "Nuclear launch codes",
"ciphertext": "EJK1;AQEDAHhZurRVk3ZWIqpympXccBmx1cOFJmQj8RBnIk01CJMnTAAAAH4wfAYJKoZIhvcNAQcGoG8wbQIBADBoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDCgMdhWkV5uphiD5DQIBEIA7kkXS7izLJ9X4x5spWTqWjLmSY/dtcQBeaXSlzcQA5Hqd+dvdMShqcEvd3RfUzZGR89qZYzrTsfybRA4=;4vukkc/Z8K9rSkex+s7XpphIIldqNcPJjhvhOixiq6RM7pMfijLMsvTNEyQKLw=="
}
]
}
AWS gives us the ability to store an arbitrary context with each secret, in the form of key-value pairs.
These key-value pairs are stored with the secret and are logged in CloudTrail for each encryption/decryption operation. You can use it for auditing purposes by adding, for example, the name of the project or the type of environment (production, staging, ...). Additionally, you can use it to further restrict access to your credentials with IAM policies.
Note: Since the context is stored with the secret and authenticated, it is read-only: once a secret has been encrypted, you cannot change the context.
SecretSecret[ejson][ejson] is the main inspiration for this project. ejson-kms is thus very similar but differs in a few ways:
ejson uses public-key cryptography with keys stored on the filesystem, ejson-kms uses secret-key cryptography, key wrapping and a master key stored on HSM-backed storage in AWS servers.ejson has a free-form file format, any kind of schema can be implemented since it will encrypt all json keys that do not start with a _. ejson-kms has a fixed schema.ejson encourages secrets to be written in plaintext on the filesystem during encryption (You first add the plaintext to the file, then encrypt it). ejson-kms never writes your secrets in plaintext anywhere.You can learn more about ejson in the write-up published on Shopify's blog here: https://engineering.shopify.com/79963908-secrets-at-shopify-introducing-ejson
[credstash][credstash] is the source of inspiration for ejson-kms's encryption workflow. It differs in a few ways:
credstash depends on DynamoDB for credential storage, ejson-kms uses the filesystem. Consequently, auditing and versioning protocols are very different.credstash is a python tool and has a few dependencies. ejson-kms is distributed as a single, statically-linked binary.You can learn more about credstash and KMS encryption here: https://blog.fugue.co/2015-04-21-aws-kms-secrets.html
[Ansible Vault][Ansible Vault] is a feature of Ansible designed to store secrets alongside playbooks. However, it uses whole-file encryption, meaning changes are not easily auditable and using git blame is impossible.
[Hashicorp Vault][Hashicorp Vault] is a tool designed to store secrets but also a number of features that are out of scope of ejson-kms such as certificate generation or AWS credentials management.
It is a complicated daemon you have to keep running in your infrastructure, as opposed to ejson-kms which you only have to install and use on the CLI.
ejson-kms as a binary has no dependencies.
It depends, however, on AWS KMS for cryptography.
Binaries for Linux, OSX and Windows are provided in the GitHub Releases page.
The binaries are signed using the GPG key C248DE6357445D6302F9A62E74BFD03C20CC21AF.
You can install ejson-kms on Linux with the following:
export EJSON_KMS_VERSION="4.2.0"
curl -Lo ejson-kms https://github.com/adrienkohlbecker/ejson-kms/releases/download/$EJSON_KMS_VERSION/ejson-kms-$EJSON_KMS_VERSION-linux-amd64
curl -Lo ejson-kms.asc https://github.com/adrienkohlbecker/ejson-kms/releases/download/$EJSON_KMS_VERSION/ejson-kms-$EJSON_KMS_VERSION-linux-amd64.asc
gpg --keyserver keyserver.ubuntu.com --recv-keys C248DE6357445D6302F9A62E74BFD03C20CC21AF
gpg --verify ejson-kms.asc
chmod +x ejson-kms
You can install ejson-kms using Homebrew:
brew install adrienkohlbecker/ejson-kms/ejson-kms
ejson-kms requires a working Go 1.6+ installation.
You can install ejson-kms from source with:
go get -u github.com/adrienkohlbecker/ejson-kms
Detailed usage instructions are available in the doc folder.
Create an empty secrets file with ejson-kms init --kms-key-id="alias/MyKMSKey".
./.secrets.json) with --path=my_secrets.json--encryption-context="key1=value1,key2=value2"Note: the encryption context is read-only. If you want to change it you will have to start over with an empty file. A facility to edit the context might be added to ejson-kms in the future (contributions welcome!)
Add a secret with ejson-kms add SECRET_NAME
ejson-kms will ask you to type the secret at runtime.echo "password" | ejson-kms add secret, but be mindful of your bash history if you do so.cat tls.key | ejson-kms add tls_key--description="Nuclear launch codes". Use it to describe what the secret is used for, how to rotate it...password, api_key, secret_123. Invalid names: Password, API KEY, 123-secret.Rotate the value of a secret with ejson-kms rotate SECRET_NAME
add commandTo rotate the KMS master key used in a secrets file, use ejson-kms rotate-kms-key NEW_KMS_KEY_ID.
Every secret will be decrypted with the old key, encrypted with the new key and the file will be overwritten.
To use your decrypted secrets, you can export them in a few formats with ejson-kms export --format=bash. The export will be output to standard out.
Currently there are four formats supported:
bash: SECRET='password' (name is capitalized, value as-is except escaping of ' with '')dotenv: SECRET="password" (name is capitalized, value uses escape sequences (\t, \n, \xFF, \u0100) for non-ASCII characters and non-printable characters)json: { "secret": "password" }yaml: secret: passwordTo use in a bash script, do the following:
#!/bin/bash
eval "$(ejson-kms export)"
echo "$SECRET"
ejson-kms will look for AWS credentials in the following locations and order:
AWS_ACCESS_KEY_ID or AWS_ACCESS_KEYAWS_SECRET_ACCESS_KEY or AWS_SECRET_KEYAWS_REGIONAWS_SESSION_TOKENAWS_SHARED_CREDENTIALS_FILE is set, this path will be used$HOME/.aws/credentials on Linux/OSX and %USERPROFILE%\.aws\credentials on WindowsAWS_PROFILE environment variable, otherwise it will use the default profile.AWS_SDK_LOAD_CONFIG=true, otherwise you need to set AWS_REGIONSee also the AWS SDK session documentation.
Below are the basic IAM policies needed to give access to ejson-kms to a user. More complex policies can be devised, especially using encryption contexts. Refer to the documentation of AWS KMS and IAM for more information.
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"kms:GenerateDataKey"
],
"Effect": "Allow",
"Resource": "arn:aws:kms:us-east-1:AWSACCOUNTID:key/KEY-GUID"
}
]
}