HipaaRules.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.RuntimeType;
import com.cloudforge.core.enums.SecurityProfile;
import com.cloudforge.core.interfaces.FrameworkRules;
import com.cloudforgeci.api.core.SystemContext;
import com.cloudforgeci.api.interfaces.SecurityProfileConfiguration;
import software.amazon.awscdk.services.logs.RetentionDays;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.logging.Logger;
import java.util.Set;
/**
* HIPAA Security Rule compliance validation.
*
* Validates HIPAA Security Rule requirements (45 CFR Part 160 and Part 164, Subparts A and C).
*
* HIPAA Security Rule Coverage:
* - §164.308(a)(1): Security Management Process
* - §164.308(a)(3): Workforce Security
* - §164.308(a)(4): Information Access Management
* - §164.312(a)(1): Access Control
* - §164.312(a)(2)(iv): Encryption and Decryption
* - §164.312(b): Audit Controls
* - §164.312(c)(1): Integrity
* - §164.312(d): Person or Entity Authentication
* - §164.312(e)(1): Transmission Security
* - §164.316(b)(1): Policies and Procedures
* - §164.316(b)(2)(i): Retention
*
* Note: HIPAA distinguishes between "Required" and "Addressable" specifications.
* This validator enforces both for maximum protection of PHI (Protected Health Information).
*
* @since 3.0.0
*/
@ComplianceFramework(
value = "HIPAA",
priority = 10,
displayName = "HIPAA Security Rule",
description = "Validates HIPAA Security Rule requirements for PHI protection"
)
public class HipaaRules implements FrameworkRules<SystemContext> {
private static final Logger LOG = Logger.getLogger(HipaaRules.class.getName());
/** Controls that still block STAGING synthesis: authentication, network isolation,
* SSL/TLS in transit, encryption at rest, audit logging, and backups -- PHI may exist
* in STAGING, so these can't be downgraded to a non-blocking finding there.
* Everything else in STAGING is a visible, non-blocking finding. */
private static final Set<String> STAGING_BLOCKING_RULES = Set.of(
"HIPAA-164.312(a)(2)(i)-Auth", "HIPAA-164.312(d)-Auth",
"HIPAA-164.312(a)(1)-NetworkAccess", "HIPAA-164.312(e)(1)-Network",
"HIPAA-164.312(e)(2)(i)-SSL", "HIPAA-164.312(e)(2)(i)-TLS",
"HIPAA-164.312(a)(2)(iv)-EncryptionAtRest", "HIPAA-164.312(a)(2)(iv)-LogEncryption",
"HIPAA-164.312(b)-CloudTrail", "HIPAA-164.312(b)-FlowLogs", "HIPAA-164.312(b)-ALB",
"HIPAA-164.312(c)(1)-AuditLogImmutability", "HIPAA-164.310(d)(2)(iii)-Backup",
"HIPAA-164.312(e)(2)(ii)-EFS"
);
// HIPAA requires 6 years retention for documentation
private static final int HIPAA_MIN_RETENTION_DAYS = 365 * 6; // 2190 days
/**
* Install HIPAA compliance validation rules for production and staging environments.
* HIPAA applies to any environment that processes PHI.
*/
@Override
public void install(SystemContext ctx) {
// HIPAA enforcement for production and staging (PHI may exist in both)
if (ctx.security != SecurityProfile.PRODUCTION && ctx.security != SecurityProfile.STAGING) {
LOG.info("HIPAA validation rules enforced for PRODUCTION and STAGING profiles only");
return;
}
LOG.info("Installing HIPAA Security Rule 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<>();
// Administrative Safeguards
rules.addAll(validateSecurityManagement(ctx));
rules.addAll(validateAccessManagement(ctx));
// Physical Safeguards (infrastructure level)
rules.addAll(validatePhysicalSafeguards(ctx));
// Technical Safeguards
rules.addAll(validateAccessControls(ctx));
rules.addAll(validateAuditControls(ctx));
rules.addAll(validateIntegrityControls(ctx));
rules.addAll(validateAuthenticationControls(ctx));
rules.addAll(validateTransmissionSecurity(ctx));
// Organizational Requirements
rules.addAll(validateRetentionRequirements(ctx));
// Matrix-required controls not covered above
rules.addAll(validateMatrixControls(
ctx.securityProfileConfig.get().orElseThrow(
() -> new IllegalStateException("SecurityProfileConfiguration not set")),
ctx.security,
ctx.runtime,
ctx.dbConnection.get().isPresent(),
ctx.maxInstanceCapacity.get().orElse(ctx.cfc.maxInstanceCapacity()),
ctx.applicationSpec.get()
.map(com.cloudforge.core.interfaces.ApplicationSpec::supportsAutoScaling).orElse(true)));
return ComplianceEnforcement.resolve(
"HIPAA", rules, complianceMode, ctx.security, STAGING_BLOCKING_RULES, LOG);
});
}
/**
* §164.308(a)(1) - Security Management Process.
* Risk analysis, risk management, sanction policy, information system activity review.
*/
private List<ComplianceRule> validateSecurityManagement(SystemContext ctx) {
List<ComplianceRule> rules = new ArrayList<>();
var config = ctx.securityProfileConfig.get().orElseThrow(
() -> new IllegalStateException("SecurityProfileConfiguration not set")
);
// §164.308(a)(1)(ii)(D) - Information System Activity Review
if (!config.isSecurityMonitoringEnabled()) {
rules.add(ComplianceRule.fail(
"HIPAA-164.308(a)(1)(ii)(D)-Monitoring",
"Security monitoring required for information system activity review (HIPAA §164.308(a)(1)(ii)(D))",
"Enable security monitoring to detect and respond to security incidents."
));
} else {
rules.add(ComplianceRule.pass(
"HIPAA-164.308(a)(1)(ii)(D)-Monitoring",
"Security monitoring enabled for information system activity review (HIPAA §164.308(a)(1)(ii)(D))"
));
}
if (!config.isGuardDutyEnabled()) {
rules.add(ComplianceRule.fail(
"HIPAA-164.308(a)(1)(ii)(D)-GuardDuty",
"GuardDuty threat detection required (HIPAA §164.308(a)(1)(ii)(D))",
"GuardDutyEnabled",
"GuardDuty threat detection required for security incident identification."
));
} else {
rules.add(ComplianceRule.pass(
"HIPAA-164.308(a)(1)(ii)(D)-GuardDuty",
"GuardDuty threat detection enabled (HIPAA §164.308(a)(1)(ii)(D))",
"GuardDutyEnabled"
));
}
return rules;
}
/**
* §164.308(a)(4) - Information Access Management.
* Access authorization, access establishment and modification.
*/
private List<ComplianceRule> validateAccessManagement(SystemContext ctx) {
List<ComplianceRule> rules = new ArrayList<>();
// §164.308(a)(4)(ii)(C) - Access Establishment and Modification
if (ctx.iamProfile == null) {
rules.add(ComplianceRule.fail(
"HIPAA-164.308(a)(4)(ii)(C)-IAM",
"IAM profile required for access control management (HIPAA §164.308(a)(4)(ii)(C))",
"IAMPasswordPolicyRule",
"Implement role-based access controls for PHI access."
));
} else {
rules.add(ComplianceRule.pass(
"HIPAA-164.308(a)(4)(ii)(C)-IAM",
"IAM profile configured for access control management (HIPAA §164.308(a)(4)(ii)(C))",
"IAMPasswordPolicyRule"
));
}
return rules;
}
/**
* Physical Safeguards - Infrastructure level controls.
* §164.310 - Facility Access Controls, Workstation Security, Device and Media Controls.
*/
private List<ComplianceRule> validatePhysicalSafeguards(SystemContext ctx) {
List<ComplianceRule> rules = new ArrayList<>();
var config = ctx.securityProfileConfig.get().orElseThrow(
() -> new IllegalStateException("SecurityProfileConfiguration not set")
);
// §164.310(d)(2)(iii) - Data Backup and Storage
if (!config.isAutomatedBackupEnabled()) {
rules.add(ComplianceRule.fail(
"HIPAA-164.310(d)(2)(iii)-Backup",
"Automated backup required for PHI data protection (HIPAA §164.310(d)(2)(iii))",
"EfsBackupEnabled",
"Enable automated backups to ensure data availability and disaster recovery."
));
} else {
rules.add(ComplianceRule.pass(
"HIPAA-164.310(d)(2)(iii)-Backup",
"Automated backup enabled for PHI data protection (HIPAA §164.310(d)(2)(iii))",
"EfsBackupEnabled"
));
}
// Cross-region backup for disaster recovery
boolean isProdOrStaging = ctx.security == SecurityProfile.PRODUCTION || ctx.security == SecurityProfile.STAGING;
if (isProdOrStaging && !config.isCrossRegionBackupEnabled()) {
rules.add(ComplianceRule.fail(
"HIPAA-164.310(d)(2)(iii)-CrossRegion",
"Cross-region backup recommended for production PHI (HIPAA §164.310(d)(2)(iii))",
"Implement geographic redundancy for disaster recovery."
));
} else if (isProdOrStaging) {
rules.add(ComplianceRule.pass(
"HIPAA-164.310(d)(2)(iii)-CrossRegion",
"Cross-region backup enabled for production PHI (HIPAA §164.310(d)(2)(iii))"
));
}
return rules;
}
/**
* §164.312(a)(1) - Access Control.
* Unique user identification, emergency access, automatic logoff, encryption and decryption.
*/
private List<ComplianceRule> validateAccessControls(SystemContext ctx) {
List<ComplianceRule> rules = new ArrayList<>();
// §164.312(a)(2)(i) - Unique User Identification (Required)
AuthMode authMode = ctx.cfc.authMode();
if (authMode == AuthMode.NONE) {
rules.add(ComplianceRule.fail(
"HIPAA-164.312(a)(2)(i)-Auth",
"Unique user identification required for PHI access (HIPAA §164.312(a)(2)(i))",
"Configure authMode = 'alb-oidc', 'jenkins-oidc', or 'application-oidc' to identify and authenticate users."
));
} else {
rules.add(ComplianceRule.pass(
"HIPAA-164.312(a)(2)(i)-Auth",
"Unique user identification enabled for PHI access (HIPAA §164.312(a)(2)(i))"
));
}
// Validate network access controls
if (ctx.albSg.get().isEmpty()) {
rules.add(ComplianceRule.fail(
"HIPAA-164.312(a)(1)-NetworkAccess",
"Access controls required at network level (HIPAA §164.312(a)(1))",
"Security groups must restrict access to PHI systems."
));
} else {
rules.add(ComplianceRule.pass(
"HIPAA-164.312(a)(1)-NetworkAccess",
"Network access controls configured (HIPAA §164.312(a)(1))"
));
}
return rules;
}
/**
* §164.312(b) - Audit Controls (Required).
* Hardware, software, and procedural mechanisms to record and examine activity.
*/
private List<ComplianceRule> validateAuditControls(SystemContext ctx) {
List<ComplianceRule> rules = new ArrayList<>();
var config = ctx.securityProfileConfig.get().orElseThrow(
() -> new IllegalStateException("SecurityProfileConfiguration not set")
);
// §164.312(b) - Audit Controls (Required)
if (!config.isCloudTrailEnabled()) {
rules.add(ComplianceRule.fail(
"HIPAA-164.312(b)-CloudTrail",
"CloudTrail audit logging required (HIPAA §164.312(b))",
"CloudTrailEnabledRule",
"Enable CloudTrail to record configured API activity."
));
} else {
rules.add(ComplianceRule.pass(
"HIPAA-164.312(b)-CloudTrail",
"CloudTrail audit logging enabled (HIPAA §164.312(b))",
"CloudTrailEnabledRule"
));
}
if (!config.isFlowLogsEnabled()) {
rules.add(ComplianceRule.fail(
"HIPAA-164.312(b)-FlowLogs",
"VPC Flow Logs required to audit network access (HIPAA §164.312(b))",
"VpcFlowLogsEnabled",
"Enable Flow Logs to record all network traffic."
));
} else {
rules.add(ComplianceRule.pass(
"HIPAA-164.312(b)-FlowLogs",
"VPC Flow Logs enabled for network access audit (HIPAA §164.312(b))",
"VpcFlowLogsEnabled"
));
}
if (!config.isAlbAccessLoggingEnabled()) {
rules.add(ComplianceRule.fail(
"HIPAA-164.312(b)-ALB",
"ALB access logging required (HIPAA §164.312(b))",
"AlbAccessLogsEnabled",
"Enable ALB access logs to record incoming requests."
));
} else {
rules.add(ComplianceRule.pass(
"HIPAA-164.312(b)-ALB",
"ALB access logging enabled (HIPAA §164.312(b))",
"AlbAccessLogsEnabled"
));
}
return rules;
}
/**
* §164.312(c)(1) - Integrity (Required).
* Policies and procedures to protect ePHI from improper alteration or destruction.
*/
private List<ComplianceRule> validateIntegrityControls(SystemContext ctx) {
List<ComplianceRule> rules = new ArrayList<>();
var config = ctx.securityProfileConfig.get().orElseThrow(
() -> new IllegalStateException("SecurityProfileConfiguration not set")
);
// §164.312(c)(2) - Mechanism to Authenticate ePHI (Addressable - we enforce)
if (!config.isCloudTrailEnabled()) {
rules.add(ComplianceRule.fail(
"HIPAA-164.312(c)(2)-Integrity",
"CloudTrail log file validation required for ePHI integrity (HIPAA §164.312(c)(2))",
"CloudTrailEnabledRule",
"Enable CloudTrail with file validation to detect unauthorized modifications."
));
} else {
rules.add(ComplianceRule.pass(
"HIPAA-164.312(c)(2)-Integrity",
"CloudTrail log file validation enabled for ePHI integrity (HIPAA §164.312(c)(2))",
"CloudTrailEnabledRule"
));
// File integrity monitoring via CloudTrail
LOG.info("HIPAA §164.312(c)(2): CloudTrail provides log file validation for integrity verification");
}
return rules;
}
/**
* §164.312(d) - Person or Entity Authentication (Required).
* Procedures to verify that a person or entity seeking access to ePHI is the one claimed.
*/
private List<ComplianceRule> validateAuthenticationControls(SystemContext ctx) {
List<ComplianceRule> rules = new ArrayList<>();
// §164.312(d) - Authentication (Required)
AuthMode authMode = ctx.cfc.authMode();
if (authMode == AuthMode.NONE) {
rules.add(ComplianceRule.fail(
"HIPAA-164.312(d)-Auth",
"Authentication required for all users accessing ePHI (HIPAA §164.312(d))",
"Configure authMode = 'alb-oidc', 'jenkins-oidc', or 'application-oidc' with strong authentication mechanism."
));
} else {
rules.add(ComplianceRule.pass(
"HIPAA-164.312(d)-Auth",
"Authentication enabled for ePHI access (HIPAA §164.312(d))"
));
}
// Multi-factor authentication (Addressable - but highly recommended)
if (authMode == AuthMode.ALB_OIDC || authMode == AuthMode.APPLICATION_OIDC) {
// Check if using Cognito with MFA (compliant) or SSO (requires ssoInstanceArn)
boolean usingCognitoWithMfa = Boolean.TRUE.equals(ctx.cfc.cognitoAutoProvision())
&& Boolean.TRUE.equals(ctx.cfc.cognitoMfaEnabled());
boolean hasValidSso = ctx.cfc.ssoInstanceArn() != null && !ctx.cfc.ssoInstanceArn().isEmpty();
if (!usingCognitoWithMfa && !hasValidSso) {
rules.add(ComplianceRule.fail(
"HIPAA-164.312(d)-MFA",
"Multi-factor authentication recommended for ePHI access (HIPAA §164.312(d))",
"IAMMfaEnabled",
"Either: (1) Enable Cognito MFA: cognitoAutoProvision = true, cognitoMfaEnabled = true " +
"OR (2) Configure AWS IAM Identity Center: provide ssoInstanceArn with MFA enforcement."
));
} else {
rules.add(ComplianceRule.pass(
"HIPAA-164.312(d)-MFA",
"Multi-factor authentication configured for ePHI access (HIPAA §164.312(d))",
"IAMMfaEnabled"
));
}
}
return rules;
}
/**
* §164.312(e)(1) - Transmission Security (Required).
* Technical security measures to guard against unauthorized access to ePHI during transmission.
*/
private List<ComplianceRule> validateTransmissionSecurity(SystemContext ctx) {
List<ComplianceRule> rules = new ArrayList<>();
var config = ctx.securityProfileConfig.get().orElseThrow(
() -> new IllegalStateException("SecurityProfileConfiguration not set")
);
// §164.312(e)(2)(i) - SSL/TLS must be enabled for encrypted ePHI transmission
if (!ctx.cfc.enableSsl()) {
rules.add(ComplianceRule.fail(
"HIPAA-164.312(e)(2)(i)-SSL",
"SSL/TLS must be enabled for encrypted transmission of ePHI (HIPAA §164.312(e)(2)(i))",
"ALBHttpsOnly",
"Set enableSsl=true for production HIPAA compliance."
));
} else {
rules.add(ComplianceRule.pass(
"HIPAA-164.312(e)(2)(i)-SSL",
"SSL/TLS enabled for transmission security (HIPAA §164.312(e)(2)(i))",
"ALBHttpsOnly"
));
}
// §164.312(e)(2)(i) - Integrity Controls (Addressable - we enforce)
if (ctx.cert.get().isEmpty()) {
rules.add(ComplianceRule.fail(
"HIPAA-164.312(e)(2)(i)-TLS",
"TLS certificate required for transmission integrity and confidentiality (HIPAA §164.312(e)(2)(i))",
"ALBHttpsOnly",
"Configure ACM certificate for HTTPS communication."
));
} else {
rules.add(ComplianceRule.pass(
"HIPAA-164.312(e)(2)(i)-TLS",
"TLS certificate configured for transmission security (HIPAA §164.312(e)(2)(i))",
"ALBHttpsOnly"
));
}
// §164.312(e)(2)(ii) - Encryption (Addressable - we enforce)
if (!config.isEfsEncryptionInTransitEnabled()) {
rules.add(ComplianceRule.fail(
"HIPAA-164.312(e)(2)(ii)-EFS",
"EFS encryption in transit required for ePHI transmission security (HIPAA §164.312(e)(2)(ii))",
"EfsEncryptionRule",
"Enable EFS in-transit encryption to protect PHI during file system access."
));
} else {
rules.add(ComplianceRule.pass(
"HIPAA-164.312(e)(2)(ii)-EFS",
"EFS encryption in transit enabled (HIPAA §164.312(e)(2)(ii))",
"EfsEncryptionRule"
));
}
// Network isolation
if (ctx.cfc.networkMode() == NetworkMode.PUBLIC) {
rules.add(ComplianceRule.fail(
"HIPAA-164.312(e)(1)-Network",
"Private network mode required for PHI systems (HIPAA §164.312(e)(1))",
"Use 'private-with-nat' to isolate PHI systems from public internet."
));
} else {
rules.add(ComplianceRule.pass(
"HIPAA-164.312(e)(1)-Network",
"Private network mode configured for PHI systems (HIPAA §164.312(e)(1))"
));
}
return rules;
}
/**
* §164.316(b)(2)(i) - Retention Requirements.
* Retain documentation for 6 years from the date of creation or last use.
*/
private List<ComplianceRule> validateRetentionRequirements(SystemContext ctx) {
List<ComplianceRule> rules = new ArrayList<>();
var config = ctx.securityProfileConfig.get().orElseThrow(
() -> new IllegalStateException("SecurityProfileConfiguration not set")
);
// §164.316(b)(2)(i) - Documentation must be retained for 6 years
var retentionDays = config.getLogRetentionDays();
if (!isRetentionSufficient(retentionDays)) {
rules.add(ComplianceRule.fail(
"HIPAA-164.316(b)(2)(i)-Retention",
"Log retention must be at least 6 years (HIPAA §164.316(b)(2)(i))",
"CloudWatchLogGroupRetention",
"Log retention must be at least 6 years (2190 days). Current: " +
retentionDays.toString() + ". " +
"HIPAA requires 6-year retention for all documentation related to HIPAA compliance."
));
} else {
rules.add(ComplianceRule.pass(
"HIPAA-164.316(b)(2)(i)-Retention",
"Log retention meets 6-year requirement (HIPAA §164.316(b)(2)(i))",
"CloudWatchLogGroupRetention"
));
}
return rules;
}
/**
* Check if log retention meets HIPAA requirement (6 years).
* §164.316(b)(2)(i): Retain documentation for 6 years.
*/
private boolean isRetentionSufficient(RetentionDays retention) {
// HIPAA STRICTLY requires 6 years (2190 days) - §164.316(b)(2)(i)
// ONLY accept SIX_YEARS (2192 days) or longer
// TWO_YEARS (731 days), THREE_YEARS (1096 days), FIVE_YEARS (1827 days) do NOT meet HIPAA requirement
return retention == RetentionDays.SIX_YEARS ||
retention == RetentionDays.SEVEN_YEARS ||
retention == RetentionDays.EIGHT_YEARS ||
retention == RetentionDays.NINE_YEARS ||
retention == RetentionDays.TEN_YEARS ||
retention == RetentionDays.INFINITE;
}
/**
* §164.312(a)(2)(iv) - Encryption and Decryption, and other {@link ComplianceMatrix} controls
* REQUIRED for HIPAA that the checks above do not already cover. Each check reads the security
* profile, so it fails only when the profile leaves a required control off. Controls already
* owned by the always-load cross-framework rule classes (KMS rotation, Secrets Manager, database
* access control, and similar) are left to those classes rather than duplicated here.
*/
List<ComplianceRule> validateMatrixControls(
SecurityProfileConfiguration config,
SecurityProfile profile,
RuntimeType runtime,
boolean databaseProvisioned,
Integer maxInstances,
boolean specSupportsScaling) {
List<ComplianceRule> rules = new ArrayList<>();
// §164.312(a)(2)(iv): encryption at rest for EBS, EFS and S3 -- REQUIRED, and previously
// unchecked here despite generateComplianceReport() printing its status.
if (!config.isEbsEncryptionEnabled() || !config.isEfsEncryptionAtRestEnabled()
|| !config.isS3EncryptionEnabled()) {
rules.add(ComplianceRule.fail(
"HIPAA-164.312(a)(2)(iv)-EncryptionAtRest",
"Encryption at rest required for EBS, EFS and S3 storing ePHI (HIPAA §164.312(a)(2)(iv))",
"EbsEncryptionRule",
"Enable encryption for all storage volumes and buckets that may hold ePHI."
));
} else {
rules.add(ComplianceRule.pass(
"HIPAA-164.312(a)(2)(iv)-EncryptionAtRest",
"Encryption at rest enabled for EBS, EFS and S3 (HIPAA §164.312(a)(2)(iv))",
"EbsEncryptionRule"
));
}
// §164.312(a)(2)(iv): CloudWatch Logs may contain ePHI in application log output.
// Both findings are in STAGING_BLOCKING_RULES, so they must be generated at STAGING too,
// not just PRODUCTION -- otherwise a disabled setting in STAGING produces no finding at
// all for the blocking set to catch.
if (profile == SecurityProfile.PRODUCTION || profile == SecurityProfile.STAGING) {
if (!config.isCloudWatchLogsKmsEncryptionEnabled()) {
rules.add(ComplianceRule.fail(
"HIPAA-164.312(a)(2)(iv)-LogEncryption",
"CloudWatch log groups must be encrypted with a customer-managed KMS key (HIPAA §164.312(a)(2)(iv))",
"Enable cloudWatchLogsKmsEncryptionEnabled."
));
} else {
rules.add(ComplianceRule.pass(
"HIPAA-164.312(a)(2)(iv)-LogEncryption",
"CloudWatch log groups encrypted with a customer-managed KMS key (HIPAA §164.312(a)(2)(iv))"
));
}
// §164.312(c)(1): audit logs must be tamper-evident.
if (!config.isS3ObjectLockEnabled()) {
rules.add(ComplianceRule.fail(
"HIPAA-164.312(c)(1)-AuditLogImmutability",
"S3 Object Lock required so audit logs cannot be altered or deleted (HIPAA §164.312(c)(1))",
"Enable S3 Object Lock on the audit-log buckets."
));
} else {
rules.add(ComplianceRule.pass(
"HIPAA-164.312(c)(1)-AuditLogImmutability",
"S3 Object Lock enabled on audit-log buckets (HIPAA §164.312(c)(1))"
));
}
// §164.308(a)(8): evaluation of security measures -- CloudTrail plus AWS Config
// together give a record of every change and detect drift from the deployed baseline.
if (config.isCloudTrailEnabled() && config.isAwsConfigEnabled()) {
rules.add(ComplianceRule.pass(
"HIPAA-164.308(a)(8)-ChangeManagement",
"Change tracking enabled via CloudTrail and AWS Config (HIPAA §164.308(a)(8))"
));
} else {
rules.add(ComplianceRule.fail(
"HIPAA-164.308(a)(8)-ChangeManagement",
"Change control tracking required (HIPAA §164.308(a)(8))",
"Enable both CloudTrail and AWS Config to track and detect infrastructure changes."
));
}
}
// §164.312(a)(1): EC2 instance metadata is a documented credential-theft vector.
if (runtime == RuntimeType.EC2) {
if (!config.isImdsv2Required()) {
rules.add(ComplianceRule.fail(
"HIPAA-164.312(a)(1)-IMDSv2",
"EC2 instances must require IMDSv2 (HIPAA §164.312(a)(1))",
"Set imdsv2Required=true."
));
} else {
rules.add(ComplianceRule.pass(
"HIPAA-164.312(a)(1)-IMDSv2",
"EC2 instances require IMDSv2 tokens (HIPAA §164.312(a)(1))"
));
}
}
// §164.308(a)(7)(ii)(B): contingency plan / disaster recovery -- database availability and
// protection, only when a database was actually provisioned.
if (profile == SecurityProfile.PRODUCTION && databaseProvisioned) {
if (!config.isRdsDatabaseMultiAzEnabled()) {
rules.add(ComplianceRule.fail(
"HIPAA-164.308(a)(7)(ii)(B)-DatabaseMultiAZ",
"RDS Multi-AZ required for database availability (HIPAA §164.308(a)(7)(ii)(B))",
"Enable Multi-AZ on the RDS instance."
));
} else {
rules.add(ComplianceRule.pass(
"HIPAA-164.308(a)(7)(ii)(B)-DatabaseMultiAZ",
"RDS Multi-AZ enabled for database availability (HIPAA §164.308(a)(7)(ii)(B))"
));
}
if (!config.isRdsDeletionProtectionEnabled()) {
rules.add(ComplianceRule.fail(
"HIPAA-164.310(d)(2)(iii)-DatabaseDeletionProtection",
"RDS deletion protection required to prevent accidental loss of ePHI (HIPAA §164.310(d)(2)(iii))",
"Enable RDS deletion protection."
));
} else {
rules.add(ComplianceRule.pass(
"HIPAA-164.310(d)(2)(iii)-DatabaseDeletionProtection",
"RDS deletion protection enabled (HIPAA §164.310(d)(2)(iii))"
));
}
}
// §164.308(a)(7)(ii)(B): high availability, for applications that can run more than one
// instance -- a single-instance deployment has nothing to make highly available.
if (profile == SecurityProfile.PRODUCTION) {
if (Soc2Rules.autoScalingApplies(specSupportsScaling, maxInstances)) {
if (!config.isMultiAzEnforced() || !config.isAutoScalingEnabled()) {
rules.add(ComplianceRule.fail(
"HIPAA-164.308(a)(7)(ii)(B)-HighAvailability",
"Multi-AZ deployment and auto-scaling required for high availability (HIPAA §164.308(a)(7)(ii)(B))",
"Deploy across multiple availability zones and enable auto-scaling."
));
} else {
rules.add(ComplianceRule.pass(
"HIPAA-164.308(a)(7)(ii)(B)-HighAvailability",
"Multi-AZ deployment and auto-scaling enabled (HIPAA §164.308(a)(7)(ii)(B))"
));
}
}
}
return rules;
}
/**
* Controls checked across every {@code validate*} method above (not just {@link
* #validateMatrixControls}) -- see {@link FrameworkRules#claimedControls}. Controls the matrix
* marks REQUIRED for HIPAA but left off this list (KMS_KEY_ROTATION, SECRETS_MANAGER,
* SECRETS_ROTATION, DATABASE_PITR, CLOUDTRAIL_INSIGHTS, ROOT_ACCOUNT_PROTECTION,
* CREDENTIAL_ROTATION, DATABASE_ACCESS_CONTROL, CONTAINER_SECURITY, API_SECURITY,
* LAMBDA_SECURITY, DATABASE_LOGGING, SNS_KMS_ENCRYPTION, SENSITIVE_DATA_DISCOVERY,
* VULNERABILITY_MANAGEMENT) are intentionally owned by the always-load
* cross-framework classes instead (KeyManagementRules, DatabaseSecurityRules, IamSecurityRules,
* and similar) -- a sync check needs the union of every installed framework's claims, not just
* this one's, to see the full picture.
*/
@Override
public Set<String> claimedControls() {
return Set.of(
"SECURITY_MONITORING", "THREAT_DETECTION", "ACCESS_CONTROL", "BACKUP_RECOVERY",
"AUTHENTICATION", "NETWORK_SEGMENTATION", "AUDIT_LOGGING", "NETWORK_FLOW_LOGS",
"HTTPS_STRICT", "ENCRYPTION_IN_TRANSIT", "LOG_RETENTION",
"ENCRYPTION_AT_REST", "CLOUDWATCH_LOGS_KMS_ENCRYPTION", "S3_OBJECT_LOCK",
"EC2_IMDSV2", "DATABASE_MULTI_AZ", "DELETION_PROTECTION", "HIGH_AVAILABILITY",
"CHANGE_MANAGEMENT"
);
}
/**
* Generate HIPAA Security Rule compliance report.
*/
public String generateComplianceReport(SystemContext ctx) {
StringBuilder report = new StringBuilder();
report.append("\n=== HIPAA Security Rule 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("Environment: ").append(ctx.cfc.env()).append("\n\n");
report.append("Administrative Safeguards (§164.308):\n");
report.append(" ✓ Security Management Process (§164.308(a)(1)): ").append(config.isSecurityMonitoringEnabled() ? "ENABLED" : "DISABLED").append("\n");
report.append(" ✓ Information Access Management (§164.308(a)(4)): ").append(ctx.iamProfile != null ? "ENABLED" : "DISABLED").append("\n");
report.append("\n");
report.append("Physical Safeguards (§164.310):\n");
report.append(" ✓ Automated Backup (§164.310(d)(2)(iii)): ").append(config.isAutomatedBackupEnabled() ? "ENABLED" : "DISABLED").append("\n");
report.append(" ✓ Cross-Region Backup (§164.310(d)(2)(iii)): ").append(config.isCrossRegionBackupEnabled() ? "ENABLED" : "DISABLED").append("\n");
report.append("\n");
report.append("Technical Safeguards (§164.312):\n");
report.append(" ✓ Access Control (§164.312(a)(1)): ").append(ctx.cfc.authMode() != AuthMode.NONE ? "ENABLED" : "DISABLED").append("\n");
report.append(" ✓ Audit Controls (§164.312(b)): ").append(config.isCloudTrailEnabled() ? "ENABLED" : "DISABLED").append("\n");
report.append(" ✓ Integrity Controls (§164.312(c)(1)): ").append(config.isCloudTrailEnabled() ? "ENABLED" : "DISABLED").append("\n");
report.append(" ✓ Authentication (§164.312(d)): ").append(ctx.cfc.authMode() != AuthMode.NONE ? "ENABLED" : "DISABLED").append("\n");
report.append(" ✓ Transmission Security (§164.312(e)(1)): ").append(ctx.cert.get().isPresent() ? "ENABLED" : "DISABLED").append("\n");
report.append(" ✓ Encryption at Rest (§164.312(a)(2)(iv)): ").append(config.isEbsEncryptionEnabled() ? "ENABLED" : "DISABLED").append("\n");
report.append(" ✓ Encryption in Transit (§164.312(e)(2)(ii)): ").append(config.isEfsEncryptionInTransitEnabled() ? "ENABLED" : "DISABLED").append("\n");
report.append("\n");
report.append("Organizational Requirements (§164.316):\n");
report.append(" ✓ Log Retention (§164.316(b)(2)(i)): ").append(config.getLogRetentionDays().toString());
if (!isRetentionSufficient(config.getLogRetentionDays())) {
report.append(" [WARNING: Less than 6 years required]");
}
report.append("\n");
report.append("\n");
report.append("Note: HIPAA requires 6-year retention. Implement S3 archival for logs older than CloudWatch retention.\n");
report.append("\n");
appendAdvisorySection(report, ctx);
return report.toString();
}
/**
* Recommendations for controls that are ADVISORY-tier (not blocking) and currently off.
* Runs the same checks {@link #install} does, so this reflects live findings, not a
* separate hand-maintained list.
*/
private void appendAdvisorySection(StringBuilder report, SystemContext ctx) {
List<ComplianceRule> rules = new ArrayList<>();
rules.addAll(validateSecurityManagement(ctx));
rules.addAll(validateAccessManagement(ctx));
rules.addAll(validatePhysicalSafeguards(ctx));
rules.addAll(validateAccessControls(ctx));
rules.addAll(validateAuditControls(ctx));
rules.addAll(validateIntegrityControls(ctx));
rules.addAll(validateAuthenticationControls(ctx));
rules.addAll(validateTransmissionSecurity(ctx));
rules.addAll(validateRetentionRequirements(ctx));
List<ComplianceRule> advisories = rules.stream().filter(ComplianceRule::isAdvisory).toList();
if (advisories.isEmpty()) {
return;
}
report.append("Recommendations (advisory, non-blocking):\n");
for (ComplianceRule rule : advisories) {
report.append(" - ").append(rule.ruleId()).append(": ").append(rule.description()).append("\n");
rule.recommendation().ifPresent(r -> report.append(" ").append(r).append("\n"));
}
report.append("\n");
}
}