A robust Symfony 8.1 prototype for handling highly sensitive data under SOC 2 compliance. This project demonstrates Envelope Encryption for data protection and Audit Trail Isolation for immutable, separated security logging.
- Envelope Encryption:
- DEK (Data Encryption Key): Unique AES-256-GCM symmetric key per document.
- KEK (Key Encrypting Key): Asymmetric RSA (2048-bit) keys per user.
- Server Backup: DEKs are also encrypted with a Server Master Key for automated backups and administrative auditability.
- Key Management Service (KMS):
- Isolated Key Store: Master keys are stored in a third dedicated database (
keys.db). - Root Key Encryption: All master keys in the database are themselves encrypted with a
ROOT_KEYfrom the environment. - Automatic Rotation: Supports defining active periods for master keys. New documents use the currently active key, while historical documents automatically select their original key for decryption via Key ID mapping.
- Master Key Sharding: Maintains a pool of 10 active master keys. The system load-balances encryption across this pool using a millisecond-precision selection algorithm, significantly reducing the "blast radius" of any single key compromise.
- Isolated Key Store: Master keys are stored in a third dedicated database (
- Audit Trail Isolation:
- Dual-Database Setup: Primary data is stored in
data.db, while immutable audit logs are moved to a physically separateaudit.db. - Asynchronous Mover: Uses Symfony Messenger with the Outbox Pattern. Logs are captured during the primary transaction and dispatched to a background worker to ensure high availability and performance.
- Dual-Database Setup: Primary data is stored in
- Granular Access Control:
- Logical Isolation: Symfony Voters ensure users only interact with documents they own or have shared access to.
- Repository Isolation: SQL-level filtering to prevent accidental data leakage.
graph TD
User[User Session] -->|Private Key| Controller
Controller -->|Verify Access| Voter
Voter -->|Check Shares| DB_Primary[(Primary DB: data.db)]
subgraph Encryption
Manager[DocumentManager] -->|AES-256-GCM| EncryptedDoc
Manager -->|RSA Wrap| Envelope
end
subgraph Audit_Isolation
DefaultEM[Primary EM] -->|onFlush| Loggable[Gedmo Loggable]
Loggable -->|Scheduled| DefaultEM
Mover[AuditLogMover] -->|Dispatch| Bus[Messenger Bus]
Bus -->|Outbox| PrimaryDB[(Primary DB: messenger_messages)]
Worker[Messenger Worker] -->|Consume| Bus
Worker -->|Persist| AuditEM[Audit EM]
AuditEM -->|Save| DB_Audit[(Audit DB: audit.db)]
Mover -->|Remove| DB_Primary
end
- PHP 8.4+
- OpenSSL extension enabled
- SQLite3
- Composer
-
Clone the repository:
git clone https://github.com/mattleads/SOC2Database.git cd SOC2Database -
Install dependencies:
composer install
-
Configure Environment: Generate a 64-character hex root key and add it to your
.envor.env.local:# Generate key php -r "echo bin2hex(random_bytes(32));" # Add to .env ROOT_KEY=your_generated_hex_key
-
Initialize Databases & Transport:
php bin/console doctrine:schema:create --em=default php bin/console doctrine:schema:create --em=audit php bin/console doctrine:schema:create --em=keys php bin/console messenger:setup-transports
-
Run the Messenger Worker (in a separate terminal or for testing):
php bin/console messenger:consume audit_async
Run the built-in verification command to simulate creating users, encrypting a document, sharing it, and verifying the audit trail isolation.
php bin/console app:verify-encryptionThe DocumentManager handles all the complex cryptographic "math" for you.
public function view(Document $document, DocumentManager $documentManager, Request $request): Response
{
// Retrieve the user's private key (e.g., from a secure session vault)
$userPrivateKey = $request->getSession()->get('user_private_key');
// Decrypt the content using the Envelope pattern
$plainText = $documentManager->readDocumentContent(
$document,
$this->getUser(),
$userPrivateKey
);
return new Response($plainText);
}- Private Key Management: In this prototype, the private key is expected to be provided during the session. In a production SOC 2 environment, consider using a Hardware Security Module (HSM) or a dedicated Key Management Service (KMS) like AWS KMS or HashiCorp Vault.
- Audit Log Access: The
audit.dbshould ideally have stricter file-system permissions than the primary database.
This project is open-sourced under the MIT license.