GdprOrganizationalRules.java
package com.cloudforgeci.api.core.rules;
import com.cloudforge.core.annotation.ComplianceFramework;
import com.cloudforge.core.interfaces.FrameworkRules;
import com.cloudforgeci.api.core.SystemContext;
import com.cloudforge.core.enums.SecurityProfile;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;
/**
* GDPR organizational and data protection validation rules.
*
* <p>These rules enforce GDPR requirements beyond infrastructure security:</p>
* <ul>
* <li><b>Lawfulness of Processing</b> - Article 6</li>
* <li><b>Data Subject Rights</b> - Articles 15-22</li>
* <li><b>Data Protection Impact Assessment</b> - Article 35</li>
* <li><b>International Data Transfers</b> - Articles 44-50</li>
* </ul>
*
* <h2>Controls Implemented</h2>
* <ul>
* <li>Legal basis documentation</li>
* <li>Consent mechanism validation</li>
* <li>Data subject rights procedures</li>
* <li>Data retention policies</li>
* <li>International transfer safeguards</li>
* </ul>
*
* <h2>Usage</h2>
* <pre>{@code
* // Install GDPR organizational validation
* GdprOrganizationalRules.install(ctx);
* }</pre>
*
* <h2>Important Note</h2>
* <p>These controls require organizational policies and legal procedures that
* cannot be fully automated. Infrastructure validation ensures technical readiness,
* but organizations must maintain separate legal documentation and processes.</p>
*/
@ComplianceFramework(
value = "GDPR-Organizational",
priority = 35,
displayName = "GDPR Organizational Requirements",
description = "Validates GDPR organizational and data protection requirements"
)
public class GdprOrganizationalRules implements FrameworkRules<SystemContext> {
private static final Logger LOG = Logger.getLogger(GdprOrganizationalRules.class.getName());
/**
* Install GDPR organizational validation rules.
* Only applies when GDPR framework is selected.
*
* @param ctx System context
*/
@Override
public void install(SystemContext ctx) {
// Only apply if GDPR is in compliance frameworks
String complianceFrameworks = ctx.cfc.complianceFrameworks();
if (complianceFrameworks == null || !complianceFrameworks.toUpperCase().contains("GDPR")) {
LOG.info("GDPR organizational rules skipped - GDPR not in complianceFrameworks");
return;
}
LOG.info("Installing GDPR organizational compliance validation rules for " + ctx.security);
ctx.getNode().addValidation(() -> {
List<ComplianceRule> rules = new ArrayList<>();
// Lawfulness of processing
rules.addAll(validateLawfulnessOfProcessing(ctx));
// Data subject rights
rules.addAll(validateDataSubjectRights(ctx));
// Data protection impact assessment
rules.addAll(validateDataProtectionImpactAssessment(ctx));
// International data transfers
rules.addAll(validateInternationalTransfers(ctx));
// Data retention and minimization
rules.addAll(validateDataRetention(ctx));
// Get all failed rules
List<ComplianceRule> failedRules = rules.stream()
.filter(rule -> !rule.passed())
.toList();
if (!failedRules.isEmpty()) {
LOG.warning("GDPR Organizational validation found " + failedRules.size() + " recommendations");
failedRules.forEach(rule ->
LOG.warning(" - " + rule.description() + ": " + rule.errorMessage().orElse("")));
// These are always advisory - cannot fully automate legal/organizational controls
if (ctx.security == SecurityProfile.DEV) {
return List.of();
}
// For production, convert to warnings (not blocking)
return failedRules.stream()
.map(rule -> "[ADVISORY] " + rule.description() + ": " + rule.errorMessage().orElse(""))
.toList();
} else {
LOG.info("GDPR Organizational validation passed (" + rules.size() + " checks)");
return List.of();
}
});
}
/**
* Validate lawfulness of processing (GDPR Article 6).
*
* <p>GDPR Requirements:</p>
* <ul>
* <li>Article 6(1) - Legal basis for processing personal data</li>
* <li>Article 7 - Conditions for consent</li>
* <li>Article 13 - Information to be provided when collecting data</li>
* </ul>
*/
private List<ComplianceRule> validateLawfulnessOfProcessing(SystemContext ctx) {
List<ComplianceRule> rules = new ArrayList<>();
// Legal basis documented
boolean legalBasisDocumented = getBooleanSetting(ctx, "gdprLegalBasisDocumented", false);
if (!legalBasisDocumented) {
rules.add(ComplianceRule.fail(
"GDPR-ART6-LEGAL-BASIS",
"Document legal basis for processing personal data",
"Identify and document legal basis for each processing activity: " +
"consent, contract, legal obligation, vital interests, public task, or legitimate interests. " +
"GDPR Article 6(1). Required for lawful processing. " +
"Set gdprLegalBasisDocumented = true when documentation is complete."
));
} else {
rules.add(ComplianceRule.pass(
"GDPR-ART6-LEGAL-BASIS",
"Legal basis for processing documented"
));
}
// Consent mechanism (if consent is legal basis)
boolean consentMechanismImplemented = getBooleanSetting(ctx, "gdprConsentMechanismImplemented", false);
if (!consentMechanismImplemented) {
rules.add(ComplianceRule.fail(
"GDPR-ART7-CONSENT",
"Implement compliant consent mechanism if using consent as legal basis",
"If using consent: ensure freely given, specific, informed, unambiguous. " +
"Separate consent for different purposes. Easy withdrawal. " +
"GDPR Article 7. Document consent records. " +
"Set gdprConsentMechanismImplemented = true when implemented (or N/A if not using consent)."
));
} else {
rules.add(ComplianceRule.pass(
"GDPR-ART7-CONSENT",
"Consent mechanism implemented or not applicable"
));
}
// Privacy notice
boolean privacyNoticeProvided = getBooleanSetting(ctx, "gdprPrivacyNoticeProvided", false);
if (!privacyNoticeProvided) {
rules.add(ComplianceRule.fail(
"GDPR-ART13-PRIVACY-NOTICE",
"Provide privacy notice when collecting personal data",
"Privacy notice must include: controller identity, purposes, legal basis, " +
"recipients, retention periods, data subject rights, withdrawal of consent. " +
"GDPR Articles 13-14. Must be concise, transparent, accessible. " +
"Set gdprPrivacyNoticeProvided = true when privacy notice is published."
));
} else {
rules.add(ComplianceRule.pass(
"GDPR-ART13-PRIVACY-NOTICE",
"Privacy notice provided to data subjects"
));
}
return rules;
}
/**
* Validate data subject rights procedures (GDPR Articles 15-22).
*
* <p>GDPR Rights:</p>
* <ul>
* <li>Article 15 - Right of access</li>
* <li>Article 16 - Right to rectification</li>
* <li>Article 17 - Right to erasure ("right to be forgotten")</li>
* <li>Article 18 - Right to restriction of processing</li>
* <li>Article 20 - Right to data portability</li>
* <li>Article 21 - Right to object</li>
* </ul>
*/
private List<ComplianceRule> validateDataSubjectRights(SystemContext ctx) {
List<ComplianceRule> rules = new ArrayList<>();
// Data subject request procedures
boolean dataSubjectRequestProcedures = getBooleanSetting(ctx, "gdprDataSubjectRequestProcedures", false);
if (!dataSubjectRequestProcedures) {
rules.add(ComplianceRule.fail(
"GDPR-DATA-SUBJECT-RIGHTS",
"Implement procedures for handling data subject rights requests",
"Document procedures for: access requests, rectification, erasure, " +
"restriction, portability, objection. 1-month response timeline. " +
"GDPR Articles 15-22. Include identity verification. " +
"Set gdprDataSubjectRequestProcedures = true when procedures are documented."
));
} else {
rules.add(ComplianceRule.pass(
"GDPR-DATA-SUBJECT-RIGHTS",
"Data subject rights request procedures implemented"
));
}
// Right to erasure technical capability
boolean rightToErasureCapability = getBooleanSetting(ctx, "gdprRightToErasureCapability", false);
if (!rightToErasureCapability) {
rules.add(ComplianceRule.fail(
"GDPR-ART17-ERASURE",
"Implement technical capability for data erasure",
"Ensure systems can delete/anonymize personal data upon request. " +
"GDPR Article 17. Consider backup retention, legal holds. " +
"Document erasure procedures. " +
"Set gdprRightToErasureCapability = true when erasure is technically feasible."
));
} else {
rules.add(ComplianceRule.pass(
"GDPR-ART17-ERASURE",
"Right to erasure technical capability implemented"
));
}
// Data portability capability
boolean dataPortabilityCapability = getBooleanSetting(ctx, "gdprDataPortabilityCapability", false);
if (!dataPortabilityCapability) {
rules.add(ComplianceRule.fail(
"GDPR-ART20-PORTABILITY",
"Implement data portability capability (structured, machine-readable format)",
"Enable data export in structured, commonly used, machine-readable format (JSON, CSV). " +
"GDPR Article 20. Applies when processing is based on consent or contract. " +
"Set gdprDataPortabilityCapability = true when export functionality exists."
));
} else {
rules.add(ComplianceRule.pass(
"GDPR-ART20-PORTABILITY",
"Data portability capability implemented"
));
}
return rules;
}
/**
* Validate Data Protection Impact Assessment (DPIA) - GDPR Article 35.
*
* <p>GDPR Requirements:</p>
* <ul>
* <li>Article 35(1) - DPIA required for high-risk processing</li>
* <li>Article 35(3) - DPIA required for: systematic monitoring, special categories, large scale</li>
* <li>Article 35(7) - DPIA must assess: necessity, proportionality, risks, safeguards</li>
* </ul>
*/
private List<ComplianceRule> validateDataProtectionImpactAssessment(SystemContext ctx) {
List<ComplianceRule> rules = new ArrayList<>();
// DPIA conducted
boolean dpiaCompleted = getBooleanSetting(ctx, "gdprDpiaCompleted", false);
if (ctx.security == SecurityProfile.PRODUCTION && !dpiaCompleted) {
rules.add(ComplianceRule.fail(
"GDPR-ART35-DPIA",
"Data Protection Impact Assessment (DPIA) required for high-risk processing",
"Conduct DPIA if processing: involves systematic monitoring, special categories of data, " +
"large-scale profiling, automated decision-making. GDPR Article 35. " +
"Assess risks to rights and freedoms. Document safeguards. " +
"Set gdprDpiaCompleted = true when DPIA is documented."
));
} else if (dpiaCompleted || ctx.security != SecurityProfile.PRODUCTION) {
rules.add(ComplianceRule.pass(
"GDPR-ART35-DPIA",
"Data Protection Impact Assessment completed or not required"
));
}
// Privacy by Design
boolean privacyByDesignImplemented = getBooleanSetting(ctx, "gdprPrivacyByDesignImplemented", false);
if (!privacyByDesignImplemented) {
rules.add(ComplianceRule.fail(
"GDPR-ART25-PRIVACY-BY-DESIGN",
"Implement data protection by design and by default",
"Implement technical and organizational measures ensuring: data minimization, " +
"pseudonymization, encryption, confidentiality, integrity, availability. " +
"GDPR Article 25. Infrastructure encryption satisfies part of this. " +
"Set gdprPrivacyByDesignImplemented = true when measures are documented."
));
} else {
rules.add(ComplianceRule.pass(
"GDPR-ART25-PRIVACY-BY-DESIGN",
"Privacy by design and by default implemented"
));
}
return rules;
}
/**
* Validate international data transfer safeguards (GDPR Chapter V).
*
* <p>GDPR Requirements:</p>
* <ul>
* <li>Articles 44-50 - Transfer of personal data to third countries</li>
* <li>Article 46 - Standard Contractual Clauses (SCCs)</li>
* <li>Article 49 - Derogations for specific situations</li>
* </ul>
*/
private List<ComplianceRule> validateInternationalTransfers(SystemContext ctx) {
List<ComplianceRule> rules = new ArrayList<>();
// Check if using EU region
String region = ctx.cfc.region();
boolean isEuRegion = region != null && region.startsWith("eu-");
// International transfer safeguards
boolean internationalTransferSafeguards = getBooleanSetting(ctx, "gdprInternationalTransferSafeguards", false);
if (!isEuRegion && !internationalTransferSafeguards) {
rules.add(ComplianceRule.fail(
"GDPR-ART46-INTERNATIONAL-TRANSFERS",
"Implement safeguards for international data transfers outside EU/EEA",
"If transferring personal data outside EU/EEA: use Standard Contractual Clauses (SCCs), " +
"Binding Corporate Rules (BCRs), or adequacy decision. " +
"GDPR Articles 44-46. AWS SCCs available through AWS Artifact. " +
"Set gdprInternationalTransferSafeguards = true when safeguards are in place."
));
} else {
rules.add(ComplianceRule.pass(
"GDPR-ART46-INTERNATIONAL-TRANSFERS",
"International transfer safeguards in place or using EU region"
));
}
// Data localization
boolean dataLocalizationEnforced = getBooleanSetting(ctx, "gdprDataLocalizationEnforced", false);
if (!dataLocalizationEnforced) {
rules.add(ComplianceRule.fail(
"GDPR-DATA-LOCALIZATION",
"Document data localization requirements and enforcement",
"Verify all personal data remains in approved regions (EU/EEA or adequate country). " +
"Configure S3 bucket policies, RDS read replicas, backup regions accordingly. " +
"Set gdprDataLocalizationEnforced = true when localization is configured."
));
} else {
rules.add(ComplianceRule.pass(
"GDPR-DATA-LOCALIZATION",
"Data localization enforced"
));
}
return rules;
}
/**
* Validate data retention and minimization (GDPR Article 5).
*
* <p>GDPR Requirements:</p>
* <ul>
* <li>Article 5(1)(c) - Data minimization</li>
* <li>Article 5(1)(e) - Storage limitation (retention periods)</li>
* <li>Article 30 - Records of processing activities</li>
* </ul>
*/
private List<ComplianceRule> validateDataRetention(SystemContext ctx) {
List<ComplianceRule> rules = new ArrayList<>();
// Data retention policy
boolean dataRetentionPolicyDefined = getBooleanSetting(ctx, "gdprDataRetentionPolicyDefined", false);
if (!dataRetentionPolicyDefined) {
rules.add(ComplianceRule.fail(
"GDPR-ART5-RETENTION",
"Define data retention policy and deletion schedules",
"Document retention periods for each category of personal data. " +
"GDPR Article 5(1)(e): data kept no longer than necessary. " +
"Implement automated deletion after retention period expires. " +
"Set gdprDataRetentionPolicyDefined = true when policy is documented."
));
} else {
rules.add(ComplianceRule.pass(
"GDPR-ART5-RETENTION",
"Data retention policy defined"
));
}
// Records of processing activities (ROPA)
boolean recordsOfProcessingActivities = getBooleanSetting(ctx, "gdprRecordsOfProcessingActivities", false);
if (!recordsOfProcessingActivities) {
rules.add(ComplianceRule.fail(
"GDPR-ART30-ROPA",
"Maintain records of processing activities (ROPA)",
"Document: purposes, categories of data subjects, categories of data, " +
"recipients, transfers, retention periods, security measures. " +
"GDPR Article 30. Required for organizations >250 employees or high-risk processing. " +
"Set gdprRecordsOfProcessingActivities = true when ROPA is maintained."
));
} else {
rules.add(ComplianceRule.pass(
"GDPR-ART30-ROPA",
"Records of processing activities (ROPA) maintained"
));
}
return rules;
}
/**
* Helper method to safely get boolean settings from deployment context.
*/
private static boolean getBooleanSetting(SystemContext ctx, String key, boolean defaultValue) {
try {
String value = ctx.cfc.getContextValue(key, String.valueOf(defaultValue));
return Boolean.parseBoolean(value);
} catch (Exception e) {
return defaultValue;
}
}
}