Soc2Rules.java
package com.cloudforgeci.api.core.rules;
import com.cloudforge.core.annotation.ComplianceFramework;
import com.cloudforge.core.enums.AuthMode;
import com.cloudforge.core.enums.ComplianceMode;
import com.cloudforge.core.enums.NetworkMode;
import com.cloudforge.core.enums.SecurityProfile;
import com.cloudforge.core.interfaces.FrameworkRules;
import com.cloudforgeci.api.core.SystemContext;
import software.amazon.awscdk.services.logs.RetentionDays;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.logging.Logger;
/**
* SOC 2 (Service Organization Control 2) Trust Services Criteria compliance validation.
*
* SOC 2 is based on five Trust Services Criteria (TSC):
* - Security (Common Criteria - CC)
* - Availability (A)
* - Processing Integrity (PI)
* - Confidentiality (C)
* - Privacy (P)
*
* This validator focuses on the Security criteria (Common Criteria) which apply to all SOC 2 reports.
* Organizations can choose additional criteria based on their services.
*
* Trust Services Criteria Coverage:
* - CC6.1: Logical and Physical Access Controls
* - CC6.2: Access Management
* - CC6.6: Network Segmentation
* - CC6.7: Data Transmission
* - CC7.2: System Monitoring
* - CC7.3: Environmental Protections (Availability)
* - CC8.1: Change Management
*/
@ComplianceFramework(
value = "SOC2",
priority = 40,
displayName = "SOC 2",
description = "Validates SOC 2 Trust Services Criteria for service organizations"
)
public class Soc2Rules implements FrameworkRules<SystemContext> {
private static final Logger LOG = Logger.getLogger(Soc2Rules.class.getName());
/**
* Install SOC 2 compliance validation rules.
* SOC 2 applies to production and staging environments serving customers.
*
* @since 3.0.0
*/
@Override
public void install(SystemContext ctx) {
// SOC 2 typically applies to production and staging
if (ctx.security != SecurityProfile.PRODUCTION && ctx.security != SecurityProfile.STAGING) {
LOG.info("SOC 2 validation rules typically apply to PRODUCTION and STAGING profiles");
return;
}
LOG.info("Installing SOC 2 Trust Services Criteria compliance validation for " + ctx.security);
// Get compliance mode (already resolved to enum with proper default)
ComplianceMode complianceMode = ctx.cfc.complianceMode();
LOG.info(" Compliance mode: " + complianceMode);
ctx.getNode().addValidation(() -> {
List<ComplianceRule> rules = new ArrayList<>();
// Common Criteria - Security
rules.addAll(validateAccessControls(ctx));
rules.addAll(validateNetworkSecurity(ctx));
rules.addAll(validateSystemMonitoring(ctx));
rules.addAll(validateChangeManagement(ctx));
// Availability Criteria
rules.addAll(validateAvailability(ctx));
// Confidentiality Criteria
rules.addAll(validateConfidentiality(ctx));
// Get all failed rules
List<ComplianceRule> failedRules = rules.stream()
.filter(rule -> !rule.passed())
.toList();
// Convert to error strings
List<String> errors = failedRules.stream()
.map(ComplianceRule::toErrorString)
.flatMap(Optional::stream)
.toList();
if (!errors.isEmpty()) {
if (complianceMode == ComplianceMode.ADVISORY) {
// Advisory mode: Log warnings but don't fail synthesis
LOG.warning("SOC 2 validation found " + errors.size() + " recommendations (ADVISORY mode - not blocking)");
errors.forEach(err -> LOG.warning(" - " + err));
return List.of(); // Return empty list = no CDK synthesis errors
} else {
// Enforce mode: Fail synthesis
LOG.severe("SOC 2 validation failed with " + errors.size() + " violations (ENFORCE mode - blocking deployment)");
errors.forEach(err -> LOG.severe(" - " + err));
return errors; // Return errors = CDK synthesis fails
}
} else {
LOG.info("SOC 2 Trust Services Criteria validation passed (" + rules.size() + " checks)");
return List.of();
}
});
}
/**
* CC6.1 & CC6.2: Logical and Physical Access Controls.
* The entity implements logical access security software, infrastructure, and architectures
* over protected information assets to protect them from security events.
*/
private List<ComplianceRule> validateAccessControls(SystemContext ctx) {
List<ComplianceRule> rules = new ArrayList<>();
var config = ctx.securityProfileConfig.get().orElseThrow(
() -> new IllegalStateException("SecurityProfileConfiguration not set")
);
// CC6.1: Access controls must be implemented
if (ctx.iamProfile == null) {
rules.add(ComplianceRule.fail(
"SOC2-CC6.1-IAM",
"IAM access controls required",
"IAMPasswordPolicyRule",
"Implement role-based access control (RBAC) to restrict access to system components."
));
} else {
rules.add(ComplianceRule.pass("SOC2-CC6.1-IAM", "IAM access controls enabled", "IAMPasswordPolicyRule"));
}
// CC6.2: Authentication required
AuthMode authMode = ctx.cfc.authMode();
if (authMode == AuthMode.NONE) {
rules.add(ComplianceRule.fail(
"SOC2-CC6.2-Auth",
"User authentication required for customer-facing systems",
"Configure authMode = 'alb-oidc', 'jenkins-oidc', or 'application-oidc' to authenticate users."
));
} else {
rules.add(ComplianceRule.pass("SOC2-CC6.2-Auth", "User authentication enabled"));
}
// CC6.1: Encryption for data protection
if (!config.isEbsEncryptionEnabled() || !config.isEfsEncryptionAtRestEnabled()) {
rules.add(ComplianceRule.fail(
"SOC2-CC6.1-Encryption",
"Encryption at rest required to protect confidential data",
"EbsEncryptionRule",
"Enable encryption for all storage volumes."
));
} else {
rules.add(ComplianceRule.pass("SOC2-CC6.1-Encryption", "Encryption at rest enabled", "EbsEncryptionRule"));
}
return rules;
}
/**
* CC6.6 & CC6.7: Network Segmentation and Data Transmission.
* The entity implements network segmentation and encrypts data in transmission.
*/
private List<ComplianceRule> validateNetworkSecurity(SystemContext ctx) {
List<ComplianceRule> rules = new ArrayList<>();
var config = ctx.securityProfileConfig.get().orElseThrow(
() -> new IllegalStateException("SecurityProfileConfiguration not set")
);
// CC6.6: Network segmentation
if (ctx.vpc.get().isEmpty()) {
rules.add(ComplianceRule.fail(
"SOC2-CC6.6-VPC",
"Network segmentation required",
"Implement VPC with proper subnet isolation."
));
} else {
rules.add(ComplianceRule.pass("SOC2-CC6.6-VPC", "VPC network segmentation enabled"));
}
if (ctx.albSg.get().isEmpty() || ctx.efsSg.get().isEmpty()) {
rules.add(ComplianceRule.fail(
"SOC2-CC6.6-SG",
"Security groups required for network access control",
"Configure security groups to restrict traffic between components."
));
} else {
rules.add(ComplianceRule.pass("SOC2-CC6.6-SG", "Security groups configured"));
}
// CC6.7: SSL/TLS must be enabled for encrypted data transmission
if (!ctx.cfc.enableSsl()) {
rules.add(ComplianceRule.fail(
"SOC2-CC6.7-SSL",
"SSL/TLS must be enabled for encrypted data transmission (CC6.7)",
"Set enableSsl=true for production SOC2 compliance."
));
} else {
rules.add(ComplianceRule.pass("SOC2-CC6.7-SSL", "SSL/TLS enabled for data transmission"));
// CC6.7: Encryption in transit - TLS certificate (only checked if SSL is enabled)
// Note: Private CA certificates (when no domain is specified) are automatically created
boolean hasUserCert = ctx.cert.get().isPresent();
boolean usePrivateCa = ctx.cfc.domain() == null && ctx.cfc.fqdn() == null;
if (!hasUserCert && !usePrivateCa) {
rules.add(ComplianceRule.fail(
"SOC2-CC6.7-TLS",
"TLS certificate required for encrypted data transmission",
"Configure a domain with HTTPS certificate or use Private CA (SSL without domain)."
));
} else {
String certType = usePrivateCa ? "Private CA certificate" : "TLS certificate";
rules.add(ComplianceRule.pass("SOC2-CC6.7-TLS", certType + " configured"));
}
}
if (!config.isEfsEncryptionInTransitEnabled()) {
rules.add(ComplianceRule.fail(
"SOC2-CC6.7-EFS",
"Encryption in transit required for internal data transfer",
"Enable EFS in-transit encryption."
));
} else {
rules.add(ComplianceRule.pass("SOC2-CC6.7-EFS", "EFS in-transit encryption enabled"));
}
// CC6.6: WAF for web application protection (recommended)
if (!config.isWafEnabled()) {
rules.add(ComplianceRule.fail(
"SOC2-CC6.6-WAF",
"Web Application Firewall recommended for production systems",
"Enable WAF to protect against common web attacks."
));
} else {
rules.add(ComplianceRule.pass("SOC2-CC6.6-WAF", "WAF protection enabled"));
}
return rules;
}
/**
* CC7.2: System Monitoring.
* The entity monitors system components and the operation of those components
* for anomalies indicative of malicious acts, natural disasters, and errors.
*/
private List<ComplianceRule> validateSystemMonitoring(SystemContext ctx) {
List<ComplianceRule> rules = new ArrayList<>();
var config = ctx.securityProfileConfig.get().orElseThrow(
() -> new IllegalStateException("SecurityProfileConfiguration not set")
);
// CC7.2: Security monitoring advisory (per ComplianceMatrix - recommended but not required)
if (config.isSecurityMonitoringEnabled()) {
rules.add(ComplianceRule.pass("SOC2-CC7.2-Monitoring", "Security monitoring enabled"));
}
// Note: When disabled, we don't fail - it's advisory for SOC2 per ComplianceMatrix
// CC7.2: Threat detection
// NOTE: GuardDuty validation is now handled by ThreatProtectionRules using ComplianceMatrix
// which marks it as ADVISORY for SOC2 (recommended but not required)
if (config.isGuardDutyEnabled()) {
rules.add(ComplianceRule.pass("SOC2-CC7.2-GuardDuty", "GuardDuty threat detection enabled"));
}
// CC7.2: Log collection for monitoring
if (!config.isCloudTrailEnabled()) {
rules.add(ComplianceRule.fail(
"SOC2-CC7.2-CloudTrail",
"Audit logging required for system monitoring",
"CloudTrailEnabledRule",
"Enable CloudTrail to record all API activity."
));
} else {
rules.add(ComplianceRule.pass("SOC2-CC7.2-CloudTrail", "CloudTrail audit logging enabled", "CloudTrailEnabledRule"));
}
if (!config.isFlowLogsEnabled()) {
rules.add(ComplianceRule.fail(
"SOC2-CC7.2-FlowLogs",
"Network monitoring required",
"Enable VPC Flow Logs to monitor network traffic."
));
} else {
rules.add(ComplianceRule.pass("SOC2-CC7.2-FlowLogs", "VPC Flow Logs enabled"));
}
// CC7.2: Configuration compliance monitoring
if (!config.isAwsConfigEnabled()) {
rules.add(ComplianceRule.fail(
"SOC2-CC7.2-Config",
"Configuration compliance monitoring recommended",
"Enable AWS Config to detect configuration drift and non-compliant resources."
));
} else {
rules.add(ComplianceRule.pass("SOC2-CC7.2-Config", "AWS Config compliance monitoring enabled"));
}
// CC7.2: Log retention for audit trail
// SOC2 requires adequate log retention for security monitoring and incident investigation
// SOC2 standard: 365 days (ONE_YEAR) minimum for audit trails
var retentionDays = config.getLogRetentionDays();
if (!isRetentionSufficient(retentionDays)) {
String currentRetention = (retentionDays != null) ? retentionDays.toString() : "not set";
rules.add(ComplianceRule.fail(
"SOC2-CC7.2-LogRetention",
"Log retention must be at least 365 days for audit trails (SOC2 CC7.2)",
"CloudWatchLogGroupRetention",
"Log retention must be at least 365 days (ONE_YEAR). Current: " +
currentRetention + ". " +
"SOC2 CC7.2 requires adequate log retention for security monitoring and incident investigation."
));
} else {
rules.add(ComplianceRule.pass(
"SOC2-CC7.2-LogRetention",
"Log retention meets 365-day requirement (SOC2 CC7.2)",
"CloudWatchLogGroupRetention"
));
}
return rules;
}
/**
* Check if log retention meets SOC2 requirement (365 days / 1 year minimum).
* CC7.2: System monitoring requires adequate log retention for audit trails.
* SOC2 requires minimum 1 year retention for security and audit logs.
*/
private boolean isRetentionSufficient(RetentionDays retention) {
// SOC2 CC7.2 requires 1 year minimum retention for security monitoring and audit trails
// Reference: SOC2 CC7.2, AICPA Trust Services Criteria
return retention == RetentionDays.ONE_YEAR ||
retention == RetentionDays.THIRTEEN_MONTHS ||
retention == RetentionDays.EIGHTEEN_MONTHS ||
retention == RetentionDays.TWO_YEARS ||
retention == RetentionDays.THREE_YEARS ||
retention == RetentionDays.FIVE_YEARS ||
retention == RetentionDays.SIX_YEARS ||
retention == RetentionDays.SEVEN_YEARS ||
retention == RetentionDays.EIGHT_YEARS ||
retention == RetentionDays.NINE_YEARS ||
retention == RetentionDays.TEN_YEARS ||
retention == RetentionDays.INFINITE;
}
/**
* CC8.1: Change Management.
* The entity authorizes, designs, develops or acquires, configures, documents,
* tests, approves, and implements changes to infrastructure, data, software,
* and procedures to meet its objectives.
*/
private List<ComplianceRule> validateChangeManagement(SystemContext ctx) {
List<ComplianceRule> rules = new ArrayList<>();
var config = ctx.securityProfileConfig.get().orElseThrow(
() -> new IllegalStateException("SecurityProfileConfiguration not set")
);
// CC8.1: Change tracking through CloudTrail
if (!config.isCloudTrailEnabled()) {
rules.add(ComplianceRule.fail(
"SOC2-CC8.1-CloudTrail",
"CloudTrail required for change tracking and audit",
"CloudTrailEnabledRule",
"Enable CloudTrail to record all infrastructure changes."
));
} else {
rules.add(ComplianceRule.pass("SOC2-CC8.1-CloudTrail", "CloudTrail change tracking enabled", "CloudTrailEnabledRule"));
}
// CC8.1: Configuration change detection
if (!config.isAwsConfigEnabled()) {
rules.add(ComplianceRule.fail(
"SOC2-CC8.1-Config",
"AWS Config recommended for change detection",
"Enable AWS Config to track configuration changes and maintain compliance."
));
} else {
rules.add(ComplianceRule.pass("SOC2-CC8.1-Config", "AWS Config change detection enabled"));
}
// CC8.1: Infrastructure as Code provides change control
rules.add(ComplianceRule.pass("SOC2-CC8.1-IaC", "Infrastructure as Code (CDK) provides version-controlled change management"));
LOG.info("SOC 2 CC8.1: Infrastructure as Code (CDK) provides version-controlled change management");
return rules;
}
/**
* A1.1, A1.2, A1.3: System Availability.
* The entity maintains, monitors, and evaluates system availability.
* (Only validated if organization claims Availability criteria)
*/
private List<ComplianceRule> validateAvailability(SystemContext ctx) {
List<ComplianceRule> rules = new ArrayList<>();
var config = ctx.securityProfileConfig.get().orElseThrow(
() -> new IllegalStateException("SecurityProfileConfiguration not set")
);
// Skip availability checks for non-production
if (ctx.security != SecurityProfile.PRODUCTION) {
return rules;
}
// A1.2: High availability configuration
if (!config.isMultiAzEnforced()) {
rules.add(ComplianceRule.fail(
"SOC2-A1.2-MultiAZ",
"Multi-AZ deployment required for high availability in production",
"Deploy across multiple availability zones."
));
} else {
rules.add(ComplianceRule.pass("SOC2-A1.2-MultiAZ", "Multi-AZ high availability enabled"));
}
// A1.2: Auto-scaling for availability
if (!config.isAutoScalingEnabled()) {
rules.add(ComplianceRule.fail(
"SOC2-A1.2-AutoScaling",
"Auto-scaling recommended for handling demand and maintaining availability",
"Enable auto-scaling to handle traffic spikes."
));
} else {
rules.add(ComplianceRule.pass("SOC2-A1.2-AutoScaling", "Auto-scaling enabled"));
}
// A1.3: Backup and recovery
if (!config.isAutomatedBackupEnabled()) {
rules.add(ComplianceRule.fail(
"SOC2-A1.3-Backup",
"Automated backups required for disaster recovery",
"Enable automated backups to ensure data can be recovered."
));
} else {
rules.add(ComplianceRule.pass("SOC2-A1.3-Backup", "Automated backups enabled"));
}
if (!config.isCrossRegionBackupEnabled()) {
rules.add(ComplianceRule.fail(
"SOC2-A1.3-CrossRegion",
"Cross-region backup recommended for disaster recovery",
"Implement geographic redundancy for business continuity."
));
} else {
rules.add(ComplianceRule.pass("SOC2-A1.3-CrossRegion", "Cross-region backup enabled"));
}
return rules;
}
/**
* C1.1, C1.2: Confidentiality.
* The entity protects confidential information to meet commitments and system requirements.
* (Only validated if organization claims Confidentiality criteria)
*/
private List<ComplianceRule> validateConfidentiality(SystemContext ctx) {
List<ComplianceRule> rules = new ArrayList<>();
var config = ctx.securityProfileConfig.get().orElseThrow(
() -> new IllegalStateException("SecurityProfileConfiguration not set")
);
// C1.1: Encryption for confidential data
if (!config.isEbsEncryptionEnabled()) {
rules.add(ComplianceRule.fail(
"SOC2-C1.1-EBS",
"EBS encryption required for confidential data at rest",
"EbsEncryptionRule",
"Enable EBS encryption."
));
} else {
rules.add(ComplianceRule.pass("SOC2-C1.1-EBS", "EBS encryption enabled", "EbsEncryptionRule"));
}
if (!config.isEfsEncryptionAtRestEnabled()) {
rules.add(ComplianceRule.fail(
"SOC2-C1.1-EFS",
"EFS encryption required for confidential file storage",
"Enable EFS encryption at rest."
));
} else {
rules.add(ComplianceRule.pass("SOC2-C1.1-EFS", "EFS encryption enabled"));
}
if (!config.isS3EncryptionEnabled()) {
rules.add(ComplianceRule.fail(
"SOC2-C1.1-S3",
"S3 encryption required for confidential data in object storage",
"S3BucketEncryptionRule",
"Enable S3 encryption."
));
} else {
rules.add(ComplianceRule.pass("SOC2-C1.1-S3", "S3 encryption enabled", "S3BucketEncryptionRule"));
}
// C1.2: Access restrictions for confidential data
if (ctx.cfc.networkMode() == NetworkMode.PUBLIC) {
rules.add(ComplianceRule.fail(
"SOC2-C1.2-Network",
"Private network mode required for confidential data",
"Use 'private-with-nat' to restrict access to confidential systems."
));
} else {
rules.add(ComplianceRule.pass("SOC2-C1.2-Network", "Private network mode configured"));
}
return rules;
}
/**
* Generate SOC 2 Trust Services Criteria compliance report.
*/
public String generateComplianceReport(SystemContext ctx) {
StringBuilder report = new StringBuilder();
report.append("\n=== SOC 2 Trust Services Criteria Compliance Report ===\n\n");
var config = ctx.securityProfileConfig.get().orElseThrow(
() -> new IllegalStateException("SecurityProfileConfiguration not set")
);
report.append("Security Profile: ").append(ctx.security).append("\n");
report.append("Service Type: ").append(ctx.cfc.tier()).append("\n\n");
report.append("Common Criteria - Security (CC):\n");
report.append(" ✓ CC6.1 - Access Controls: ").append(ctx.iamProfile != null ? "ENABLED" : "DISABLED").append("\n");
report.append(" ✓ CC6.2 - Authentication: ").append(ctx.cfc.authMode() != AuthMode.NONE ? "ENABLED" : "DISABLED").append("\n");
report.append(" ✓ CC6.6 - Network Segmentation: ").append(ctx.vpc.get().isPresent() ? "ENABLED" : "DISABLED").append("\n");
report.append(" ✓ CC6.7 - Encryption in Transit: ").append(ctx.cfc.enableSsl() && (ctx.cert.get().isPresent() || (ctx.cfc.domain() == null && ctx.cfc.fqdn() == null)) ? "ENABLED" : "DISABLED").append("\n");
report.append(" ✓ CC7.2 - System Monitoring: ").append(config.isSecurityMonitoringEnabled() ? "ENABLED" : "DISABLED").append("\n");
report.append(" ✓ CC8.1 - Change Management: ").append(config.isCloudTrailEnabled() ? "ENABLED" : "DISABLED").append("\n");
report.append("\n");
if (ctx.security == SecurityProfile.PRODUCTION) {
report.append("Availability Criteria (A):\n");
report.append(" ✓ A1.2 - High Availability: ").append(config.isMultiAzEnforced() ? "ENABLED" : "DISABLED").append("\n");
report.append(" ✓ A1.2 - Auto-Scaling: ").append(config.isAutoScalingEnabled() ? "ENABLED" : "DISABLED").append("\n");
report.append(" ✓ A1.3 - Backup & Recovery: ").append(config.isAutomatedBackupEnabled() ? "ENABLED" : "DISABLED").append("\n");
report.append("\n");
}
report.append("Confidentiality Criteria (C):\n");
report.append(" ✓ C1.1 - Encryption at Rest: ").append(config.isEbsEncryptionEnabled() ? "ENABLED" : "DISABLED").append("\n");
report.append(" ✓ C1.2 - Access Restrictions: ").append(ctx.cfc.networkMode() != NetworkMode.PUBLIC ? "ENABLED" : "DISABLED").append("\n");
report.append("\n");
report.append("Note: SOC 2 audit requires independent CPA firm examination.\n");
report.append("Type I: Design of controls | Type II: Operating effectiveness over time\n");
report.append("\n");
return report.toString();
}
}