Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release v0.3.0 #64

Merged
merged 33 commits into from
Dec 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
054822d
Added GIF to represent how envcloak works in mian README.md
Veinar Nov 29, 2024
083537b
Remove unwanted debug from encrypt
Veinar Nov 29, 2024
51dd0bb
CHANGELOG v0.2.2
Veinar Nov 29, 2024
d89988d
Changed version origin for --version command #52
Veinar Nov 29, 2024
48a0b90
Merge pull request #57 from Veinar/chore/version_handling
Veinar Nov 29, 2024
3a96e75
Added possibility to not specify output when encrypting single file
Veinar Nov 30, 2024
4c1f788
Merge
Veinar Nov 30, 2024
2ec7aa3
Merge pull request #58 from Veinar/feature/no_output
Veinar Nov 30, 2024
53151f6
Add --preview flag for encryptor
Veinar Nov 30, 2024
7fa5bff
Merge pull request #59 from Veinar/feature/preview
Veinar Nov 30, 2024
9fd7ec8
Update README to include `--preview` option
Veinar Nov 30, 2024
a96b390
Minor fix with debug output
Veinar Nov 30, 2024
b5980cc
New badge + minor fixes
Veinar Nov 30, 2024
0b82877
Applied correct black formatting
Veinar Dec 3, 2024
c0dce35
Implemented preview
Veinar Dec 3, 2024
109a18c
Merge pull request #61 from Veinar/feature/preview_rotation
Veinar Dec 3, 2024
3a4a4b3
Fixed encrypt
Veinar Dec 3, 2024
3818297
Refactored decrypt
Veinar Dec 3, 2024
3ab68ba
Refactored decrypt - apply black formatting
Veinar Dec 3, 2024
a3237c1
Remove rendundancy 1
Veinar Dec 3, 2024
3410181
Added module docstrings + further refactor
Veinar Dec 3, 2024
338d684
Added module docstrings + further refactor + black format
Veinar Dec 3, 2024
856c443
More docstrings
Veinar Dec 3, 2024
be845ee
Renamed recursion to recursion_option in decorators
Veinar Dec 3, 2024
47d8725
More docstrings 2
Veinar Dec 3, 2024
d468b4b
More docstrings 2 + black formatting
Veinar Dec 3, 2024
3cfdd7a
Minor fixes of imports
Veinar Dec 3, 2024
478640d
Merge pull request #62 from Veinar/chore/refactor
Veinar Dec 3, 2024
5e17597
Added KMS integration guidelines
Veinar Dec 4, 2024
210a2b2
Feature/secure random value generation (#63)
BavyaMittal Dec 4, 2024
1991d7c
Release v0.3.0
Veinar Dec 4, 2024
757a58d
Minor fix in README.md
Veinar Dec 4, 2024
3a07ac4
Minor fix in README.md 2
Veinar Dec 4, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,5 +1,23 @@
# CHANGELOG for EnvCloak

## *[0.3.0]* - xxxx-xx-xx
### Added
- **Information about versatility.**
- Added possibility to not specify output when encrypting single file (using original name with `.enc` suffix).
- Added `--preview` flag for encrypt and decrypt command.
- Introduced `SECURITY.md` policy with guidelines how to securely use this tool.
- Added guidelines for integrating with popular cloud KMS.

### Changed
- Code refactor to modularize logic.
- Increased randomness when generating salt by introducing `secure` package. (Thanks to @BavyaMittal)
- Applied module docstrings

## *[0.2.2]* - 2024-11-29
### Changed

- Fix critical error with `packaging` not declared in dependencies list.

## *[0.2.1]* & *[0.2.0]* - 2024-11-27
> First of Beta release
### Added
Expand Down
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,21 @@
<img src="https://veinar.pl/envcloak.png" alt="logo" width="350"/>
</p>

<p align="center" style="background-color:#FF0000; color:white; padding:10px; border-radius:8px; font-size:14px; line-height:1.5;">
⚠️ <strong>IMPORTANT NOTE: EnvCloak is NOT Limited to .env Files!</strong>⚠️<br>
EnvCloak was originally built to secure <b>.env</b> files, but it can encrypt and decrypt <strong>any file type</strong>.<br>
Use it for <i>.json</i>, <i>.yaml</i>, <i>.txt</i>, <i>binary files</i>, or <i>any sensitive data.</i><br>
<br>
<span style="font-style:italic;">The name may be misleading, but the tool is far more versatile than it suggests!</span>
</p>

# 🔒 EnvCloak

> "Because Your Secrets Deserve Better Than Plaintext!"

![GitHub License](https://img.shields.io/github/license/Veinar/envcloak)
![Contrib Welcome](https://img.shields.io/badge/contributions-welcome-blue)
![Looking for](https://img.shields.io/badge/looking%20for-maintainers-228B22)
![Code style](https://img.shields.io/badge/code%20style-black-black)
![CI/CD Pipeline](https://github.com/Veinar/envcloak/actions/workflows/test.yaml/badge.svg)
![Build Pipeline](https://github.com/Veinar/envcloak/actions/workflows/build.yaml/badge.svg)
Expand Down Expand Up @@ -57,6 +66,9 @@ envcloak generate-key-from-password --password "YourTopSecretPassword" --output
# From random password and salt
envcloak generate-key --output secretkey.key
```

![generate-key-gif](https://veinar.pl/envcloak-generate-key.gif)

> **What it does:** generates your private key used to encrypt and decrypt files. **Appends (or creates if needed) .gitignore as well** as super-hero should! 🎉

> ⚠ **If someone knows your password and salt (option 1) can recreate same `key` - keep those variables safe as `key` itself** ⚠
Expand All @@ -66,13 +78,19 @@ envcloak generate-key --output secretkey.key
```bash
envcloak encrypt --input .env --output .env.enc --key-file mykey.key
```

![encrypt-gif](https://veinar.pl/envcloak-encrypt.gif)

> **What it does:** Encrypts your `.env` file with a specified key, outputting a sparkling `.env.enc` file.

### Decrypting Variables:

```bash
envcloak decrypt --input .env.enc --output .env --key-file mykey.key
```

![decrypt-gif](https://veinar.pl/envcloak-decrypt.gif)

> **What it does:** Decrypts the `.env.enc` file back to `.env` using the same key. Voilà!

or you may want to use it ...
Expand Down Expand Up @@ -105,6 +123,7 @@ load_encrypted_env('.env.enc', key_file='mykey.key').to_os_env()
* Works with directories using `--directory` instead of `--input` on `encrypt` and `decrypt`.
> ℹ️ EnvCloak process files in batch one-by-one.
* Can [recursively](docs/recursive.md) encrypt or decrypt directories.
* Can list files in directory that will be encrypted using `--preview` flag (ℹ️ only for directories and it does not commit the operation!).

🚦 Error Handling

Expand Down
95 changes: 95 additions & 0 deletions SECURITY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
# ⛨ Security Policy

This document outlines the security policies and practices for the **EnvCloak** project, ensuring the tool is secure and reliable for managing encrypted environment variables.

## 🔩 Supported Versions

The following table indicates the versions of **EnvCloak** currently supported with security updates:

| Version | Supported |
|-----------|--------------------|
| > 0.3 | :white_check_mark: |
| ≤ 0.3 | :x: |

## 🚨 Reporting a Vulnerability

If you discover a security vulnerability in **EnvCloak**, please report it to the project author.
Or create issue describing what is wrong.

## ℹ️ Known Security Risks

### 1. Key Storage in Plaintext
- **Risk**: Keys are stored as plaintext files (e.g., `.key` extension) and may be exposed if file permissions are weak or the file is mishandled.
- **Mitigation**:
- Store key files in secure locations with restricted permissions (`chmod 600` recommended).
- Use secure directories or storage solutions (e.g., encrypted storage or key management services).
- Avoid committing key files to version control systems.

### 2. Tampering with Encrypted Files
- **Risk**: Encrypted files could be tampered with, leading to undetected data corruption or malicious injection.
- **Mitigation**:
- **EnvCloak** implements a double SHA-3 verification:
1. A SHA-3 hash is generated for the encrypted file.
2. A second SHA-3 hash is generated from the content of the file during encryption.
- **EnvCloak will not decrypt files if SHA validation fails**, ensuring file integrity. To bypass this validation, users must explicitly use the `--skip-sha-validation` flag.
- Use the `envcloak compare` command to verify file integrity.

### 3. Improper Key Rotation
- **Risk**: Key rotation errors could lead to data being unrecoverable or inconsistencies between environments.
- **Mitigation**:
- Use the `--dry-run` option during key rotation to preview changes before applying them.
- Backup all encrypted files before initiating key rotation.

### 4. Key Recreation via Password and Salt
- **Risk**: If a key is generated using a password and salt, the same key can be recreated if both the password and salt are known.
- **Mitigation**:
- Use sufficiently long and unique passwords.
- Avoid using predictable or commonly reused salts.
- Consider generating random keys without relying on passwords when possible.

### 5. Directory Encryption Risks
- **Risk**: Encrypting entire directories without care may include unintended sensitive or system-critical files.
- **Mitigation**:
- Use the `--preview` option to list files before encryption.
- Avoid running **EnvCloak** on system-critical paths without reviewing the target files.

### 6. Unauthorized Access
- **Risk**: Weak file permissions or mishandled decryption keys could expose sensitive data to unauthorized users.
- **Mitigation**:
- Ensure encrypted files are stored with restricted access (`chmod 600` recommended).
- Do not store decrypted files or plaintext keys in accessible locations.

### 7. Outdated Algorithms
- **Risk**: Encryption algorithms used by **EnvCloak** may become outdated or insecure over time.
- **Mitigation**:
- **EnvCloak** currently uses **AES-256**, a widely trusted encryption standard.
- Regular audits will ensure algorithms remain up-to-date with industry standards.
- A migration mechanism will be provided if future updates require transitioning to a new algorithm.

## 🦑 Best Practices for Secure Usage

1. **Key Management**:
- Store key files securely, with restricted access (`chmod 600`).
- Use extensions like `.key` to clearly differentiate key files from other files.
- Rotate keys periodically using the `envcloak rotate` command.

2. **Environment File Handling**:
- Do not store plaintext `.env` files in version control systems.
- Encrypt sensitive `.env` files using the `envcloak encrypt` command.

3. **File Permissions**:
- Restrict access to encrypted files (`chmod 600` on Linux systems).
- Ensure only authorized users have access to the decryption key.

4. **Tamper Detection**:
- Leverage the double SHA-3 verification feature to detect unauthorized changes to encrypted files.
- Be cautious when using `--skip-sha-validation`, as this bypasses integrity checks.

5. **Integration Security**:
- Pass sensitive keys or data via environment variables in CI/CD pipelines.
- Avoid logging sensitive data during encryption or decryption processes.

## Contact

For any security-related concerns or questions, please contact the project author via the email address listed on their [GitHub profile](https://github.com/Veinar) or Package (pypi) site https://pypi.org/project/envcloak/.
We appreciate your support in keeping **EnvCloak** secure for everyone. 🥳
2 changes: 1 addition & 1 deletion envcloak/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from .loader import load_encrypted_env

__version__ = "0.2.2"
__version__ = "0.3.0"
__all__ = ["load_encrypted_env"]
10 changes: 9 additions & 1 deletion envcloak/cli.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
"""
cli.py

This module defines the command-line interface for interacting with the `envcloak` package.
It provides commands for encrypting, decrypting, and managing environment variables.
"""

import click
from envcloak.commands.encrypt import encrypt
from envcloak.commands.decrypt import decrypt
Expand All @@ -6,13 +13,14 @@
from envcloak.commands.rotate_keys import rotate_keys
from envcloak.commands.compare import compare
from envcloak.version_check import warn_if_outdated
from envcloak import __version__

# Warn About Outdated Versions
warn_if_outdated()


@click.group()
@click.version_option(prog_name="EnvCloak")
@click.version_option(version=__version__, prog_name="EnvCloak")
def main():
"""
EnvCloak: Securely manage encrypted environment variables.
Expand Down
6 changes: 6 additions & 0 deletions envcloak/commands/compare.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
"""
compare.py

This module provides logic for compare command of EnvCloak
"""

import click
from click import style
from envcloak.comparator import compare_files_or_directories
Expand Down
91 changes: 44 additions & 47 deletions envcloak/commands/decrypt.py
Original file line number Diff line number Diff line change
@@ -1,28 +1,38 @@
import os
import shutil
from pathlib import Path
"""
decrypt.py

This module provides logic for decrypt command of EnvCloak
"""

import click
from click import style
from envcloak.utils import debug_log, calculate_required_space
from envcloak.utils import (
debug_log,
calculate_required_space,
list_files_to_encrypt,
read_key_file,
)
from envcloak.handlers import (
handle_directory_preview,
handle_overwrite,
handle_common_exceptions,
)
from envcloak.decorators.common_decorators import (
debug_option,
dry_run_option,
force_option,
no_sha_validation_option,
recursion,
recursion_option,
preview_option,
)
from envcloak.validation import (
check_file_exists,
check_directory_exists,
check_directory_not_empty,
check_output_not_exists,
check_permissions,
check_disk_space,
)
from envcloak.encryptor import decrypt_file, traverse_and_process_files
from envcloak.exceptions import (
OutputFileExistsException,
DiskSpaceException,
FileDecryptionException,
)

Expand All @@ -32,7 +42,8 @@
@dry_run_option
@force_option
@no_sha_validation_option
@recursion
@recursion_option
@preview_option
@click.option(
"--input",
"-i",
Expand Down Expand Up @@ -64,21 +75,29 @@ def decrypt(
debug,
skip_sha_validation,
recursion,
preview,
):
"""
Decrypt environment variables from a file or all files in a directory.
"""
try:
debug_log("Debug mode is enabled", debug)

# Always perform validation
debug_log("Debug: Validating input and directory parameters.", debug)
if not input and not directory:
raise click.UsageError("You must provide either --input or --directory.")
if input and directory:
raise click.UsageError(
"You must provide either --input or --directory, not both."
)

if directory and preview:
handle_directory_preview(directory, recursion, debug, list_files_to_encrypt)
return

debug_log(f"Debug: Validating key file {key_file}.", debug)
check_file_exists(key_file)
check_permissions(key_file)

if input:
debug_log(f"Debug: Validating input file {input}.", debug)
check_file_exists(input)
Expand All @@ -87,32 +106,8 @@ def decrypt(
debug_log(f"Debug: Validating directory {directory}.", debug)
check_directory_exists(directory)
check_directory_not_empty(directory)
debug_log(f"Debug: Validating key file {key_file}.", debug)
check_file_exists(key_file)
check_permissions(key_file)

# Handle overwrite with --force
debug_log("Debug: Handling overwrite logic with force flag.", debug)
if not force:
check_output_not_exists(output)
else:
if os.path.exists(output):
debug_log(
f"Debug: Existing file or directory found at {output}. Overwriting due to --force.",
debug,
)
click.echo(
style(
f"⚠️ Warning: Overwriting existing file or directory {output} (--force used).",
fg="yellow",
)
)
if os.path.isdir(output):
debug_log(f"Debug: Removing existing directory {output}.", debug)
shutil.rmtree(output) # Remove existing directory
else:
debug_log(f"Debug: Removing existing file {output}.", debug)
os.remove(output) # Remove existing file
handle_overwrite(output, force, debug)

debug_log(
f"Debug: Calculating required space for input {input} or directory {directory}.",
Expand All @@ -126,10 +121,7 @@ def decrypt(
click.echo("Dry-run checks passed successfully.")
return

# Actual decryption logic
with open(key_file, "rb") as kf:
key = kf.read()
debug_log(f"Debug: Key file {key_file} read successfully.", debug)
key = read_key_file(key_file, debug)

if input:
debug_log(
Expand All @@ -139,6 +131,7 @@ def decrypt(
decrypt_file(input, output, key, validate_integrity=not skip_sha_validation)
click.echo(f"File {input} decrypted -> {output} using key {key_file}")
elif directory:
debug_log(f"Debug: Decrypting files in directory {directory}.", debug)
traverse_and_process_files(
directory,
output,
Expand All @@ -154,9 +147,13 @@ def decrypt(
recursion=recursion,
)
click.echo(f"All files in directory {directory} decrypted -> {output}")
except (
OutputFileExistsException,
DiskSpaceException,
FileDecryptionException,
) as e:
click.echo(f"Error during decryption: {str(e)}")
except FileDecryptionException as e:
click.echo(
f"Error during decryption: Error: Failed to decrypt the file.\nDetails: {e.details}",
err=True,
)
except click.UsageError as e:
click.echo(f"Usage Error: {e}", err=True)
except Exception as e:
handle_common_exceptions(e, debug)
raise
Loading
Loading