KeyManagementRules.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;

/**
 * Key Management compliance validation rules.
 *
 * <p>These rules enforce cryptographic key management best practices across
 * multiple compliance frameworks:</p>
 * <ul>
 *   <li><b>PCI-DSS</b> - Requirement 3.5, 3.6: Cryptographic key management</li>
 *   <li><b>HIPAA</b> - ยง164.312(a)(2)(iv): Encryption key management</li>
 *   <li><b>SOC 2</b> - CC6.1: Encryption key protection</li>
 *   <li><b>GDPR</b> - Article 32(1)(a): Encryption of personal data</li>
 * </ul>
 *
 * <h2>Controls Implemented</h2>
 * <ul>
 *   <li>KMS key rotation enforcement</li>
 *   <li>Certificate lifecycle management</li>
 *   <li>Secrets Manager integration for credentials</li>
 *   <li>Key access policies and least privilege</li>
 * </ul>
 *
 * <h2>Usage</h2>
 * <pre>{@code
 * // Automatically loaded via FrameworkLoader (v2.0 pattern)
 * // Or manually: new KeyManagementRules().install(ctx);
 * }</pre>
 *
 * @since 3.0.0
 */
@ComplianceFramework(
    value = "KeyManagement",
    priority = -10,
    alwaysLoad = true,
    displayName = "Key Management & Encryption",
    description = "Cross-framework key management and encryption validation"
)
public class KeyManagementRules implements FrameworkRules<SystemContext> {

    private static final Logger LOG = Logger.getLogger(KeyManagementRules.class.getName());

    /**
     * Install key management validation rules.
     * These rules apply to PRODUCTION and STAGING environments.
     *
     * @param ctx System context
     */
    @Override
    public void install(SystemContext ctx) {
        // Key management is critical for production and staging
        if (ctx.security == SecurityProfile.DEV) {
            LOG.info("Key management validation rules are advisory for DEV environments");
        }

        LOG.info("Installing key management compliance validation rules for " + ctx.security);

        ctx.getNode().addValidation(() -> {
            List<ComplianceRule> rules = new ArrayList<>();

            // KMS key management
            rules.addAll(validateKmsKeyManagement(ctx));

            // Certificate management
            rules.addAll(validateCertificateManagement(ctx));

            // Secrets management
            rules.addAll(validateSecretsManagement(ctx));

            // Get all failed rules
            List<ComplianceRule> failedRules = rules.stream()
                .filter(rule -> !rule.passed())
                .toList();

            if (!failedRules.isEmpty()) {
                LOG.warning("Key Management validation found " + failedRules.size() + " recommendations");
                failedRules.forEach(rule ->
                    LOG.warning("  - " + rule.description() + ": " + rule.errorMessage().orElse("")));

                // For DEV and STAGING, these are advisory only (warnings but not blocking)
                if (ctx.security == SecurityProfile.DEV || ctx.security == SecurityProfile.STAGING) {
                    return List.of();
                }

                // For PRODUCTION only, convert to error strings (blocking)
                return failedRules.stream()
                    .map(rule -> rule.description() + ": " + rule.errorMessage().orElse(""))
                    .toList();
            } else {
                LOG.info("Key Management validation passed (" + rules.size() + " checks)");
                return List.of();
            }
        });
    }

    /**
     * Validate KMS key management practices.
     *
     * <p>Checks:</p>
     * <ul>
     *   <li>KMS key rotation enabled (annual rotation required)</li>
     *   <li>Customer-managed keys used for production data</li>
     *   <li>Key policies follow least privilege</li>
     * </ul>
     */
    private List<ComplianceRule> validateKmsKeyManagement(SystemContext ctx) {
        List<ComplianceRule> rules = new ArrayList<>();

        var config = ctx.securityProfileConfig.get().orElse(null);

        // Check if security profile enables encryption (which implies key management)
        boolean encryptionEnabled = config != null &&
            (config.isEbsEncryptionEnabled() ||
             config.isEfsEncryptionAtRestEnabled() ||
             config.isS3EncryptionEnabled());

        // Check deployment context override
        boolean kmsKeyRotationEnabled = getBooleanSetting(ctx, "kmsKeyRotationEnabled", encryptionEnabled);

        // Use ComplianceMatrix to determine if KMS rotation is REQUIRED or ADVISORY
        String complianceFrameworks = ctx.cfc.complianceFrameworks();
        ComplianceMode complianceMode = ctx.cfc.complianceMode();

        ComplianceMatrix.ValidationResult result = ComplianceMatrix.validateControlMultiFramework(
            ComplianceMatrix.SecurityControl.KMS_KEY_ROTATION,
            complianceFrameworks,
            kmsKeyRotationEnabled,
            complianceMode
        );

        if (ctx.security == SecurityProfile.PRODUCTION) {
            if (result == ComplianceMatrix.ValidationResult.FAIL) {
                rules.add(ComplianceRule.fail(
                    "KMS-ROTATION",
                    "KMS automatic key rotation required for " + complianceFrameworks,
                    "KmsKeyRotationEnabled",
                    "Enable automatic key rotation for all customer-managed KMS keys. " +
                    "Set kmsKeyRotationEnabled = true in deployment context if using custom KMS keys."
                ));
            } else if (result == ComplianceMatrix.ValidationResult.WARN) {
                LOG.warning("KMS key rotation recommended but not required for " + complianceFrameworks);
                rules.add(ComplianceRule.pass(
                    "KMS-ROTATION",
                    "KMS key rotation is advisory for " + complianceFrameworks + " (recommended but not required)"
                ));
            } else {
                rules.add(ComplianceRule.pass(
                    "KMS-ROTATION",
                    "KMS automatic key rotation enabled" +
                    (encryptionEnabled ? " (via security profile)" : ""),
                    "KmsKeyRotationEnabled"
                ));
            }
        } else {
            rules.add(ComplianceRule.pass(
                "KMS-ROTATION",
                "KMS key rotation not required for " + ctx.security + " environment"
            ));
        }

        return rules;
    }

    /**
     * Validate certificate lifecycle management.
     *
     * <p>Checks:</p>
     * <ul>
     *   <li>Certificate expiration monitoring</li>
     *   <li>Automated certificate renewal</li>
     *   <li>Strong cipher suites</li>
     * </ul>
     */
    private List<ComplianceRule> validateCertificateManagement(SystemContext ctx) {
        List<ComplianceRule> rules = new ArrayList<>();

        // Certificate must exist for HTTPS
        if (ctx.cert.get().isEmpty()) {
            // Already validated in other rules, just pass
            rules.add(ComplianceRule.pass(
                "CERT-EXISTS",
                "Certificate validation handled by encryption rules"
            ));
            return rules;
        }

        var config = ctx.securityProfileConfig.get().orElse(null);

        // Certificate expiration monitoring
        boolean securityMonitoringEnabled = config != null && config.isSecurityMonitoringEnabled();
        boolean certExpirationMonitoringEnabled = getBooleanSetting(ctx, "certificateExpirationMonitoring", securityMonitoringEnabled);

        // Use ComplianceMatrix to determine if certificate monitoring is REQUIRED or ADVISORY
        String complianceFrameworks = ctx.cfc.complianceFrameworks();
        ComplianceMode complianceMode = ctx.cfc.complianceMode();

        ComplianceMatrix.ValidationResult result = ComplianceMatrix.validateControlMultiFramework(
            ComplianceMatrix.SecurityControl.CERTIFICATE_EXPIRATION_MONITORING,
            complianceFrameworks,
            certExpirationMonitoringEnabled,
            complianceMode
        );

        if (ctx.security == SecurityProfile.PRODUCTION) {
            if (result == ComplianceMatrix.ValidationResult.FAIL) {
                rules.add(ComplianceRule.fail(
                    "CERT-EXPIRATION-MONITOR",
                    "Certificate expiration monitoring required for " + complianceFrameworks,
                    "CertificateExpirationAlarm",
                    "Enable CloudWatch alarms to monitor certificate expiration (30 days before). " +
                    "Set certificateExpirationMonitoring = true in deployment context."
                ));
            } else if (result == ComplianceMatrix.ValidationResult.WARN) {
                LOG.warning("Certificate expiration monitoring recommended but not required for " + complianceFrameworks);
                rules.add(ComplianceRule.pass(
                    "CERT-EXPIRATION-MONITOR",
                    "Certificate expiration monitoring is advisory for " + complianceFrameworks + " (recommended but not required)",
                    "CertificateExpirationAlarm"
                ));
            } else {
                rules.add(ComplianceRule.pass(
                    "CERT-EXPIRATION-MONITOR",
                    "Certificate expiration monitoring enabled" +
                    (securityMonitoringEnabled ? " (via security profile)" : ""),
                    "CertificateExpirationAlarm"
                ));
            }
        } else {
            rules.add(ComplianceRule.pass(
                "CERT-EXPIRATION-MONITOR",
                "Certificate expiration monitoring not required for " + ctx.security,
                "CertificateExpirationAlarm"
            ));
        }

        // ACM automatic renewal (for ACM certificates) - default to true (ACM renews automatically)
        boolean usesAcmAutoRenewal = getBooleanSetting(ctx, "acmAutoRenewalEnabled", true);

        if (usesAcmAutoRenewal) {
            rules.add(ComplianceRule.pass(
                "CERT-AUTO-RENEWAL",
                "ACM automatic certificate renewal enabled"
            ));
        } else {
            rules.add(ComplianceRule.fail(
                "CERT-AUTO-RENEWAL",
                "ACM automatic renewal recommended for certificates",
                "Use AWS Certificate Manager with automatic renewal for HTTPS certificates"
            ));
        }

        return rules;
    }

    /**
     * Validate secrets management practices.
     *
     * <p>Checks:</p>
     * <ul>
     *   <li>Secrets Manager for database credentials</li>
     *   <li>Automatic secret rotation</li>
     *   <li>No hardcoded credentials</li>
     * </ul>
     */
    private List<ComplianceRule> validateSecretsManagement(SystemContext ctx) {
        List<ComplianceRule> rules = new ArrayList<>();

        var config = ctx.securityProfileConfig.get().orElse(null);

        // Secrets Manager usage for credentials
        boolean encryptionEnabled = config != null && config.isS3EncryptionEnabled();
        boolean usesSecretsManager = getBooleanSetting(ctx, "secretsManagerEnabled", encryptionEnabled);

        // Use ComplianceMatrix to determine if Secrets Manager is REQUIRED or ADVISORY
        String complianceFrameworks = ctx.cfc.complianceFrameworks();
        ComplianceMode complianceMode = ctx.cfc.complianceMode();

        ComplianceMatrix.ValidationResult smResult = ComplianceMatrix.validateControlMultiFramework(
            ComplianceMatrix.SecurityControl.SECRETS_MANAGER,
            complianceFrameworks,
            usesSecretsManager,
            complianceMode
        );

        if (ctx.security == SecurityProfile.PRODUCTION) {
            if (smResult == ComplianceMatrix.ValidationResult.FAIL) {
                rules.add(ComplianceRule.fail(
                    "SECRETS-MANAGER",
                    "AWS Secrets Manager required for " + complianceFrameworks + " credentials",
                    "SecretsManagerInUse",
                    "Store database credentials, API keys, and secrets in AWS Secrets Manager. " +
                    "Set secretsManagerEnabled = true in deployment context."
                ));
            } else if (smResult == ComplianceMatrix.ValidationResult.WARN) {
                LOG.warning("Secrets Manager recommended but not required for " + complianceFrameworks);
                rules.add(ComplianceRule.pass(
                    "SECRETS-MANAGER",
                    "Secrets Manager is advisory for " + complianceFrameworks + " (recommended but not required)",
                    "SecretsManagerInUse"
                ));
            } else {
                rules.add(ComplianceRule.pass(
                    "SECRETS-MANAGER",
                    "AWS Secrets Manager enabled for credential management" +
                    (encryptionEnabled ? " (via security profile)" : ""),
                    "SecretsManagerInUse"
                ));
            }

            // Automatic secret rotation (only validate if Secrets Manager is in use)
            if (usesSecretsManager) {
                boolean secretRotationEnabled = getBooleanSetting(ctx, "secretRotationEnabled", encryptionEnabled);

                ComplianceMatrix.ValidationResult rotationResult = ComplianceMatrix.validateControlMultiFramework(
                    ComplianceMatrix.SecurityControl.SECRETS_ROTATION,
                    complianceFrameworks,
                    secretRotationEnabled,
                    complianceMode
                );

                if (rotationResult == ComplianceMatrix.ValidationResult.FAIL) {
                    rules.add(ComplianceRule.fail(
                        "SECRET-ROTATION",
                        "Automatic secret rotation required for " + complianceFrameworks,
                        "SecretsManagerRotation",
                        "Enable automatic rotation for secrets (90 days or less). " +
                        "Set secretRotationEnabled = true in deployment context."
                    ));
                } else if (rotationResult == ComplianceMatrix.ValidationResult.WARN) {
                    LOG.warning("Secret rotation recommended but not required for " + complianceFrameworks);
                    rules.add(ComplianceRule.pass(
                        "SECRET-ROTATION",
                        "Secret rotation is advisory for " + complianceFrameworks + " (recommended but not required)",
                        "SecretsManagerRotation"
                    ));
                } else {
                    rules.add(ComplianceRule.pass(
                        "SECRET-ROTATION",
                        "Automatic secret rotation enabled" +
                        (encryptionEnabled ? " (via security profile)" : ""),
                        "SecretsManagerRotation"
                    ));
                }
            }
        } else {
            // For non-production, advisory only
            if (usesSecretsManager) {
                rules.add(ComplianceRule.pass(
                    "SECRETS-MANAGER",
                    "AWS Secrets Manager enabled",
                    "SecretsManagerInUse"
                ));
            } else {
                rules.add(ComplianceRule.pass(
                    "SECRETS-MANAGER",
                    "Secrets Manager not required for " + ctx.security + " environment"
                ));
            }
        }

        return rules;
    }

    /**
     * Helper method to safely get boolean settings from deployment context.
     */
    private 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;
        }
    }
}