IamSecurityRules.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.ComplianceMode;
import com.cloudforge.core.enums.SecurityProfile;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;
/**
* IAM security compliance validation rules.
*
* <p>These rules enforce IAM policy and role security requirements across multiple
* compliance frameworks:</p>
* <ul>
* <li><b>PCI-DSS</b> - Req 7.1: Limit access by business need; Req 8.3: MFA</li>
* <li><b>HIPAA</b> - §164.312(a)(1): Access control; §164.312(d): Authentication</li>
* <li><b>SOC 2</b> - CC6.1: Logical access controls; CC6.2: User authentication</li>
* <li><b>GDPR</b> - Art.32(1)(b): Confidentiality and access control</li>
* </ul>
*
* <h2>Controls Implemented</h2>
* <ul>
* <li>Least privilege enforcement</li>
* <li>MFA requirements</li>
* <li>Root account protection</li>
* <li>Credential rotation</li>
* <li>KMS key policy security</li>
* </ul>
*
* @since 3.0.0
*/
@ComplianceFramework(
value = "IamSecurity",
priority = 0,
alwaysLoad = true,
displayName = "IAM Security",
description = "Cross-framework IAM policy and access control validation"
)
public class IamSecurityRules implements FrameworkRules<SystemContext> {
private static final Logger LOG = Logger.getLogger(IamSecurityRules.class.getName());
@Override
public void install(SystemContext ctx) {
LOG.info("Installing IAM security compliance validation rules for " + ctx.security);
ctx.getNode().addValidation(() -> {
List<ComplianceRule> rules = new ArrayList<>();
// Access control validation
rules.addAll(validateAccessControl(ctx));
// Authentication requirements
rules.addAll(validateAuthentication(ctx));
// Root account protection
rules.addAll(validateRootAccountProtection(ctx));
// Credential rotation
rules.addAll(validateCredentialRotation(ctx));
// Get all failed rules
List<ComplianceRule> failedRules = rules.stream()
.filter(rule -> !rule.passed())
.toList();
if (!failedRules.isEmpty()) {
LOG.warning("IAM Security validation found " + failedRules.size() + " recommendations");
failedRules.forEach(rule ->
LOG.warning(" - " + rule.description() + ": " + rule.errorMessage().orElse("")));
// For DEV and STAGING, these are advisory only
if (ctx.security == SecurityProfile.DEV || ctx.security == SecurityProfile.STAGING) {
return List.of();
}
// For PRODUCTION, return blocking failures
List<String> blockingRules = failedRules.stream()
.filter(rule -> isBlockingRule(ctx, rule.description()))
.map(rule -> rule.description() + ": " + rule.errorMessage().orElse(""))
.toList();
return blockingRules;
} else {
LOG.info("IAM Security validation passed (" + rules.size() + " checks)");
return List.of();
}
});
}
/**
* Validate access control settings (least privilege).
*/
private List<ComplianceRule> validateAccessControl(SystemContext ctx) {
List<ComplianceRule> rules = new ArrayList<>();
String complianceFrameworks = ctx.cfc.complianceFrameworks();
ComplianceMode complianceMode = ctx.cfc.complianceMode();
// Access control / least privilege
if (ctx.security == SecurityProfile.PRODUCTION) {
// Check if IAM profile is properly configured
boolean hasIamProfile = ctx.iamProfile != null;
ComplianceMatrix.ValidationResult result = ComplianceMatrix.validateControlMultiFramework(
ComplianceMatrix.SecurityControl.ACCESS_CONTROL,
complianceFrameworks,
hasIamProfile,
complianceMode
);
if (result == ComplianceMatrix.ValidationResult.FAIL) {
rules.add(ComplianceRule.fail(
"IAM-ACCESS-CONTROL",
"IAM role-based access control required for " + complianceFrameworks,
"Configure IAM roles with least privilege permissions. " +
"Required for PCI-DSS Req 7.1 and HIPAA access controls."
));
} else {
rules.add(ComplianceRule.pass(
"IAM-ACCESS-CONTROL",
"IAM access control configured"
));
}
// Check for overly permissive policies (advisory)
boolean leastPrivilegeReviewed = getBooleanSetting(ctx, "leastPrivilegeReviewed", false);
if (!leastPrivilegeReviewed) {
rules.add(ComplianceRule.fail(
"IAM-LEAST-PRIVILEGE",
"IAM policies should follow least privilege principle",
"Review IAM policies to ensure no wildcards (*) in Actions or Resources. " +
"Set leastPrivilegeReviewed = true after review."
));
} else {
rules.add(ComplianceRule.pass(
"IAM-LEAST-PRIVILEGE",
"IAM least privilege review completed"
));
}
}
return rules;
}
/**
* Validate authentication requirements.
*/
private List<ComplianceRule> validateAuthentication(SystemContext ctx) {
List<ComplianceRule> rules = new ArrayList<>();
var config = ctx.securityProfileConfig.get().orElse(null);
if (config == null) {
return rules;
}
String complianceFrameworks = ctx.cfc.complianceFrameworks();
ComplianceMode complianceMode = ctx.cfc.complianceMode();
// MFA requirement
if (ctx.security == SecurityProfile.PRODUCTION) {
boolean mfaRequired = config.isMfaRequired();
ComplianceMatrix.ValidationResult result = ComplianceMatrix.validateControlMultiFramework(
ComplianceMatrix.SecurityControl.AUTHENTICATION,
complianceFrameworks,
mfaRequired,
complianceMode
);
if (result == ComplianceMatrix.ValidationResult.FAIL) {
rules.add(ComplianceRule.fail(
"MFA-REQUIRED",
"Multi-factor authentication required for " + complianceFrameworks,
"MfaRequired",
"Enable MFA for user authentication. " +
"Required for PCI-DSS Req 8.3 and HIPAA §164.312(d). " +
"Set mfaRequired = true in security profile."
));
} else {
rules.add(ComplianceRule.pass(
"MFA-REQUIRED",
"Multi-factor authentication configured"
));
}
// Password policy
int minPasswordLength = config.getMinimumPasswordLength();
if (minPasswordLength < 12) {
rules.add(ComplianceRule.fail(
"PASSWORD-POLICY",
"Minimum password length should be 12+ characters for production",
"Configure minimum password length of 12+ characters. " +
"NIST SP 800-63B recommends 12+ character passwords."
));
} else {
rules.add(ComplianceRule.pass(
"PASSWORD-POLICY",
"Password policy meets requirements"
));
}
}
return rules;
}
/**
* Validate root account protection.
*/
private List<ComplianceRule> validateRootAccountProtection(SystemContext ctx) {
List<ComplianceRule> rules = new ArrayList<>();
String complianceFrameworks = ctx.cfc.complianceFrameworks();
ComplianceMode complianceMode = ctx.cfc.complianceMode();
// Root account protection
if (ctx.security == SecurityProfile.PRODUCTION) {
boolean rootMfaEnabled = getBooleanSetting(ctx, "rootMfaEnabled", false);
ComplianceMatrix.ValidationResult result = ComplianceMatrix.validateControlMultiFramework(
ComplianceMatrix.SecurityControl.ROOT_ACCOUNT_PROTECTION,
complianceFrameworks,
rootMfaEnabled,
complianceMode
);
if (result == ComplianceMatrix.ValidationResult.FAIL) {
rules.add(ComplianceRule.fail(
"ROOT-MFA",
"Root account MFA required for " + complianceFrameworks,
"Enable MFA on the AWS root account. " +
"Required for PCI-DSS Req 8.3 and FedRAMP. " +
"Set rootMfaEnabled = true after enabling MFA."
));
} else if (result == ComplianceMatrix.ValidationResult.WARN) {
LOG.warning("Root account MFA recommended for " + complianceFrameworks);
rules.add(ComplianceRule.pass(
"ROOT-MFA",
"Root account MFA recommended"
));
} else {
rules.add(ComplianceRule.pass(
"ROOT-MFA",
"Root account MFA enabled"
));
}
// Root access key check
boolean rootAccessKeysDisabled = getBooleanSetting(ctx, "rootAccessKeysDisabled", false);
if (!rootAccessKeysDisabled) {
rules.add(ComplianceRule.fail(
"ROOT-ACCESS-KEYS",
"Root account access keys should be disabled",
"Remove access keys from the root account. " +
"Use IAM roles for programmatic access. " +
"Set rootAccessKeysDisabled = true after removal."
));
} else {
rules.add(ComplianceRule.pass(
"ROOT-ACCESS-KEYS",
"Root account access keys disabled"
));
}
}
return rules;
}
/**
* Validate credential rotation settings.
*/
private List<ComplianceRule> validateCredentialRotation(SystemContext ctx) {
List<ComplianceRule> rules = new ArrayList<>();
String complianceFrameworks = ctx.cfc.complianceFrameworks();
ComplianceMode complianceMode = ctx.cfc.complianceMode();
// Credential rotation
if (ctx.security == SecurityProfile.PRODUCTION) {
boolean credentialRotation = getBooleanSetting(ctx, "credentialRotationEnabled", false);
ComplianceMatrix.ValidationResult result = ComplianceMatrix.validateControlMultiFramework(
ComplianceMatrix.SecurityControl.CREDENTIAL_ROTATION,
complianceFrameworks,
credentialRotation,
complianceMode
);
if (result == ComplianceMatrix.ValidationResult.FAIL) {
rules.add(ComplianceRule.fail(
"CREDENTIAL-ROTATION",
"Credential rotation required for " + complianceFrameworks,
"Configure automatic credential rotation (90 days or less). " +
"Required for PCI-DSS Req 8.2.4. " +
"Set credentialRotationEnabled = true when rotation is configured."
));
} else if (result == ComplianceMatrix.ValidationResult.WARN) {
LOG.warning("Credential rotation recommended for " + complianceFrameworks);
rules.add(ComplianceRule.pass(
"CREDENTIAL-ROTATION",
"Credential rotation recommended"
));
} else {
rules.add(ComplianceRule.pass(
"CREDENTIAL-ROTATION",
"Credential rotation configured"
));
}
// Unused credentials detection
boolean unusedCredentialsCheck = getBooleanSetting(ctx, "unusedCredentialsCheckEnabled", false);
if (!unusedCredentialsCheck) {
rules.add(ComplianceRule.fail(
"UNUSED-CREDENTIALS",
"Unused credentials should be identified and removed",
"Enable AWS Config rules to detect unused IAM credentials. " +
"Set unusedCredentialsCheckEnabled = true when monitoring is configured."
));
} else {
rules.add(ComplianceRule.pass(
"UNUSED-CREDENTIALS",
"Unused credentials monitoring enabled"
));
}
}
return rules;
}
/**
* Check if a rule failure should block deployment.
*
* <p>Most IAM rules are advisory because they involve operational controls
* that cannot be automatically verified during CDK synthesis. Examples:</p>
* <ul>
* <li>Root account MFA - requires manual AWS console configuration</li>
* <li>Credential rotation - requires organization-wide policy enforcement</li>
* <li>Access key management - requires manual IAM user management</li>
* </ul>
*
* <p>Only infrastructure-level IAM requirements (like role configuration) can block.</p>
*/
private boolean isBlockingRule(SystemContext ctx, String ruleDescription) {
String complianceFrameworks = ctx.cfc.complianceFrameworks();
boolean requiresPciDss = complianceFrameworks != null &&
complianceFrameworks.toUpperCase().contains("PCI-DSS");
boolean requiresHipaa = complianceFrameworks != null &&
complianceFrameworks.toUpperCase().contains("HIPAA");
// MFA for application users (Cognito) is blocking - can be configured via CDK
if (ruleDescription.contains("Multi-factor authentication") && (requiresPciDss || requiresHipaa)) {
return true;
}
// IAM role access control is blocking - can be configured via CDK
if (ruleDescription.contains("access control required") && (requiresPciDss || requiresHipaa)) {
return true;
}
// Root account MFA is ADVISORY - requires manual AWS console action
// Credential rotation is ADVISORY - requires organization-wide policy
// Access key management is ADVISORY - requires manual IAM management
// These cannot be automated via CDK synthesis
return false;
}
/**
* Get boolean setting from context with default value.
*/
private boolean getBooleanSetting(SystemContext ctx, String key, boolean defaultValue) {
try {
var method = ctx.cfc.getClass().getMethod(key);
Boolean value = (Boolean) method.invoke(ctx.cfc);
return value != null ? value : defaultValue;
} catch (Exception e) {
return defaultValue;
}
}
}