Skip to content

Latest commit

History

5 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

🛡️ DataGuard Engine v1.2.0 — Clean Architecture Edition

JavaMavenJUnitVirtual ThreadsBuildTestsOCPLicense

DataGuard Engine is an anonymization and data loss prevention (DLP) engine featuring Streaming I/O, Zero-Garbage architecture, Virtual Threads (Project Loom), and strict Clean Architecture / SOLID compliance. It operates in two modes: PII file sanitization and DLP auditing for Git pre-commit hooks and CI/CD pipelines.

v1.2.0 Highlights: Pure Core engine (zero System.err side effects), RuleProvider SPI enforced via OCP, LicenseValidator SPI wired into CLI gate, DlpAuditResult domain records, DRY-compliant single source of truth for all regex patterns, and a 24-test Red Team bypass suite.

Learning Project: This project was built to learn, practice and deepen skills in DevSecOps, Java 21 (Virtual Threads / Project Loom), Clean Architecture, SOLID principles, high-performance file processing, secure coding practices, JUnit 5 testing, Git-based security automation, and AI-assisted software engineering. It also serves as a hands-on exploration of how modern AI coding agents can be leveraged to design, generate, review, and strengthen automated test suites, including adversarial (Red Team) security testing.


📦 Project Structure

src/
├── main/java/com/devdiego/
│ ├── Main.java # CLI Boundary — owns all presentation (System.out/err)
│ └── dataguard/
│ ├── config/
│ │ ├── RuleProvider.java # SPI interface for rule catalogs (OCP)
│ │ ├── StandardPiiRuleProvider.java # 4 PII rules: EMAIL, CREDIT_CARD, IPV4, CELLPHONE
│ │ └── DlpAuditRuleProvider.java # 4 DLP rules: AWS, GitHub, PrivateKey, JWT
│ ├── core/
│ │ ├── DataGuardEngine.java # Pure engine: sanitizeStream / auditDLP / auditConcurrent
│ │ └── license/
│ │ ├── LicenseValidator.java # SPI interface for license validation (OCP)
│ │ └── CommunityLicenseValidator.java # Community Edition implementation (MIT)
│ └── model/
│ ├── Rule.java # Immutable record (name, pattern, replacementTag)
│ ├── DlpViolation.java # Immutable record (ruleName, file, lineNumber)
│ └── DlpAuditResult.java # Immutable record (leakDetected, violations)
└── test/java/com/devdiego/dataguard/core/
├── DataGuardEngineTest.java # 26 functional tests (JUnit 5)
└── DlpBypassTest.java # 24 Red Team adversarial bypass tests

⚙️ Architecture — v1.2.0

Clean Architecture Layers

┌─────────────────────────────────────────────────────────────┐
│ Presentation Layer │
│ Main.java (CLI) — owns System.out, System.err, System.exit │
├─────────────────────────────────────────────────────────────┤
│ Core / Domain Layer │
│ DataGuardEngine — pure functions, returns domain records │
│ RuleProvider (SPI) LicenseValidator (SPI) │
├─────────────────────────────────────────────────────────────┤
│ Model / Domain Layer │
│ Rule · DlpViolation · DlpAuditResult (immutable records) │
├─────────────────────────────────────────────────────────────┤
│ Infrastructure / Config Layer │
│ StandardPiiRuleProvider · DlpAuditRuleProvider │
│ CommunityLicenseValidator │
└─────────────────────────────────────────────────────────────┘

Dependency Rule: Dependencies point only inward. The Core layer has zero references to System.err, System.out, or any presentation concern.

Components

ComponentResponsibility
Rule (record)Defines a compiled regex pattern, its name, and replacement tag. Immutable, thread-safe, validated on construction.
RuleProvider (SPI)Interface for pluggable rule catalogs. Enforces Open/Closed Principle — new providers can be added without modifying the engine.
StandardPiiRuleProviderProvider with 4 PII rules: EMAIL, CREDIT_CARD, IPV4, CELLPHONE. Used by the sanitization pipeline.
DlpAuditRuleProviderProvider with 4 DLP rules: AWS_ACCESS_KEY, GITHUB_TOKEN, PRIVATE_KEY, JWT_TOKEN. Used by the DLP audit pipeline.
DlpViolation (record)Immutable record capturing a single violation (ruleName, file, lineNumber).
DlpAuditResult (record)Immutable aggregate result with leakDetected flag and violations list. Returned by the engine — no System.err side effects.
LicenseValidator (SPI)Interface for pluggable license validation. Enforces OCP — swap implementations without modifying the CLI.
CommunityLicenseValidatorCommunity Edition (MIT) implementation. Always validates true.
DataGuardEnginePure core with three modes: streaming sanitization, DLP auditing with short-circuit, and concurrent auditing with Virtual Threads. Accepts RuleProvider SPI. Zero presentation side effects.
MainCLI with subcommands: --dlp-audit <file> (Git hook) and --sanitize <src> <dst> (file cleanup). Gates execution behind LicenseValidator. Owns all presentation (System.out/System.err).

Mode 1: Streaming Sanitization (sanitizeStream)

Original line → [EMAIL] → [CREDIT_CARD] → [IPV4] → [CELLPHONE] → Clean line

Chained pipeline that recycles StringBuilder and Matcher. Each rule receives the output of the previous one. Inline counting without a second pass. Rules sourced from the injected RuleProvider SPI.

Mode 2: DLP Audit (auditDLP) — Short-Circuit

Line 1 → [AWS_ACCESS_KEY] → [GITHUB_TOKEN] → [PRIVATE_KEY] → [JWT_TOKEN] → clean
Line 2 → [AWS_ACCESS_KEY] → [GITHUB_TOKEN] → [PRIVATE_KEY] → [JWT_TOKEN] → clean
Line 3 → [AWS_ACCESS_KEY] → MATCH! → return DlpAuditResult (closes FD, reads no further)

On first match, immediately aborts without reading the rest of the file. Returns a DlpAuditResult with the first DlpViolation. Ideal for CI/CD where time is critical.

Mode 3: Concurrent Auditing (auditMultipleFilesConcurrently) — Java 21

File 1 ──→ [Virtual Thread 1] ──→ auditDLP() ──→ DlpAuditResult
File 2 ──→ [Virtual Thread 2] ──→ auditDLP() ──→ DlpAuditResult
File 3 ──→ [Virtual Thread 3] ──→ auditDLP() ──→ DlpAuditResult
...
File N ──→ [Virtual Thread N] ──→ auditDLP() ──→ DlpAuditResult
↓
Aggregated DlpAuditResult (all violations)

Uses Executors.newVirtualThreadPerTaskExecutor() from Project Loom. Each Virtual Thread weighs ~KB, enabling auditing of thousands of files simultaneously without saturating the OS. All DlpViolation objects from virtual threads are aggregated into a thread-safe Collections.synchronizedList and returned as a unified DlpAuditResult.

Performance Comparison

TechniqueNaïve approachDataGuard Engine v1.2.0
ReadFiles.readString (all in RAM)BufferedReader (streaming O(1))
RegexString.replaceAll (millions of Strings)Matcher.appendReplacement (recycled buffers)
MemoryOutOfMemoryError with >1 GB~10–15 MB constant
CountSecond pass over the fileInline counting in a single pass
DLPAlways reads entire fileShort-circuit: returns on first match
ConcurrencyPlatform Threads (~1 MB each)Virtual Threads (~KB each, Project Loom)
ArchitectureCore writes to System.errPure Core — returns DlpAuditResult domain records
ExtensibilityStatic factory (RuleConfigurator)RuleProvider SPI (OCP-compliant)

🚀 Usage Guide

Requirements

  • Java 21 or higher
  • Apache Maven 3.8 or higher

1. Clone and build

git clone https://github.com/your-user/java-anonimo-engine.git
cd java-anonimo-engine
mvn clean compile

2. Run tests

mvn clean test# Tests run: 50, Failures: 0, Errors: 0, Skipped: 0# BUILD SUCCESS

3. Sanitization Mode (clean PII from files)

java -jar dataguard-engine.jar --sanitize logs.txt clean_logs.txt

Output:

License: Community Edition (MIT License - Free for all uses)
[DataGuard Engine] Sanitizing file stream...
Sanitization complete. Audit metrics:
-> EMAIL: 2 redactions
-> IPV4: 2 redactions
-> CREDIT_CARD: 1 redactions
-> CELLPHONE: 0 redactions

4. DLP Audit Mode (Git pre-commit hook / CI/CD)

# Audit a file for secrets
java -jar dataguard-engine.jar --dlp-audit config.env

If a secret is found (exit code 1):

License: Community Edition (MIT License - Free for all uses)
🛡️ [DataGuard Engine v1.2.0] Starting DLP Audit on: config.env
🚨 [DLP VIOLATION] Rule: AWS_ACCESS_KEY | File: config.env | Line: 3
X / COMMIT REJECTED: Secrets or sensitive data detected in code.

If clean (exit code 0):

License: Community Edition (MIT License - Free for all uses)
🛡️ [DataGuard Engine v1.2.0] Starting DLP Audit on: clean_service.java
OK / DLP Audit Passed. Zero leaks detected.

Exit codes:

CodeMeaning
0Operation successful (audit passed / sanitize complete)
1DLP violation detected or I/O error
2License validation failed

Git Hook Integration

# .git/hooks/pre-commit#!/bin/bashforfilein$(git diff --cached --name-only);do
java -jar dataguard.jar --dlp-audit "$file"||exit 1
done

⚠️Security Note: Pre-commit hooks are advisory and can be bypassed with git commit --no-verify. For production enforcement, add a server-side pre-receive hook as a backstop. See the Red Team Analysis section for known bypass vectors.


🔧 Rule Catalogs

Standard PII Rules (StandardPiiRuleProvider)

RuleDetectsTag
EMAILuser@domain.com[EMAIL_REDACTED]
CREDIT_CARD1234-5678-9012-3456[CARD_REDACTED]
IPV4192.168.1.50[IP_REDACTED]
CELLPHONE+57 3001234567[CELLPHONE_REDACTED]

DLP Secrets Rules (DlpAuditRuleProvider)

RuleDetectsExample
AWS_ACCESS_KEYAKIA... (20 chars)AKIA_FAKE_FAKE_FAKE_
GITHUB_TOKENghp_... / github_pat_...ghp_abc123...
PRIVATE_KEY-----BEGIN RSA PRIVATE KEY-----Private key headers
JWT_TOKENeyJ... (base64)eyJhbGciOiJIUzI1NiJ9.eyJzdWIi...

🧩 Extensibility

Custom RuleProvider (OCP)

Create your own RuleProvider implementation to add custom rule catalogs without modifying the engine (Open/Closed Principle):

publicclassMyCustomRuleProviderimplementsRuleProvider {
privatestaticfinalList<Rule> RULES = List.of(
newRule("DNI", Pattern.compile("\\b\\d{8}[A-Z]\\b"), "[DNI_REDACTED]"),
newRule("API_KEY", Pattern.compile("sk-[a-zA-Z0-9]{32}"), "[API_KEY_BLOCKED]")
);
@OverridepublicList<Rule> getRules() { returnRULES; }
@OverridepublicStringgetProviderName() { return"Custom Rule Provider"; }
}
// SanitizationMap<String, Long> metrics = DataGuardEngine.sanitizeStream(source, target, newMyCustomRuleProvider());
// DLP Audit — returns DlpAuditResult (pure data, no System.err)DlpAuditResultresult = DataGuardEngine.auditDLP(file, newMyCustomRuleProvider());
if (result.leakDetected()) {
result.violations().forEach(v -> System.err.printf("🚨 %s | %s | line %d%n",
v.ruleName(), v.file().getFileName(), v.lineNumber()));
}
// Concurrent DLP (thousands of files)DlpAuditResultresult = DataGuardEngine.auditMultipleFilesConcurrently(fileList, newMyCustomRuleProvider());

Custom LicenseValidator (OCP)

publicclassEnterpriseLicenseValidatorimplementsLicenseValidator {
@Overridepublicbooleanvalidate() throwsSecurityException {
// Check license server, verify signature, etc.returnverifyEnterpriseLicense();
}
@OverridepublicStringgetLicenseType() {
return"Enterprise Edition (Commercial License)";
}
}
// In Main.java — swap one line:LicenseValidatorlicense = newEnterpriseLicenseValidator();

🧪 Testing

Functional Test Suite — 26 tests

Test suite using JUnit 5 and @TempDir:

Test GroupTestsWhat it validates
DLP Audit — Single File Detection6AWS key, GitHub token, private key, JWT, clean files, empty files
DLP Audit — Short-Circuit Optimization3Stop at line 1, stop at line 50, no false positives on near-miss patterns
DLP Audit — Concurrent (Virtual Threads)3Leak detection across files, all-clean, 100 files without crash
Sanitization — PII Redaction Pipeline5All PII types, accurate counts, clean line preservation, empty file, 10K-line file
Custom Rules & Edge Cases5Custom Stripe key, custom DNI, null/blank name rejection, null pattern rejection, default tag
Enterprise Scenario — CI/CD Simulation2Pre-commit hook (20 staged files), CI/CD log sanitization (500 lines)
License Validator SPI2Community license validates, non-blank license type

Red Team Bypass Suite — 24 tests

Adversarial tests proving regex bypass vectors and pre-commit hook weaknesses:

Test GroupTestsWhat it validates
AWS Access Key — Bypass Vectors6Lowercase prefix, split lines, runtime assembly, base64, 15-char edge, zero-width space
GitHub Token — Bypass Vectors435-char body, hyphen in body, hex encoding, runtime assembly
JWT Token — Bypass Vectors7Space instead of dot, split lines, URL-encoded dots, zero-width space, hex, URL-encoded ey, control test
Pre-Commit Hook — Filesystem Bypass6--no-verify, symlink, word-splitting, binary null bytes, UTF-16, OOM long line
ReDoS — Catastrophic Backtracking1Alternating A. pattern × 10,000
mvn clean test# Tests run: 50, Failures: 0, Errors: 0, Skipped: 0# BUILD SUCCESS

🔴 Red Team Security Analysis

The DlpBypassTest.java suite empirically demonstrates 24 bypass vectors against the current DLP regex patterns and pre-commit hook. Key findings:

Regex Bypasses

PatternBypass ExamplesSeverity
AKIA[0-9A-Z]{16}Lowercase akia, split across lines, base64-encoded, zero-width space🔴 Critical
(ghp|github_pat)_[a-zA-Z0-9]{36,82}35-char body, hyphen in body, hex-encoded, runtime assembly🔴 Critical
ey[A-Za-z0-9-_=]+\.[A-Za-z0-9-_=]+...URL-encoded dots, zero-width space in ey, hex-encoded, space instead of dot🔴 Critical

Pre-Commit Hook Bypasses

VectorMechanismSeverity
git commit --no-verifyHooks are advisory, not enforced🔴 Critical
Symlink to clean fileEngine follows symlink; real secret never staged🔴 Critical
UTF-16 encoded fileBufferedReader (UTF-8) reads garbled chars🔴 Critical
Binary file with null bytesNull bytes break ASCII sequence🔴 High

Recommended Mitigations

  1. Server-side pre-receive hook — backstop for --no-verify bypass
  2. Multi-line sliding window — detect secrets split across lines
  3. Encoding detection — detect UTF-16/UTF-32 BOMs
  4. Case-insensitive regex — add Pattern.CASE_INSENSITIVE for AWS keys
  5. Flexible quantifiers{16}{15,20}, {36,82}{30,90}
  6. Max line length cap — prevent OOM on minified files
  7. Symlink detection — flag staged symlinks

🐳 Docker

# STAGE 1: Build & CompileFROM eclipse-temurin:21-jdk-alpine AS builder
WORKDIR /build
COPY pom.xml .
RUN apk add --no-cache maven && mvn dependency:go-offline -B
COPY src ./src
RUN mvn clean package -DskipTests
# STAGE 2: Production RuntimeFROM eclipse-temurin:21-jre-alpine AS runtime
WORKDIR /app
RUN addgroup -S dataguard && adduser -S dataguard -G dataguard
USER dataguard
COPY --from=builder /build/target/java-anonimo-engine-1.0-SNAPSHOT.jar ./dataguard-engine.jar
VOLUME ["/data", "/etc/dataguard"]
ENV JAVA_OPTS="-XX:+UseG1GC -XX:MaxRAMPercentage=75.0"ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -jar dataguard-engine.jar $0 $@"]
CMD ["--help"]
# Build and run
docker build -t dataguard-engine .
docker run --rm -v $(pwd):/data dataguard-engine --dlp-audit /data/config.env

📄 License

MIT © 2026 — DataGuard Engine v1.2.0 · Clean Architecture Edition

About

High-performance Java 21 PII anonymization engine using zero-garbage streaming I/O.

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages