Skip to content

Repository files navigation

AEGIS - PII Privacy Vault

A PII Data Privacy Vault REST API built in Go. Instead of storing raw sensitive data (emails, phone numbers, card numbers) in your application database, you send them to AEGIS, get back an opaque token, and store that token. Only authorized roles can retrieve the real data — and every access is logged.


Architecture

AEGIS Architecture


Quickstart

cp .env.example .env
# Edit .env: set JWT_SECRET (32+ chars) and VAULT_MASTER_KEY (exactly 32 chars)

docker-compose up --build

That's it. Postgres starts, migrations run, API is live at http://localhost:8080.


Usage

Full step-by-step guide with curl examples for every endpoint → docs/USAGE_GUIDE.md

API reference → docs/API.md

Swagger UI (GitHub Pages) → https://anandukch.github.io/aegis/swagger.html


RBAC Access Matrix

Role email phone card_number aadhaar pan name dob
ADMIN FULL FULL FULL FULL FULL FULL FULL
ANALYST MASKED MASKED DENIED MASKED MASKED MASKED MASKED
SERVICE MASKED MASKED FULL MASKED MASKED MASKED MASKED
VIEWER MASKED MASKED MASKED MASKED MASKED MASKED MASKED

Masking examples:

  • email: john@example.comj***@example.com
  • phone: 9876543210******3210
  • card: 4111111111114242****-****-****-4242
  • aadhaar: 123456781234XXXX-XXXX-1234
  • pan: ABCDE1234FABCDE****F
  • name: John DoeJ*** D***
  • dob: 1990-07-15****-**-15

Threat Model — What Happens If AEGIS Is Compromised?

This is the right question to ask about any vault system.

Database leaked (without the master key)

Attacker gets rows of enc_value + nonce — both base64-encoded ciphertext. Without VAULT_MASTER_KEY, these are computationally infeasible to reverse. AES-256-GCM with a random nonce per record gives no pattern to exploit. Raw PII remains safe.

VAULT_MASTER_KEY leaked

This is the single critical secret. If it leaks alongside the database, every record can be decrypted. This is game over for all stored data.

Mitigation for production:

  • Never store the master key in a .env file on the server
  • Use a dedicated secrets manager: AWS KMS, HashiCorp Vault, or GCP Secret Manager
  • Ideally use envelope encryption — the master key itself is encrypted by a hardware-backed KMS key that never leaves the HSM
  • Rotate the master key periodically (requires re-encrypting all vault records)

JWT_SECRET leaked

Attacker can forge valid JWTs with any role (including ADMIN), then call /detokenize to retrieve raw values — provided the API is reachable and the DB is accessible. Effectively full read access.

Mitigation: short JWT_EXPIRY_HOURS, rotate the secret immediately on suspicion, use RS256 (asymmetric) JWTs in production so the signing key never needs to be shared.

Audit logs as a detection layer

Every detokenize call is logged with actor_id, ip_address, and timestamp — even denied ones. Anomalous patterns (high volume from one actor, unusual IPs, DENIED spikes) signal an active breach before full exfiltration completes.

Summary

What leaks Impact Mitigation
Database only None — ciphertext is opaque AES-256-GCM (built in)
VAULT_MASTER_KEY Full decryption of all records Store in KMS, never in env files
JWT_SECRET Attacker can impersonate any role Short expiry, rotate immediately, use RS256
Both key + DB Total breach Defense in depth — restrict DB network access, monitor audit logs. Production-grade mitigation: use Customer-Managed Keys (CMK) where the KEK lives in the customer's own AWS KMS account — even a full vendor-side compromise cannot decrypt data without the customer's key.

Design Decisions

AES-256-GCM — authenticated encryption. GCM provides both confidentiality and integrity: any tamper with the ciphertext causes decryption to fail rather than silently return garbage. A fresh 12-byte random nonce per record ensures identical values produce different ciphertexts.

Soft deletesdeleted_at timestamp instead of hard delete. Audit logs reference tokens; hard-deleting vault records would leave dangling audit entries. Soft delete preserves the audit trail while making the data inaccessible through normal API flows.

Append-only audit logs — no update or delete endpoint for audit records. The audit trail's value is in its immutability. Every STORE, DETOKENIZE, and DELETE is logged regardless of outcome.

Role embedded in JWT — no DB lookup per request for role resolution. Role changes only take effect on next login (short JWT expiry mitigates stale role window).


Running Tests

go test ./internal/crypto/... ./internal/vault/... -v

What's Next

See internal/llmproxy/README.md — planned LLM proxy that detokenizes PII before sending prompts to external models, preventing raw PII from ever reaching OpenAI/Anthropic.


Environment Variables

Variable Description
APP_PORT HTTP listen port (default: 8080)
APP_ENV development or production
DB_HOST Postgres host
DB_PORT Postgres port
DB_USER Postgres user
DB_PASSWORD Postgres password
DB_NAME Database name
JWT_SECRET HMAC secret for JWT signing (min 32 chars)
JWT_EXPIRY_HOURS JWT TTL in hours (default: 24)
VAULT_MASTER_KEY AES-256 master key — must be exactly 32 bytes

About

PII privacy vault API in Go - tokenize sensitive data, role-based access, encrypted storage, audit trail.

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages