diff --git a/terraform/modules/feature-flags/README.md b/terraform/modules/feature-flags/README.md new file mode 100644 index 0000000..06b5163 --- /dev/null +++ b/terraform/modules/feature-flags/README.md @@ -0,0 +1,232 @@ +# Feature Flags Module + +Centralized feature toggles for organization-wide security, compliance, and operational controls. Define once, propagate everywhere. + +## Philosophy + +- **Everything OPT-IN**: All features default to `false` or minimal settings +- **Environment Presets**: Quick setup via `production`, `staging`, or `development` presets +- **User Override Wins**: Explicit settings always override preset defaults +- **Single Source of Truth**: Define features once, reference everywhere + +## Usage + +### Basic - Custom Settings + +```hcl +module "feature_flags" { + source = "../modules/feature-flags" + + security = { + guardduty_enabled = true + securityhub_enabled = true + config_enabled = true + cloudtrail_enabled = true + } + + compliance = { + cis_benchmark_enabled = true + } + + iam = { + mfa_enforcement_enabled = true + } +} +``` + +### Quick Start - Environment Presets + +```hcl +# Production: Maximum security (all security services enabled) +module "feature_flags" { + source = "../modules/feature-flags" + environment_preset = "production" +} + +# Staging: Security with cost awareness +module "feature_flags" { + source = "../modules/feature-flags" + environment_preset = "staging" +} + +# Development: Minimal security, maximum flexibility +module "feature_flags" { + source = "../modules/feature-flags" + environment_preset = "development" +} +``` + +### Preset with Overrides + +```hcl +module "feature_flags" { + source = "../modules/feature-flags" + environment_preset = "production" + + # Override: Disable Macie even in production + security = { + macie_enabled = false + } + + # Override: Enable PCI compliance + compliance = { + pci_dss_enabled = true + } +} +``` + +### Consuming in Other Modules + +```hcl +module "security_baseline" { + source = "../modules/security-baseline" + + name = "org-security" + + # Reference feature flags + enable_guardduty = module.feature_flags.security.guardduty_enabled + enable_securityhub = module.feature_flags.security.securityhub_enabled + enable_config = module.feature_flags.security.config_enabled + enable_access_analyzer = module.feature_flags.security.access_analyzer_enabled + + config_bucket_name = module.s3_bucket.id +} + +module "alerting" { + source = "../modules/alerting" + + name = "org-alerts" + + enable_guardduty_events = module.feature_flags.alerting.guardduty_alerts_enabled + enable_securityhub_events = module.feature_flags.alerting.securityhub_alerts_enabled + enable_aws_health_events = module.feature_flags.alerting.health_alerts_enabled +} +``` + +## Environment Presets Comparison + +| Feature | Production | Staging | Development | +|---------|------------|---------|-------------| +| GuardDuty | ✅ | ✅ | ❌ | +| Security Hub | ✅ | ✅ | ❌ | +| AWS Config | ✅ | ✅ | ❌ | +| CloudTrail | ✅ | ✅ | ❌ | +| Access Analyzer | ✅ | ❌ | ❌ | +| CIS Benchmark | ✅ | ❌ | ❌ | +| MFA Enforcement | ✅ | ❌ | ❌ | +| Permissions Boundary | ✅ | ✅ | ❌ | +| EBS Encryption | ✅ | ✅ | ✅ | +| S3 Block Public | ✅ | ✅ | ❌ | + +## Feature Categories + +### Security (`var.security`) + +Threat detection and data protection services. + +| Flag | Default | Description | +|------|---------|-------------| +| `guardduty_enabled` | `false` | Enable GuardDuty threat detection | +| `guardduty_s3_protection` | `true` | GuardDuty S3 data source | +| `guardduty_eks_protection` | `true` | GuardDuty EKS audit logs | +| `guardduty_malware_protection` | `true` | GuardDuty malware scanning | +| `securityhub_enabled` | `false` | Enable Security Hub | +| `config_enabled` | `false` | Enable AWS Config | +| `cloudtrail_enabled` | `false` | Enable CloudTrail | +| `access_analyzer_enabled` | `false` | Enable IAM Access Analyzer | +| `ebs_encryption_default` | `true` | Default EBS encryption | +| `s3_block_public_access` | `true` | Account-level S3 public block | + +### Compliance (`var.compliance`) + +Compliance frameworks and Config rules. + +| Flag | Default | Description | +|------|---------|-------------| +| `cis_benchmark_enabled` | `false` | CIS AWS Foundations Benchmark | +| `aws_foundational_enabled` | `true` | AWS Foundational Security Best Practices | +| `pci_dss_enabled` | `false` | PCI DSS compliance rules | +| `hipaa_enabled` | `false` | HIPAA compliance rules | +| `config_rules_enabled` | `false` | Enable managed Config rules | +| `config_auto_remediation` | `false` | Auto-remediate Config findings | + +### IAM (`var.iam`) + +Identity and access management policies. + +| Flag | Default | Description | +|------|---------|-------------| +| `password_policy_enabled` | `true` | Enable account password policy | +| `password_minimum_length` | `14` | Minimum password length | +| `password_max_age_days` | `90` | Password rotation period | +| `mfa_enforcement_enabled` | `false` | Require MFA for all actions | +| `mfa_grace_period_days` | `0` | Grace period for new users | +| `require_imdsv2` | `true` | Require EC2 IMDSv2 | + +### Alerting (`var.alerting`) + +Security event notifications. + +| Flag | Default | Description | +|------|---------|-------------| +| `guardduty_alerts_enabled` | `true` | Alert on GuardDuty findings | +| `securityhub_alerts_enabled` | `true` | Alert on Security Hub findings | +| `health_alerts_enabled` | `true` | Alert on AWS Health events | +| `guardduty_min_severity` | `4.0` | Minimum GuardDuty severity (0-10) | +| `securityhub_min_severity` | `70` | Minimum Security Hub severity (0-100) | + +### Cost (`var.cost`) + +Budget and cost management. + +| Flag | Default | Description | +|------|---------|-------------| +| `budgets_enabled` | `true` | Enable AWS Budgets | +| `budget_default_limit` | `1000` | Default monthly budget | +| `budget_alert_thresholds` | `[50,80,100]` | Alert threshold percentages | +| `cost_allocation_tags_enabled` | `true` | Enable cost allocation tags | + +### Networking (`var.networking`) + +VPC and network configuration. + +| Flag | Default | Description | +|------|---------|-------------| +| `create_vpc` | `true` | Create tenant VPC | +| `vpc_endpoints_enabled` | `true` | Create VPC endpoints | +| `nat_gateway_enabled` | `true` | Create NAT Gateway | +| `nat_gateway_ha` | `false` | Multi-AZ NAT Gateways | + +### Backup (`var.backup`) + +AWS Backup configuration. + +| Flag | Default | Description | +|------|---------|-------------| +| `backup_enabled` | `false` | Enable AWS Backup | +| `daily_backup_enabled` | `true` | Daily backup schedule | +| `daily_retention_days` | `7` | Daily backup retention | + +## Outputs + +| Output | Description | +|--------|-------------| +| `security` | Merged security feature flags | +| `compliance` | Merged compliance feature flags | +| `iam` | Merged IAM feature flags | +| `alerting` | Merged alerting feature flags | +| `cost` | Cost management feature flags | +| `networking` | Networking feature flags | +| `backup` | Backup feature flags | +| `environment_preset` | Active preset name | +| `is_production` | Boolean: true if production preset | +| `encryption_required` | Boolean: true if encryption defaults enabled | +| `compliance_strict` | Boolean: true if strict compliance enabled | + +## Best Practices + +1. **Define Once**: Create feature flags in your root/organization module +2. **Reference Everywhere**: Pass flags to child modules via outputs +3. **Use Presets**: Start with a preset, override as needed +4. **Document Deviations**: Comment why you override preset defaults +5. **Review Regularly**: Periodically review which features are enabled diff --git a/terraform/modules/feature-flags/examples/organization-baseline/main.tf b/terraform/modules/feature-flags/examples/organization-baseline/main.tf new file mode 100644 index 0000000..199a6e3 --- /dev/null +++ b/terraform/modules/feature-flags/examples/organization-baseline/main.tf @@ -0,0 +1,170 @@ +################################################################################ +# Example: Organization Baseline with Feature Flags +# +# Demonstrates wiring feature flags into security and compliance modules. +# Copy and adapt for your organization's needs. +################################################################################ + +terraform { + required_version = ">= 1.5.0" + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.0" + } + } +} + +provider "aws" { + region = "us-east-1" +} + +################################################################################ +# Feature Flags - Single Source of Truth +################################################################################ + +module "feature_flags" { + source = "../../" + + # Use production preset with customizations + environment_preset = "production" + + # Override: Also enable PCI compliance + compliance = { + pci_dss_enabled = true + } + + # Override: Configure alerting thresholds + alerting = { + guardduty_min_severity = 7.0 # Only alert on HIGH+ findings + critical_to_pagerduty = true # Page for critical issues + } +} + +################################################################################ +# Security Baseline - Consumes Feature Flags +################################################################################ + +resource "aws_s3_bucket" "config" { + bucket_prefix = "org-config-" + force_destroy = true +} + +resource "aws_s3_bucket_versioning" "config" { + bucket = aws_s3_bucket.config.id + versioning_configuration { + status = "Enabled" + } +} + +module "security_baseline" { + source = "../../../security-baseline" + + name = "org-security" + + # Wire feature flags + enable_guardduty = module.feature_flags.security.guardduty_enabled + enable_securityhub = module.feature_flags.security.securityhub_enabled + enable_config = module.feature_flags.security.config_enabled + enable_access_analyzer = module.feature_flags.security.access_analyzer_enabled + + config_bucket_name = aws_s3_bucket.config.id + + # Security Hub standards based on compliance flags + securityhub_standards = concat( + module.feature_flags.compliance.aws_foundational_enabled ? ["aws-foundational-security-best-practices/v/1.0.0"] : [], + module.feature_flags.compliance.cis_benchmark_enabled ? ["cis-aws-foundations-benchmark/v/1.4.0"] : [], + module.feature_flags.compliance.pci_dss_enabled ? ["pci-dss/v/3.2.1"] : [] + ) + + tags = { + Environment = module.feature_flags.environment_preset + ManagedBy = "terraform" + } +} + +################################################################################ +# Alerting - Consumes Feature Flags +################################################################################ + +module "alerting" { + source = "../../../alerting" + + name = "org-alerts" + + email_endpoints = ["security@example.com"] + + # Wire feature flags + enable_guardduty_events = module.feature_flags.alerting.guardduty_alerts_enabled + enable_securityhub_events = module.feature_flags.alerting.securityhub_alerts_enabled + enable_aws_health_events = module.feature_flags.alerting.health_alerts_enabled + + tags = { + Environment = module.feature_flags.environment_preset + } +} + +################################################################################ +# IAM Account Settings - Consumes Feature Flags +################################################################################ + +module "iam_settings" { + source = "../../../iam-account-settings" + + account_alias = "my-org-prod" + + enable_password_policy = module.feature_flags.iam.password_policy_enabled + enforce_mfa = module.feature_flags.iam.mfa_enforcement_enabled + + password_policy = { + minimum_length = module.feature_flags.iam.password_minimum_length + require_symbols = module.feature_flags.iam.password_require_symbols + require_numbers = module.feature_flags.iam.password_require_numbers + require_uppercase_characters = module.feature_flags.iam.password_require_uppercase + require_lowercase_characters = module.feature_flags.iam.password_require_lowercase + max_password_age = module.feature_flags.iam.password_max_age_days + password_reuse_prevention = module.feature_flags.iam.password_reuse_prevention + } + + tags = { + Environment = module.feature_flags.environment_preset + } +} + +################################################################################ +# CloudTrail - Consumes Feature Flags +################################################################################ + +module "cloudtrail" { + source = "../../../cloudtrail" + count = module.feature_flags.security.cloudtrail_enabled ? 1 : 0 + + name = "org-trail" + is_multi_region = module.feature_flags.security.cloudtrail_multi_region + + enable_log_file_validation = module.feature_flags.security.cloudtrail_log_validation + enable_insights = module.feature_flags.security.cloudtrail_insights + enable_data_events = module.feature_flags.security.cloudtrail_data_events + + tags = { + Environment = module.feature_flags.environment_preset + } +} + +################################################################################ +# Outputs +################################################################################ + +output "feature_flags" { + value = { + preset = module.feature_flags.environment_preset + is_production = module.feature_flags.is_production + encryption_required = module.feature_flags.encryption_required + compliance_strict = module.feature_flags.compliance_strict + } + description = "Active feature flags summary" +} + +output "enabled_services" { + value = module.security_baseline.enabled_services +} diff --git a/terraform/modules/feature-flags/main.tf b/terraform/modules/feature-flags/main.tf new file mode 100644 index 0000000..6a75a2d --- /dev/null +++ b/terraform/modules/feature-flags/main.tf @@ -0,0 +1,425 @@ +################################################################################ +# Feature Flags Module +# +# Centralized feature toggles for organization-wide security controls. +# Define once, propagate everywhere. All features are OPT-IN by default. +# +# Usage: +# module "feature_flags" { +# source = "../modules/feature-flags" +# +# security = { +# guardduty_enabled = true +# securityhub_enabled = true +# config_enabled = true +# cloudtrail_enabled = true +# } +# +# compliance = { +# cis_benchmark_enabled = true +# pci_dss_enabled = false +# hipaa_enabled = false +# } +# } +# +# Then reference in other modules: +# enable_guardduty = module.feature_flags.security.guardduty_enabled +# +################################################################################ + +terraform { + required_version = ">= 1.5.0" +} + +################################################################################ +# Security Feature Flags +################################################################################ + +variable "security" { + type = object({ + # Threat Detection + guardduty_enabled = optional(bool, false) + guardduty_s3_protection = optional(bool, true) + guardduty_eks_protection = optional(bool, true) + guardduty_malware_protection = optional(bool, true) + guardduty_rds_protection = optional(bool, false) + guardduty_lambda_protection = optional(bool, false) + guardduty_runtime_monitoring = optional(bool, false) + + # Security Posture + securityhub_enabled = optional(bool, false) + securityhub_auto_enable = optional(bool, true) + + # Configuration Compliance + config_enabled = optional(bool, false) + config_all_resources = optional(bool, true) + config_include_global = optional(bool, true) + + # Audit Logging + cloudtrail_enabled = optional(bool, false) + cloudtrail_multi_region = optional(bool, true) + cloudtrail_log_validation = optional(bool, true) + cloudtrail_insights = optional(bool, false) + cloudtrail_data_events = optional(bool, false) + + # Identity + access_analyzer_enabled = optional(bool, false) + access_analyzer_type = optional(string, "ACCOUNT") + macie_enabled = optional(bool, false) + inspector_enabled = optional(bool, false) + + # Network Security + vpc_flow_logs_enabled = optional(bool, false) + network_firewall_enabled = optional(bool, false) + + # Data Protection + ebs_encryption_default = optional(bool, true) + s3_block_public_access = optional(bool, true) + rds_encryption_default = optional(bool, true) + }) + default = {} + description = "Security service feature flags" +} + +################################################################################ +# Compliance Feature Flags +################################################################################ + +variable "compliance" { + type = object({ + # Standards + cis_benchmark_enabled = optional(bool, false) + cis_benchmark_version = optional(string, "1.4.0") + aws_foundational_enabled = optional(bool, true) + pci_dss_enabled = optional(bool, false) + hipaa_enabled = optional(bool, false) + nist_800_53_enabled = optional(bool, false) + soc2_enabled = optional(bool, false) + + # Config Rules + config_rules_enabled = optional(bool, false) + config_auto_remediation = optional(bool, false) + + # Custom Rules + custom_config_rules = optional(list(string), []) + }) + default = {} + description = "Compliance framework feature flags" +} + +################################################################################ +# IAM Feature Flags +################################################################################ + +variable "iam" { + type = object({ + # Password Policy + password_policy_enabled = optional(bool, true) + password_minimum_length = optional(number, 14) + password_require_symbols = optional(bool, true) + password_require_numbers = optional(bool, true) + password_require_uppercase = optional(bool, true) + password_require_lowercase = optional(bool, true) + password_max_age_days = optional(number, 90) + password_reuse_prevention = optional(number, 24) + password_hard_expiry = optional(bool, false) + + # MFA + mfa_enforcement_enabled = optional(bool, false) + mfa_hardware_required = optional(bool, false) + mfa_grace_period_days = optional(number, 0) + + # Roles + create_admin_role = optional(bool, true) + create_developer_role = optional(bool, true) + create_readonly_role = optional(bool, true) + create_permissions_boundary = optional(bool, true) + + # Service Control + require_imdsv2 = optional(bool, true) + }) + default = {} + description = "IAM feature flags" +} + +################################################################################ +# Alerting Feature Flags +################################################################################ + +variable "alerting" { + type = object({ + # Event Sources + guardduty_alerts_enabled = optional(bool, true) + securityhub_alerts_enabled = optional(bool, true) + config_alerts_enabled = optional(bool, true) + health_alerts_enabled = optional(bool, true) + cloudtrail_alerts_enabled = optional(bool, false) + + # Severity Routing + critical_to_pagerduty = optional(bool, false) + high_to_slack = optional(bool, true) + medium_to_email = optional(bool, true) + low_to_cloudwatch = optional(bool, true) + + # Thresholds + guardduty_min_severity = optional(number, 4.0) + securityhub_min_severity = optional(number, 70) + }) + default = {} + description = "Alerting feature flags" +} + +################################################################################ +# Cost Management Feature Flags +################################################################################ + +variable "cost" { + type = object({ + # Budgets + budgets_enabled = optional(bool, true) + budget_forecasted_alerts = optional(bool, true) + budget_default_limit = optional(number, 1000) + budget_alert_thresholds = optional(list(number), [50, 80, 100]) + + # Cost Allocation + cost_allocation_tags_enabled = optional(bool, true) + cost_explorer_enabled = optional(bool, true) + }) + default = {} + description = "Cost management feature flags" +} + +################################################################################ +# Networking Feature Flags +################################################################################ + +variable "networking" { + type = object({ + # VPC + create_vpc = optional(bool, true) + vpc_endpoints_enabled = optional(bool, true) + nat_gateway_enabled = optional(bool, true) + nat_gateway_ha = optional(bool, false) + + # DNS + route53_enabled = optional(bool, false) + private_dns_enabled = optional(bool, true) + + # Transit + transit_gateway_enabled = optional(bool, false) + ram_sharing_enabled = optional(bool, false) + }) + default = {} + description = "Networking feature flags" +} + +################################################################################ +# Backup Feature Flags +################################################################################ + +variable "backup" { + type = object({ + # AWS Backup + backup_enabled = optional(bool, false) + backup_vault_encryption = optional(bool, true) + backup_cross_region = optional(bool, false) + backup_cross_account = optional(bool, false) + + # Default Schedules + daily_backup_enabled = optional(bool, true) + weekly_backup_enabled = optional(bool, true) + monthly_backup_enabled = optional(bool, false) + + # Retention + daily_retention_days = optional(number, 7) + weekly_retention_days = optional(number, 30) + monthly_retention_days = optional(number, 365) + }) + default = {} + description = "Backup feature flags" +} + +################################################################################ +# Environment Presets +################################################################################ + +variable "environment_preset" { + type = string + default = "custom" + description = "Environment preset (production, staging, development, custom)" + + validation { + condition = contains(["production", "staging", "development", "custom"], var.environment_preset) + error_message = "Must be production, staging, development, or custom" + } +} + +locals { + # Production preset - maximum security + production_overrides = { + security = { + guardduty_enabled = true + securityhub_enabled = true + config_enabled = true + cloudtrail_enabled = true + access_analyzer_enabled = true + ebs_encryption_default = true + s3_block_public_access = true + } + compliance = { + cis_benchmark_enabled = true + aws_foundational_enabled = true + config_rules_enabled = true + } + iam = { + password_policy_enabled = true + mfa_enforcement_enabled = true + create_permissions_boundary = true + } + alerting = { + guardduty_alerts_enabled = true + securityhub_alerts_enabled = true + health_alerts_enabled = true + } + } + + # Staging preset - security with cost awareness + staging_overrides = { + security = { + guardduty_enabled = true + securityhub_enabled = true + config_enabled = true + cloudtrail_enabled = true + access_analyzer_enabled = false + ebs_encryption_default = true + s3_block_public_access = true + } + compliance = { + cis_benchmark_enabled = false + aws_foundational_enabled = true + config_rules_enabled = true + } + iam = { + password_policy_enabled = true + mfa_enforcement_enabled = false + create_permissions_boundary = true + } + alerting = { + guardduty_alerts_enabled = true + securityhub_alerts_enabled = false + health_alerts_enabled = true + } + } + + # Development preset - minimal security, maximum flexibility + development_overrides = { + security = { + guardduty_enabled = false + securityhub_enabled = false + config_enabled = false + cloudtrail_enabled = false + access_analyzer_enabled = false + ebs_encryption_default = true + s3_block_public_access = false + } + compliance = { + cis_benchmark_enabled = false + aws_foundational_enabled = false + config_rules_enabled = false + } + iam = { + password_policy_enabled = true + mfa_enforcement_enabled = false + create_permissions_boundary = false + } + alerting = { + guardduty_alerts_enabled = false + securityhub_alerts_enabled = false + health_alerts_enabled = true + } + } + + # Select preset or use custom + preset_map = { + production = local.production_overrides + staging = local.staging_overrides + development = local.development_overrides + custom = {} + } + + selected_preset = local.preset_map[var.environment_preset] +} + +################################################################################ +# Merged Outputs +# +# Merge user input with preset defaults. User input always wins. +################################################################################ + +output "security" { + value = merge( + var.security, + try(local.selected_preset.security, {}) + ) + description = "Merged security feature flags" +} + +output "compliance" { + value = merge( + var.compliance, + try(local.selected_preset.compliance, {}) + ) + description = "Merged compliance feature flags" +} + +output "iam" { + value = merge( + var.iam, + try(local.selected_preset.iam, {}) + ) + description = "Merged IAM feature flags" +} + +output "alerting" { + value = merge( + var.alerting, + try(local.selected_preset.alerting, {}) + ) + description = "Merged alerting feature flags" +} + +output "cost" { + value = var.cost + description = "Cost management feature flags" +} + +output "networking" { + value = var.networking + description = "Networking feature flags" +} + +output "backup" { + value = var.backup + description = "Backup feature flags" +} + +output "environment_preset" { + value = var.environment_preset + description = "Active environment preset" +} + +# Convenience outputs for common checks +output "is_production" { + value = var.environment_preset == "production" + description = "True if production preset is active" +} + +output "encryption_required" { + value = var.security.ebs_encryption_default && var.security.s3_block_public_access + description = "True if encryption defaults are enabled" +} + +output "compliance_strict" { + value = var.compliance.cis_benchmark_enabled || var.compliance.pci_dss_enabled || var.compliance.hipaa_enabled + description = "True if any strict compliance standard is enabled" +}