Skip to content

Commit

Permalink
Release v0.3.0
Browse files Browse the repository at this point in the history
Release v0.3.0
  • Loading branch information
Veinar authored Dec 4, 2024
2 parents 5fdc3d1 + 3a07ac4 commit c959ae8
Show file tree
Hide file tree
Showing 34 changed files with 787 additions and 182 deletions.
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

0 comments on commit c959ae8

Please sign in to comment.