About one month ago, I wrote a small Python script to securely manage secret data in my Git repositories. I believe this tool is very convenient and useful for many projects beyond just my personal use cases.
I named the script keepsecret.py and published it on my Github account.
In this article, I will explain what keepsecret.py is and how to use it.
Background: Seeking a simple way to manage secrets
I am a software engineer specializing in server-side application development. These applications often require sensitive data such as database passwords, API keys, etc. Dotenv (.env) is a well-known method for configuring this sensitive data in a plain text file. Generally, you should not commit the .env file to your Git repository to avoid accidentally exposing it to the internet. So, how should I store the .env file and secret data?
We have several methods to ensure security. I think the most secure approach is to use dedicated tools or services, such as GCP Secret Manager or HashiCorp Vault.
However, it is too complicated for my personal projects. I donβt want my tiny web applications to depend on additional services.
Another practical approach is to encrypt files and store them in your Git repository. Tools like git-secret or git-crypt are available for this purpose.
However, these tools require familiarity with GPG and are tightly integrated with Git, which I find too complex. I prefer a simpler way to encrypt files.
That is why I created keepsecret.py
.
What is keepsecret.py
keepsecret.py is a command line tool written in Python. It focuses just on encrypting and decrypting files without unnecessary complexity.
To use keepsecret.py, you need the following two dependencies:
- Python 3.11 or later
- age
These are available on most platforms and can be installed easily. For example, if you are using a Mac, you can install them via Homebrew as follows:
brew install python3
brew install age
keepsecret.py is implemented as a single file Python script. You can use it by simply downloading it and making the file executable.
curl -O https://raw.githubusercontent.com/kohkimakimoto/keepsecret/main/keepsecret.py && chmod +x keepsecret.py
You are now ready to use it.
How to use keepsecret.py
Before using keepsecret.py, you must have both the public and private keys for age, which is a modern file encryption tool.
I prefer age over GPG due to its simplicity. Unlike GPG, age does not dictate where private keys should be stored. The tool is straightforward to use: you simply run the age command with the keys and file paths to encrypt files.
You can generate a private and public key pair by running the following command:
# age-keygen is bundled with age installation.
age-keygen
This command will generate a key pair as shown below.
# created: 2024-04-07T14:41:45+09:00
# public key: age1d9huzvucvm7hueyz0ck90gkyxuqyzvqepx594nfhzzfv2tk60yysdf2l09
AGE-SECRET-KEY-1VGYZM79EQPV80CRMKTQHFN4GD6X7UMY7KJ8LYTG3S5EVGUXW7T5S9JRS6Z
Encrypt files
You can encrypt files (for example: file1.txt
, file2.txt
) with the following command:
keepsecret.py encrypt -r age1d9...(age-public-key)... -- file1.txt file2.txt
This command will generate encrypted files file1.txt.encrypted
, file2.txt.encrypted
. keepsecret.py adds a .encrypted
extension to generate encrypted versions of the files.
Decrypt files
You can decrypt files (for example: file1.txt.encrypted
, file2.txt.encrypted
) with the following command:
keepsecret.py decrypt -- file1.txt.encrypted file2.txt.encrypted
This command prompts you to input your private key like the following:
Input private key content:
After inputting the correct private key, keepsecret.py will generate decrypted files file1.txt
, file2.txt
. keepsecret.py removes a .encrypted
extension to restore the files to their original form.
Organize secrets using a configuration file
You now have the simplest method available for encrypting and decrypting files. For more practical use cases, keepsecret.py organizes multiple secret files using a configuration file.
The configuration file is named keepsecret.toml
. Check the following example:
# You can create separate sections for different environments.
[development]
force = true
# The development secret files can be decrypted using the development private keys.
recipients = [
"age1d9...(public-key-for-development-engineer1)...",
"age1d9...(public-key-for-development-engineer2)...",
]
# Secret files for the development environment.
# Ensure to include them in .gitignore
files = [
".env.development",
".env.testing",
]
[production]
force = true
# The production secret files can only be decrypted using the production private key.
recipients = [
"age1d9...(public-key-for-production)...",
]
# Secret files for the production environment.
# Ensure to include them in .gitignore
files = [
".env.production",
]
The above configuration file manages secret files for the environments (development
and production
).
The development
secret files are encrypted with multiple keys. These keys are provided by engineers working on the project. This allows the engineers to use these secret files in their development.
In contrast, the production
secret files can only be decrypted with a single, specific production private key.
Access to this production key should be restricted. For example, the key is used exclusively with tools like Github Actions Secrets.
You can encrypt and decrypt the files by specifying the section with the -s
, --section
option:
# Ensure `keepsecret.toml` is in your current working directory.
# Encrypt the files in development environment.
keepsecret.py encrypt -s development
# Decrypt the files in development environment.
keepsecret.py decrypt -s development
Conclusion
I developed a CLI tool for managing secret files in Git repositories. Security often requires balancing convenience with constraints. While it may not be the perfect solution, it provides a practical method for handling sensitive data in your projects.
If you're interested, please give it a try!
Top comments (0)