salakala v0.5.3
salakala šš
We've all been there, sharing .env
files in Slack to get an application working quickly while feeling bad about security practices. š«
But teams always have a shared secret or password manager, and you already have a way to access it through a CLI or service account, right?
What if you just had a nice little JSON file in your code repository that defined which environment variables to fetch from any manager through URIs?
// salakala.json
{
"DATABASE_URL": "op://application-secrets/db/url"
}
salakala does exactly that! It wraps around your manager and generates environment variables for you as .env
files or by setting variables directly in your environment.
Installation
# Install globally to use the CLI
npm install -g salakala
Usage
- Create a
salakala.json
file in your project (safe to commit to your repository!) - Run salakala to generate your
.env
file or set environment variables:
# Generate .env file in the current directory (default)
salakala
# Set environment variables in the current shell
salakala -s
# Specify an environment
salakala -e staging
# Specify a different output file
salakala -o .env.local
# Overwrite existing file instead of merging
salakala -w
# Show help
salakala --help
Examples
Flat structure (no environment specific secrets)
// salakala.json
{
"SECRET_ENV_VALUE": "op://application-secrets/test/test-section"
}
Nested structure (environment specific secrets)
// salakala.json
{
"development": {
"SECRET_ENV_VALUE": "op://application-secrets/test/test-section"
},
"staging": {
"SECRET_ENV_VALUE": "op://application-secrets/staging/test-section"
}
}
Using environment variables in secret paths
You can use environment variables in your secret paths using ${VARIABLE_NAME}
syntax:
// salakala.json
{
"development": {
"GCP_API_KEY": "gcsm://projects/${PROJECT_ID}/secrets/api-key/versions/latest"
}
}
The environment variables must of course be set before running:
PROJECT_ID=my-project salakala
Using non-secret values
You can also include regular, non-secret values. Any value that doesn't start with a provider prefix (like op://
, gcsm://
, etc.) will be passed through:
{
"development": {
"DB_PASSWORD": "op://vault/database/password",
"APP_NAME": "My Development App",
}
}
In this example:
DB_PASSWORD
will be fetched from the secret managerAPP_NAME
will be passed through directly to the generated environment variables
Providers
Uses the 1Password CLI to fetch secrets. Requires the op
CLI to be installed.
- ā Tested against a real 1Password account in CI
- š§āš» Interactive login via invoking
op
- š¤ Noninteractive login using environment variables
Format:
op://vault-name/item-name/[section-name/]field-name
Example:
op://Personal/AWS/access-key
Uses the Bitwarden CLI (bw
) to fetch secrets. Requires the bw
CLI to be installed. Supports different vault locations.
- ā Tested against a real Bitwarden account in CI
- š§āš» Interactive login via invoking
bw
- š¤ Noninteractive login using environment variables
Format:
bw://[folder]/item-name-or-id/field::json-key
Example: Plaintext field via item ID:
bw://1c9448b3-3d30-4f01-8d3c-3a4b8d14d00a/password
Example: Plaintext field via item name:
bw://my-folder/my-item/password
Example: JSON field via item name:
bw://my-folder/my-item/notes::foo.bar[1]
This expects that the item has a notes
field that is a JSON object. It will return the value of the foo.bar[1]
key.
Example: URI from a login item:
bw://my-folder/my-item/uris/0
This would get the first URI from the uris
field.
- ā Tested against a real KeePass database in CI
- š§āš» Interactive login via invoking
keepassxc-cli
- š¤ Noninteractive login using environment variables
Format:
kp://path/to/database.kdbx/entry-path/field
Example:
kp:///Users/me/secrets.kdbx/Web/GitHub/Password
Notes:
- To find field titles, you can use the
keepassxc-cli
command:keepassxc-cli show "/path/to/database.kdbx" "entry-name"
Fetches secrets from AWS Secrets Manager. Requires some form of AWS credentials to be configured. Uses the AWS SDK to fetch secrets.
- ā Tested against a real AWS account in CI
- š§āš» Semi-interactive login
- š¤ Noninteractive login using environment variables
Format:
awssm://region/secret-name[:key]
Example: Plaintext secret:
awssm://us-east-1/prod/api-key
Example: JSON object:
awssm://us-east-1/prod/database
This will fetch the entire JSON object in the database
secret and pass it through as a JSON string.
Example: Specific key in JSON object:
awssm://us-east-1/prod/database::password
This will fetch the password
key from the JSON object in the database
secret.
Fetches secrets from Google Cloud Secret Manager. Requires Google Cloud credentials to be configured. Uses the Google Cloud SDK to fetch secrets.
- ā Tested against a real Google Cloud project in CI
- š§āš» Semi-interactive login
- š¤ Noninteractive login using environment variables
Format:
gcsm://projects/project-id/secrets/secret-id/versions/version[:key]
Example: Plaintext secret:
gcsm://projects/my-project/secrets/api-key/versions/latest
Example: JSON object:
gcsm://projects/my-project/secrets/database/versions/latest
This will fetch the entire JSON object in the database
secret and pass it through as a JSON string.
Example: Specific key in JSON object:
gcsm://projects/my-project/secrets/database/versions/latest::password
This will fetch the password
key from the JSON object in the database
secret.
Uses the LastPass CLI to fetch secrets. Requires the lpass
CLI to be installed.
ā Needs testing
Format:
lp://group/item-name[/field]
Example:
lp://Personal/AWS/api-key
Fetches secrets from Azure Key Vault. Requires Azure credentials to be configured. Uses the Azure SDK to fetch secrets.
ā Needs testing
Format:
azurekv://vault-name.vault.azure.net/secret-name
Example:
azurekv://my-vault.vault.azure.net/database-password
Fetches secrets from HashiCorp Vault. Requires the VAULT_ADDR
and VAULT_TOKEN
environment variables to be set. Uses the HashiCorp Vault SDK to fetch secrets.
ā Needs testing
Format:
hcv://vault-address/secret/path
Example:
hcv://vault.example.com:8200/secret/data/database/credentials
Uses the Doppler CLI to fetch secrets. Requires the Doppler CLI to be installed.
ā Needs testing
Format:
doppler://project/config/secret-name
Example:
doppler://my-project/dev/DATABASE_URL
Uses the Infisical CLI to fetch secrets. Requires the Infisical CLI to be installed.
ā Needs testing
Format:
inf://workspace/environment/secret-name
Example:
inf://my-project/dev/DATABASE_URL
Recommendations
- ā
DO commit
salakala.json
- it should only contain paths to secrets, not the secrets themselves - ā DON'T commit generated
.env
files - Add
.env*
to your.gitignore
Contributing
Contributions are welcome! Feel free to submit issues and pull requests.
License
MIT