Skip to content

Commit 527fc88

Browse files
committed
Update documentation and configuration for encryption bundle
- Enhanced the description in composer.json to better reflect the bundle's capabilities, including GDPR compliance and key rotation. - Updated README.md to clarify usage and features, emphasizing support for multiple encryption configurations and integration with Nowo\AnonymizedBundle. - Improved demo Makefile and entrypoint scripts to streamline key generation and environment variable handling. - Added support for environment variable-based encryption keys in configuration files, enhancing flexibility for users. - Updated various templates and forms to reflect changes in encryption handling and improve user experience.
1 parent 625dc09 commit 527fc88

64 files changed

Lines changed: 1261 additions & 229 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.symfony/recipe/nowo-tech/doctrine-encrypt-bundle/1.0/1.0/config/packages/nowo_doctrine_encrypt.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,6 @@ nowo_doctrine_encrypt:
99
default:
1010
encryptor_class: Halite # or Defuse (requires: composer require defuse/php-encryption ^2.1)
1111
secret_directory_path: '%kernel.project_dir%'
12+
# Optional: secret_key_filename: '.my_app.key' # custom key file name (only when using path)
13+
# Optional: secret_key_env_var: '%env(APP_ENCRYPT_KEY)%' # Symfony resolves at config load; do not set secret_directory_path; run generate-secret-key to get the key
1214
# Optional: add more configs (e.g. personal_data, financial_data) - see docs/CONFIGURATION.md

README.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22

33
[![CI](https://github.com/nowo-tech/DoctrineEncryptBundle/actions/workflows/ci.yml/badge.svg)](https://github.com/nowo-tech/DoctrineEncryptBundle/actions/workflows/ci.yml) [![Packagist Version](https://img.shields.io/packagist/v/nowo-tech/doctrine-encrypt-bundle.svg?style=flat)](https://packagist.org/packages/nowo-tech/doctrine-encrypt-bundle) [![Packagist Downloads](https://img.shields.io/packagist/dt/nowo-tech/doctrine-encrypt-bundle.svg)](https://packagist.org/packages/nowo-tech/doctrine-encrypt-bundle) [![License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) [![PHP](https://img.shields.io/badge/PHP-8.1%2B-777BB4?logo=php)](https://php.net) [![Symfony](https://img.shields.io/badge/Symfony-7%20%7C%208-000000?logo=symfony)](https://symfony.com) [![GitHub stars](https://img.shields.io/github/stars/nowo-tech/doctrine-encrypt-bundle.svg?style=social&label=Star)](https://github.com/nowo-tech/DoctrineEncryptBundle)
44

5-
> **Found this useful?** [Install from Packagist](https://packagist.org/packages/nowo-tech/doctrine-encrypt-bundle) · Give it a **star** on [GitHub](https://github.com/nowo-tech/DoctrineEncryptBundle) so more developers can find it.
5+
**Symfony bundle to encrypt Doctrine entity fields at rest** using [Halite](https://github.com/paragonie/halite) or [Defuse](https://github.com/defuse/php-encryption)—audited libraries, no custom crypto. For **Symfony 7 and 8** · PHP 8.1+. Suits **GDPR** and compliance (e.g. Art. 32); supports key rotation and [Nowo\AnonymizedBundle](https://github.com/nowo-tech/AnonymizedBundle) for anonymization and erasure.
66

7-
**Doctrine Encrypt Bundle** — Encrypt Doctrine entity fields with [Halite](https://github.com/paragonie/halite) or [Defuse](https://github.com/defuse/php-encryption). Uses verified, standardized libraries (no custom crypto). For Symfony 7 and 8 · PHP 8.1+.
7+
> **Found this useful?** [Install from Packagist](https://packagist.org/packages/nowo-tech/doctrine-encrypt-bundle) · Give it a **star** on [GitHub](https://github.com/nowo-tech/DoctrineEncryptBundle) so more developers can find it.
88
99
## Table of contents
1010

@@ -33,7 +33,8 @@ Looking for **Doctrine encryption**, **encrypt entity fields**, **Halite Symfony
3333
-**Twig filter** `|decrypt` — decrypt in templates; optional config argument: `{{ value|decrypt }}` or `{{ value|decrypt('financial_data') }}`
3434
- ✅ Works with **embedded entities** and **inheritance**
3535
- ✅ Console commands: status, generate secret key, encrypt/decrypt database
36-
-**Symfony Flex** recipe (register bundle + config; see [Recipe/](Recipe/README.md))
36+
-**Key rotation** — decrypt, replace keys, re-encrypt; combinable with [Nowo\AnonymizedBundle](https://github.com/nowo-tech/AnonymizedBundle) for GDPR-compliant anonymization and erasure
37+
-**Symfony Flex** recipe (register bundle + config; see [docs/INSTALLATION.md](docs/INSTALLATION.md))
3738
- ✅ Compatible with **Symfony 7 and 8** and **Doctrine ORM 2.x and 3.x**
3839

3940
## Installation
@@ -144,7 +145,7 @@ Values are encrypted on persist/update and decrypted on load. For **programmatic
144145
| [**Usage**](docs/USAGE.md) | Encrypted attribute, embedded entities, inheritance |
145146
| [**Example**](docs/EXAMPLE.md) | Full example: entity, fixtures, controller, template |
146147
| [**Commands**](docs/COMMANDS.md) | Status, generate key, encrypt/decrypt database |
147-
| [**Key rotation**](docs/KEY_ROTATION.md) | Strategy to change keys: backup, decrypt, replace keys, re-encrypt |
148+
| [**Key rotation**](docs/KEY_ROTATION.md) | Strategy to change keys: backup, decrypt, replace keys, re-encrypt. Supports GDPR compliance; combinable with Nowo\AnonymizedBundle. |
148149
| [**Demo**](docs/DEMO.md) | Demo projects (Symfony 7/8) and how to run them |
149150
| [**Changelog**](docs/CHANGELOG.md) | Version history |
150151
| [**Upgrading**](docs/UPGRADING.md) | Upgrade notes between versions |

composer.json

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,28 @@
11
{
22
"name": "nowo-tech/doctrine-encrypt-bundle",
3-
"description": "Encrypt Symfony 7|8 entity fields with Halite or Defuse (verified libraries).",
3+
"description": "Encrypt Doctrine entity fields at rest with Halite or Defuse. Symfony 7|8 bundle for field-level encryption, GDPR-friendly, multiple keys, key rotation.",
44
"type": "symfony-bundle",
55
"license": "MIT",
66
"keywords": [
77
"doctrine",
88
"symfony",
9-
"halite",
10-
"defuse",
9+
"symfony-bundle",
10+
"encryption",
1111
"encrypt",
1212
"decrypt",
13-
"entity"
13+
"halite",
14+
"defuse",
15+
"entity",
16+
"field-level encryption",
17+
"data-at-rest",
18+
"gdpr",
19+
"key rotation"
1420
],
1521
"homepage": "https://github.com/nowo-tech/DoctrineEncryptBundle",
1622
"support": {
1723
"issues": "https://github.com/nowo-tech/DoctrineEncryptBundle/issues",
1824
"source": "https://github.com/nowo-tech/DoctrineEncryptBundle",
19-
"docs": "https://github.com/nowo-tech/DoctrineEncryptBundle/tree/main/docs"
25+
"docs": "https://github.com/nowo-tech/DoctrineEncryptBundle/blob/master/docs/INSTALLATION.md"
2026
},
2127
"authors": [
2228
{

demo/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,12 @@ Luego abre en el navegador la URL que se indique (ej. `http://localhost:8008`).
3030
- **down** – Para los contenedores.
3131
- **build** – Reconstruye la imagen sin caché.
3232
- **install**`composer install` en el contenedor (usa el bundle desde `/var/doctrine-encrypt-bundle`).
33-
- **setup** – install + `doctrine:database:create` + `doctrine:schema:update` + `doctrine:encrypt:generate-secret-key`.
33+
- **setup** – install + `doctrine:database:create` + `doctrine:schema:update` + `doctrine:encrypt:generate-secret-key` (crea archivos de clave y añade `APP_ENCRYPT_KEY` a `.env` si no existe).
3434
- **shell** – Abre una shell en el contenedor PHP.
3535
- **logs** – Muestra los logs del contenedor.
3636
- **db-create** – Crea la base SQLite.
3737
- **db-schema** – Actualiza el schema Doctrine.
38-
- **key** – Genera la clave secreta de cifrado (Halite).
38+
- **key** – Genera claves: `personal_data` usa `APP_ENCRYPT_KEY` (se imprime y debe añadirse a `.env`); `financial_data` usa el archivo `.demo_financial.key`.
3939
- **cache-clear** – Limpia la caché de Symfony.
4040
- **update-bundle** – Actualiza el bundle desde el path montado y limpia caché.
4141
- **test** – Ejecuta los tests de la demo (si existen).

demo/symfony7/.env.example

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
APP_ENV=dev
22
APP_SECRET=change-me-in-production
33

4-
# Doctrine Encrypt Bundle: Halite | Defuse | Sodium | OpenSSL
5-
APP_ENCRYPTOR=Halite
4+
# Doctrine Encrypt Bundle (personal_data config; generated on first make up / entrypoint)
5+
APP_ENCRYPT_KEY=
66

77
###> doctrine/doctrine-bundle ###
88
DATABASE_URL="sqlite:///%kernel.project_dir%/var/data.db"

demo/symfony7/.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,5 @@
1717
.Halite.key
1818
.Defuse.key
1919
.Halite.*.key
20-
.Defuse.*.key
20+
.Defuse.*.key
21+
.demo_financial.key

demo/symfony7/Makefile

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ COMPOSE := docker-compose -f $(COMPOSE_FILE)
66
SERVICE_PHP := php
77

88
.PHONY: help up down build install shell logs setup db-create db-schema key fixtures cache-clear update-bundle test encrypt-status encrypt-database decrypt-database ensure-up
9-
.PHONY: encrypt-database-all decrypt-database-all encrypt-database-personal_data decrypt-database-personal_data encrypt-database-financial_data decrypt-database-financial_data
9+
.PHONY: encrypt-database-all decrypt-database-all encrypt-database-personal_data decrypt-database-personal_data encrypt-database-financial_data decrypt-database-financial_data encrypt-database-env_var decrypt-database-env_var
1010

1111
help:
1212
@echo "Doctrine Encrypt Bundle Demo - Symfony 7"
@@ -25,12 +25,14 @@ help:
2525
@echo " make encrypt-status List entities and encrypted properties"
2626
@echo " make encrypt-database Encrypt: all configs (interactive)"
2727
@echo " make encrypt-database-all Same: all configs"
28-
@echo " make encrypt-database-personal_data Encrypt: only config personal_data"
29-
@echo " make encrypt-database-financial_data Encrypt: only config financial_data"
28+
@echo " make encrypt-database-personal_data Encrypt: config personal_data (default path)"
29+
@echo " make encrypt-database-financial_data Encrypt: config financial_data (secret_key_filename)"
30+
@echo " make encrypt-database-env_var Encrypt: config env_var (%env(APP_ENCRYPT_KEY)%)"
3031
@echo " make decrypt-database Decrypt: all configs (interactive)"
3132
@echo " make decrypt-database-all Same: all configs"
32-
@echo " make decrypt-database-personal_data Decrypt: only config personal_data"
33-
@echo " make decrypt-database-financial_data Decrypt: only config financial_data"
33+
@echo " make decrypt-database-personal_data Decrypt: config personal_data"
34+
@echo " make decrypt-database-financial_data Decrypt: config financial_data"
35+
@echo " make decrypt-database-env_var Decrypt: config env_var"
3436
@echo " make cache-clear Clear Symfony cache"
3537
@echo " make update-bundle Update bundle from path repo"
3638
@echo " make test Run tests"
@@ -81,7 +83,7 @@ db-schema: ensure-up
8183

8284
key: ensure-up
8385
$(COMPOSE) exec -T $(SERVICE_PHP) php bin/console doctrine:encrypt:generate-secret-key 2>/dev/null || true
84-
@echo "Halite key for personal_data generated (or exists). Defuse creates .Defuse.financial_data.key on first use."
86+
@echo "Keys: personal_data = .Halite.personal_data.key; financial_data = .demo_financial.key; env_var = APP_ENCRYPT_KEY (.env). Add printed key to .env if APP_ENCRYPT_KEY is empty."
8587

8688
encrypt-status: ensure-up
8789
$(COMPOSE) exec -T $(SERVICE_PHP) php bin/console doctrine:encrypt:status
@@ -97,6 +99,9 @@ encrypt-database-personal_data: ensure-up
9799
encrypt-database-financial_data: ensure-up
98100
$(COMPOSE) exec $(SERVICE_PHP) php bin/console doctrine:encrypt:database financial_data
99101

102+
encrypt-database-env_var: ensure-up
103+
$(COMPOSE) exec $(SERVICE_PHP) php bin/console doctrine:encrypt:database env_var
104+
100105
# Decrypt: all configs (no config argument)
101106
decrypt-database decrypt-database-all: ensure-up
102107
$(COMPOSE) exec $(SERVICE_PHP) php bin/console doctrine:decrypt:database
@@ -108,6 +113,9 @@ decrypt-database-personal_data: ensure-up
108113
decrypt-database-financial_data: ensure-up
109114
$(COMPOSE) exec $(SERVICE_PHP) php bin/console doctrine:decrypt:database financial_data
110115

116+
decrypt-database-env_var: ensure-up
117+
$(COMPOSE) exec $(SERVICE_PHP) php bin/console doctrine:decrypt:database env_var
118+
111119
cache-clear: ensure-up
112120
$(COMPOSE) exec -T $(SERVICE_PHP) php bin/console cache:clear
113121

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,23 @@
1-
# Single encryptor (default) - uncomment to use only one encryptor:
2-
# nowo_doctrine_encrypt:
3-
# encryptor_class: Halite
4-
# secret_directory_path: '%kernel.project_dir%'
5-
6-
# Multiple encryptors (see docs/CONFIGURATION.md) - SecretMessage (default), SensitiveRecord (personal_data + financial_data)
1+
# Demo: three config variants
2+
# 1. default_path (personal_data): default key path, no secret_key_filename → .Halite.personal_data.key
3+
# 2. custom_filename (financial_data): custom secret_key_filename → .demo_financial.key
4+
# 3. env_var: key from environment; %env(APP_ENCRYPT_KEY)% is resolved by Symfony and the bundle receives the value
75
# Halite and Defuse (requires: composer require defuse/php-encryption ^2.1)
86
nowo_doctrine_encrypt:
97
default_config: personal_data
108
configs:
9+
# 1) No secret_key_filename: default path .Halite.personal_data.key
1110
personal_data:
1211
encryptor_class: Halite
1312
secret_directory_path: '%kernel.project_dir%'
13+
14+
# 2) With secret_key_filename: custom filename
1415
financial_data:
1516
encryptor_class: Defuse
1617
secret_directory_path: '%kernel.project_dir%'
18+
secret_key_filename: '.demo_financial.key'
19+
20+
# 3) Key from .env; Symfony resolves %env()% and the bundle receives the value
21+
env_var:
22+
encryptor_class: Halite
23+
secret_key_env_var: '%env(APP_ENCRYPT_KEY)%'

demo/symfony7/docker/entrypoint.sh

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,22 @@ if [ -d /app/vendor ]; then
1414
echo "📦 Creating database and schema if needed..."
1515
php /app/bin/console doctrine:database:create --if-not-exists --no-interaction 2>/dev/null || true
1616
php /app/bin/console doctrine:schema:update --force --no-interaction 2>/dev/null || true
17-
echo "📦 Generating encryption secret key if needed..."
18-
php /app/bin/console doctrine:encrypt:generate-secret-key 2>/dev/null || true
17+
if [ ! -f /app/.env ]; then
18+
cp /app/.env.example /app/.env 2>/dev/null || true
19+
fi
20+
echo "📦 Generating encryption keys (files + env)..."
21+
KEYGEN_OUT=$(php /app/bin/console doctrine:encrypt:generate-secret-key 2>/dev/null || true)
22+
echo "$KEYGEN_OUT"
23+
KEY=$(echo "$KEYGEN_OUT" | grep -E '^[a-f0-9]{100,}$' | head -1)
24+
if [ -n "$KEY" ] && ! grep -q '^APP_ENCRYPT_KEY=.' /app/.env 2>/dev/null; then
25+
echo "" >> /app/.env
26+
echo "# Doctrine Encrypt Bundle - key for personal_data (generated by doctrine:encrypt:generate-secret-key)" >> /app/.env
27+
echo "APP_ENCRYPT_KEY=$KEY" >> /app/.env
28+
echo "✅ APP_ENCRYPT_KEY added to .env"
29+
fi
1930
echo "📦 Loading fixtures..."
2031
php /app/bin/console doctrine:fixtures:load --no-interaction 2>/dev/null || true
21-
echo "✅ Database, key and fixtures ready."
32+
echo "✅ Database, keys and fixtures ready."
2233
fi
2334

2435
exec frankenphp run --config /etc/frankenphp/Caddyfile --adapter caddyfile

demo/symfony7/src/Controller/EncryptUtilDemoController.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,17 @@ public function index(EncryptUtil $encryptUtil): Response
2222
$encryptedDefault = $encryptUtil->encrypt($plainDefault);
2323
$decryptedDefault = $encryptUtil->decrypt($encryptedDefault);
2424

25-
// --- Config indicada: personal_data ---
25+
// --- Specified config: personal_data ---
2626
$plainPersonal = 'Secret with personal_data config';
2727
$encryptedPersonal = $encryptUtil->encrypt($plainPersonal, 'personal_data');
2828
$decryptedPersonal = $encryptUtil->decrypt($encryptedPersonal, 'personal_data');
2929

30-
// --- Config indicada: financial_data ---
30+
// --- Specified config: financial_data ---
3131
$plainFinancial = 'Secret with financial_data config';
3232
$encryptedFinancial = $encryptUtil->encrypt($plainFinancial, 'financial_data');
3333
$decryptedFinancial = $encryptUtil->decrypt($encryptedFinancial, 'financial_data');
3434

35-
// --- For Twig filter: default and config indicada (misma y distinta de la default) ---
35+
// --- For Twig filter: default and specified config (same and different from default) ---
3636
$encryptedForTwigDefault = $encryptUtil->encrypt('Decrypted in Twig with |decrypt (default)');
3737
$encryptedForTwigPersonal = $encryptUtil->encrypt('Decrypted with |decrypt(\'personal_data\')', 'personal_data');
3838
$encryptedForTwigFinancial = $encryptUtil->encrypt('Decrypted with |decrypt(\'financial_data\')', 'financial_data');

0 commit comments

Comments
 (0)