Expand description
(r)EJSON
rejson
is a utility for managing a collection of secrets in source control. The secrets are encrypted using
public key, elliptic curve cryptography (NaCl Box: Curve25519 + Salsa20 + Poly1305-AES). Secrets are
collected in a JSON file, in which all the string values are encrypted. Public keys are embedded in the file, and
the decrypter looks up the corresponding private key from its local filesystem.
This is a rust port of EJSON with a few extra bells and whistles. Full credit should go to the team that made EJSON. No innovation here other than needing Rust bindings and wanting a few extra features I’m not sure belonged upstream.
Install
From Releases
curl -fsSL https://github.com/pseudomuto/rejson/releases/download/v0.2.0/rejson_0.2.0_$(uname -s)_$(uname -m).tar.gz | tar xzf -
With Cargo
cargo install rejson
Since this is a drop-in replacement for ejson
you can add alias ejson="rejson"
if you like. The expectation is that
this is 100% compatible with ejson
and it only additive. If that’s not the case, it’s a bug, and I’d appreciate you
filing an issue.
Additions to EJSON
- A
--strip-key
flag ondecrypt
which will remove_public_key
from the result. env
command which will export all keys under the top-levelenvironment
key.kube-secrets
command which will output K8s secret manifests for values under thekubernetes
key.
Usage
CLI
See rejson -h
or (cargo run -- -h
) for usage details.
A command line utility for managing secrets
Usage: rejson <COMMAND>
Commands:
encrypt Encrypt one or more EJSON files
decrypt Decrypt an EJSON file
keygen Generate a new EJSON key pair
env Export the all scalar values under the "environment" key
help Print this message or the help of the given subcommand(s)
Options:
-h, --help Print help
-V, --version Print version
To export all environment values in the environment key, run eval $(rejson env secrets.ejson)
.
{
"_public_key": "...",
"environment": {
"SOME_KEY": "SOME_VALUE"
}
}
Docker
A docker image is published for each release of rEJSON. Usage is similar to using the binary, only the /keys
and
/files
volumes are required for encrypt/decrypt functionality.
docker run --rm -it rejson keygen
docker run --rm -it \
-v $(pwd)/keys:/keys \
-v $(pwd)/secrets:/files \
rejson encrypt /files/secrets.ejson
docker run --rm -it \
-v $(pwd)/keys:/keys \
-v $(pwd)/secrets:/files \
rejson decrypt /files/secrets.ejson
Code
use std::fs;
use rejson::{KeyPair, SecretsFile};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let file = "examples/data/secrets.ejson";
let mut secrets_file = SecretsFile::load(file).expect("failed to load file");
secrets_file.transform(rejson::compact()?)?;
secrets_file.transform(rejson::encrypt(&secrets_file)?)?;
let json = secrets_file.to_string();
let data = json.as_bytes();
fs::write(file, data)?;
println!("Wrote {} bytes to {}", data.len(), file);
Ok(())
}
See the examples directory for more.
Development
Local Setup
- Make sure you have the nightly toolchain (used for rustfmt only)
- Add pre-commit to avoid committing malformatted code
ln -sf ../../build/pre-commit .git/hooks/pre-commit
Cutting a New release
Run build/release <new_version>
. This will:
- Update version in Cargo.toml
- Create a new commit with the message “Release v
” git tag -sm "Release v<version" v<version>
git push --tags
Once the release pipeline has finished and published the crate, run the following to create the GitHub release with attached binaries, etc.
goreleaser release --clean
Yes, I’ve hacked goreleaser into thinking this is a go project so I can leverage it for running cross, publishing docker images, and setting up GitHub releases.
Structs
- A newtype representing an encryption key (32-byte array)
- A struct representing a Curve25519 key pair (public and private).
- A wrapper around a map of dot-delimited keys and values that can be converted into a Kubernetes manifest of secrets.
- SecretsMap is a flattened map of secrets, tpically loaded from a EJSON/JSON file. The values are not decrypted here, unless that was done before loading.
Functions
- Returns a transform function that compacts multiline strings into single lines with line break characters. This is useful when adding something like a service account in the EJSON file and having the encrypt function compact it before encryption.
- Returns a transform that will decrypt incoming values from the supplied secrets file. This is done by creating a KeyPair consisting of the public key from the file and the supplied private key.
- Returns a transform function for use with SecretsFile::transform that will encrypt all eligible values (that aren’t already encrypted).
- Loads the private key from disk, searching for a file named as the public key defined in the secrets file.