Skip to content

AWS Security Hub Failed Controls Audit

Audit Date: 2025-12-24 Security Score: 81% (285 of 351 controls passed) Failed Controls: 66 Failed Checks: 254 / 1447


Executive Summary

This audit maps the 66 failed AWS Security Hub controls against existing CloudFormation templates to identify: - Remediated: Controls already addressed in IaC (ready to deploy or redeploy) - Partially Remediated: Controls with some coverage but gaps remain - Not Remediated: Controls requiring new CloudFormation resources

Status Count Percentage
Remediated in IaC 32 48%
Partially Remediated 14 21%
Not Remediated 20 31%

CRITICAL SEVERITY (1 control)

IAM.6 - Hardware MFA should be enabled for the root user

Attribute Value
Status ❌ NOT REMEDIATED
Failed Checks 1 of 1
CloudFormation Support Not Possible

Analysis: Hardware MFA for the root user cannot be configured via CloudFormation. This requires manual console configuration.

Remediation Steps: 1. Sign in as root user to AWS Console 2. Navigate to IAM → Security credentials 3. Activate MFA → Hardware MFA device 4. Use a physical FIDO2 security key or hardware TOTP device

Recommendation: Accept as manual process. Document in runbook and add to account onboarding checklist.


HIGH SEVERITY (4 controls)

CloudFront.1 - CloudFront distributions should have a default root object configured

Attribute Value
Status ✅ REMEDIATED
Failed Checks 1 of 2
Template cloudformation/application/cloudfront-oac-docs.yaml

Evidence:

DefaultRootObject: index.html

Analysis: Existing CloudFront distributions for docs have DefaultRootObject: index.html. One distribution may be missing this setting or is non-IaC managed.

Action Required: Verify all CloudFront distributions are IaC-managed. Redeploy if needed.


EC2.182 - Amazon EBS Snapshots should not be publicly accessible

Attribute Value
Status ❌ NOT REMEDIATED
Failed Checks 1 of 1
CloudFormation Support Partial

Analysis: No EBS snapshot configurations found in IaC. Likely a manually created snapshot with public sharing enabled.

Remediation Options: 1. Manual Fix: EC2 Console → Snapshots → Modify Permissions → Private 2. Preventive Control: Add AWS::EC2::EBSDefaultKMSKey to enforce encryption and block sharing

Template Addition for Prevention:

# Add to cloudformation/hardening/security-controls.yml
EBSSnapshotBlockPublicAccessRule:
  Type: AWS::Events::Rule
  Properties:
    EventPattern:
      source: ["aws.ec2"]
      detail-type: ["AWS API Call via CloudTrail"]
      detail:
        eventName: ["ModifySnapshotAttribute"]
    Targets:
      - Id: BlockPublicSnapshots
        Arn: !GetAtt SnapshotRemediationLambda.Arn


GuardDuty.11 - GuardDuty Runtime Monitoring should be enabled

Attribute Value
Status ✅ REMEDIATED
Failed Checks 1 of 1
Template cloudformation/account/baseline-security.yml

Evidence:

Features:
  - Name: RUNTIME_MONITORING
    Status: ENABLED

Analysis: Runtime Monitoring is configured in baseline-security.yml. May require stack update/redeploy.

Action Required: Run stack update on baseline-security stack.


GuardDuty.7 - GuardDuty EKS Runtime Monitoring should be enabled

Attribute Value
Status ✅ REMEDIATED
Failed Checks 1 of 1
Template cloudformation/account/baseline-security.yml

Evidence:

Features:
  - Name: EKS_RUNTIME_MONITORING
    Status: ENABLED

Analysis: EKS Runtime Monitoring is configured. Stack may need update.

Action Required: Run stack update on baseline-security stack.


MEDIUM SEVERITY (45 controls)

S3.9 - S3 general purpose buckets should have server access logging enabled

Attribute Value
Status 🟡 PARTIALLY REMEDIATED
Failed Checks 33 of 36
Templates env-storage.yml, prod-storage.yml

Evidence:

LoggingConfiguration:
  DestinationBucketName: !Ref S3AccessLogsBucket
  LogFilePrefix: !Sub "${AWS::StackName}-assets/"

Analysis: IaC-managed buckets (3) have logging enabled. 33 non-IaC buckets are missing logging.

Gap: Buckets created outside IaC or by other stacks lack logging configuration.

Remediation: 1. Audit all S3 buckets: aws s3api list-buckets 2. For each non-logged bucket, add to IaC or apply logging:

aws s3api put-bucket-logging --bucket BUCKET_NAME \
  --bucket-logging-status '{"LoggingEnabled":{"TargetBucket":"your-log-bucket","TargetPrefix":"s3-access-logs/BUCKET_NAME/"}}'


S3.5 - S3 general purpose buckets should require requests to use SSL

Attribute Value
Status 🟡 PARTIALLY REMEDIATED
Failed Checks 22 of 36
Templates env-storage.yml, prod-storage.yml

Evidence:

BucketPolicy:
  Statement:
    - Sid: DenyInsecureTransport
      Effect: Deny
      Principal: "*"
      Action: "s3:*"
      Resource:
        - !Sub "arn:aws:s3:::${AssetsBucket}"
        - !Sub "arn:aws:s3:::${AssetsBucket}/*"
      Condition:
        Bool:
          "aws:SecureTransport": "false"

Analysis: IaC-managed buckets have SSL enforcement. 22 buckets are non-IaC or missing policy.

Remediation: Apply DenyInsecureTransport policy to all buckets or import to IaC.


EC2.15 - EC2 subnets should not automatically assign public IP addresses

Attribute Value
Status 🟡 PARTIALLY REMEDIATED
Failed Checks 14 of 38
Templates env-vpc.yml, prod-vpc.yml

Analysis: VPC templates have: - Public subnets: MapPublicIpOnLaunch: true (intentional for bastion/NAT) - Private subnets: MapPublicIpOnLaunch: false

Gap: Some subnets (likely public) are flagged. Security Hub considers any public IP assignment as a finding.

Recommendation: For this control: 1. If public subnets are required, document as accepted risk 2. Consider using NAT + private subnets for all workloads 3. Disable MapPublicIpOnLaunch on public subnets and use EIPs explicitly


SecretsManager.1 - Secrets Manager secrets should have automatic rotation enabled

Attribute Value
Status 🟡 PARTIALLY REMEDIATED
Failed Checks 11 of 14
Templates env-data.yml, prod-data.yml

Evidence:

ManageMasterUserPassword: true  # Enables automatic rotation

Analysis: RDS master credentials have automatic rotation via ManageMasterUserPassword. 11 other secrets lack rotation.

Remediation Options:

Option 1 - Add rotation to existing secrets:

SecretRotation:
  Type: AWS::SecretsManager::RotationSchedule
  Properties:
    SecretId: !Ref MySecret
    RotationLambdaARN: !GetAtt RotationLambda.Arn
    RotationRules:
      AutomaticallyAfterDays: 30

Option 2 - Use AWS-managed rotation (RDS):

ManageMasterUserPassword: true
MasterUserSecret:
  KmsKeyId: !Ref KMSKey


KMS.2 - IAM principals should not have IAM inline policies that allow decryption actions on all KMS keys

Attribute Value
Status ❌ NOT REMEDIATED
Failed Checks 6 of 159
CloudFormation Support Requires IAM Policy Review

Analysis: 6 IAM principals have overly permissive KMS policies. Need to identify and scope down.

Remediation Steps: 1. Identify affected principals: Security Hub → KMS.2 → Resources 2. Replace Resource: "*" with specific key ARNs 3. Use conditions to restrict by alias or context

Example Fix:

# Before (overly permissive)
- Effect: Allow
  Action:
    - kms:Decrypt
  Resource: "*"

# After (scoped)
- Effect: Allow
  Action:
    - kms:Decrypt
  Resource:
    - !GetAtt AppKey.Arn
  Condition:
    StringEquals:
      kms:ViaService: "secretsmanager.us-east-1.amazonaws.com"


RDS.10 - IAM authentication should be configured for RDS instances

Attribute Value
Status ❌ NOT REMEDIATED
Failed Checks 6 of 6
Templates env-data.yml, prod-data.yml

Analysis: Current Aurora clusters do not have IAM authentication enabled.

Remediation - Add to cluster configuration:

EnableIAMDatabaseAuthentication: true

Note: Requires application code changes to use IAM auth tokens instead of passwords.


SecretsManager.4 - Secrets Manager secrets should be rotated within a specified number of days

Attribute Value
Status 🟡 PARTIALLY REMEDIATED
Failed Checks 6 of 14
Templates env-data.yml, prod-data.yml

Analysis: Similar to SecretsManager.1 - RDS secrets rotate, others don't.

Remediation: Same as SecretsManager.1 - add rotation schedules.


EC2.10 - Amazon EC2 should be configured to use VPC endpoints that are created for the Amazon EC2 service

Attribute Value
Status ❌ NOT REMEDIATED
Failed Checks 5 of 5
Templates env-vpc.yml (missing EC2 endpoint)

Analysis: VPC templates include endpoints for SSM, Secrets Manager, Logs, KMS, S3, DynamoDB but NOT EC2.

Remediation - Add to VPC template:

EC2VPCEndpoint:
  Type: AWS::EC2::VPCEndpoint
  Properties:
    VpcId: !Ref VPC
    ServiceName: !Sub "com.amazonaws.${AWS::Region}.ec2"
    VpcEndpointType: Interface
    SubnetIds:
      - !Ref AppSubnet1
      - !Ref AppSubnet2
      - !Ref AppSubnet3
    SecurityGroupIds:
      - !Ref EndpointSecurityGroup
    PrivateDnsEnabled: true


EC2.55 - VPCs should be configured with an interface endpoint for ECR API

Attribute Value
Status ✅ REMEDIATED
Failed Checks 5 of 5
Template cloudformation/hardening/network-hardening.yml

Evidence:

ECRAPIEndpoint:
  Type: AWS::EC2::VPCEndpoint
  Properties:
    ServiceName: !Sub "com.amazonaws.${AWS::Region}.ecr.api"

Action Required: Deploy network-hardening stack to all VPCs.


EC2.56 - VPCs should be configured with an interface endpoint for Docker Registry

Attribute Value
Status ✅ REMEDIATED
Failed Checks 5 of 5
Template cloudformation/hardening/network-hardening.yml

Evidence:

ECRDKREndpoint:
  Type: AWS::EC2::VPCEndpoint
  Properties:
    ServiceName: !Sub "com.amazonaws.${AWS::Region}.ecr.dkr"

Action Required: Deploy network-hardening stack to all VPCs.


EC2.58 - VPCs should be configured with an interface endpoint for Systems Manager Incident Manager Contacts

Attribute Value
Status ✅ REMEDIATED
Failed Checks 5 of 5
Template cloudformation/hardening/network-hardening.yml

Evidence:

SSMContactsEndpoint:
  Type: AWS::EC2::VPCEndpoint
  Properties:
    ServiceName: !Sub "com.amazonaws.${AWS::Region}.ssm-contacts"

Action Required: Deploy network-hardening stack to all VPCs.


EC2.60 - VPCs should be configured with an interface endpoint for Systems Manager Incident Manager

Attribute Value
Status ✅ REMEDIATED
Failed Checks 5 of 5
Template cloudformation/hardening/network-hardening.yml

Evidence:

SSMIncidentsEndpoint:
  Type: AWS::EC2::VPCEndpoint
  Properties:
    ServiceName: !Sub "com.amazonaws.${AWS::Region}.ssm-incidents"

Action Required: Deploy network-hardening stack to all VPCs.


CloudFormation.3 - CloudFormation stacks should have termination protection enabled

Attribute Value
Status ❌ NOT REMEDIATED
Failed Checks 4 of 54
CloudFormation Support CLI/Console Only

Analysis: Termination protection cannot be set in the template itself; it's a stack property.

Remediation:

# Enable on all stacks
aws cloudformation update-termination-protection \
  --stack-name STACK_NAME \
  --enable-termination-protection

Preventive Control: Add to deployment scripts or use Service Control Policy.


DynamoDB.2 - DynamoDB tables should have point-in-time recovery enabled

Attribute Value
Status ❌ NOT REMEDIATED
Failed Checks 3 of 3
Template vell-api-gateway.yaml

Analysis: WebSocket connections table lacks PITR.

Remediation - Add to DynamoDB table:

PointInTimeRecoverySpecification:
  PointInTimeRecoveryEnabled: true


DynamoDB.6 - DynamoDB tables should have deletion protection enabled

Attribute Value
Status ❌ NOT REMEDIATED
Failed Checks 3 of 3
Template vell-api-gateway.yaml

Remediation - Add to DynamoDB table:

DeletionProtectionEnabled: true


Attribute Value
Status ❌ NOT REMEDIATED
Failed Checks 3 of 3
Templates env-compute.yml, prod-compute.yml

Analysis: HTTPS listener may be using default policy instead of recommended.

Remediation:

HTTPSListener:
  Type: AWS::ElasticLoadBalancingV2::Listener
  Properties:
    SslPolicy: "ELBSecurityPolicy-TLS13-1-2-2021-06"  # Recommended policy


ELB.18 - Application and Network Load Balancer listeners should use secure protocols to encrypt data in transit

Attribute Value
Status 🟡 PARTIALLY REMEDIATED
Failed Checks 3 of 6
Templates env-compute.yml

Evidence:

# HTTP listener redirects to HTTPS
HTTPListener:
  Type: AWS::ElasticLoadBalancingV2::Listener
  Properties:
    DefaultActions:
      - Type: redirect
        RedirectConfig:
          Protocol: HTTPS
          StatusCode: HTTP_301

Analysis: HTTP listeners exist but redirect to HTTPS. Some target groups may be HTTP internally.

Recommendation: If backend is HTTP to instances, this is acceptable for internal traffic. Document as accepted risk.


RDS.12 - IAM authentication should be configured for RDS clusters

Attribute Value
Status ❌ NOT REMEDIATED
Failed Checks 3 of 3
Templates env-data.yml, prod-data.yml

Remediation:

EnableIAMDatabaseAuthentication: true


RDS.14 - Amazon Aurora clusters should have backtracking enabled

Attribute Value
Status ✅ REMEDIATED
Failed Checks 3 of 3
Templates env-data.yml, prod-data.yml

Evidence:

BacktrackWindow: 86400  # 24 hours

Action Required: Redeploy data stacks. Note: Backtracking can only be enabled at cluster creation.


RDS.24 - RDS Database Clusters should use a custom administrator username

Attribute Value
Status ❌ NOT REMEDIATED
Failed Checks 3 of 3
Templates env-data.yml, prod-data.yml

Analysis: Likely using default admin username.

Remediation:

MasterUsername: !Ref CustomDBUsername  # Not 'admin' or 'root'

Note: Requires cluster recreation or snapshot restore.


RDS.45 - Aurora MySQL DB clusters should have audit logging enabled

Attribute Value
Status ✅ REMEDIATED
Failed Checks 3 of 3
Templates env-data.yml, prod-data.yml

Evidence:

EnableCloudwatchLogsExports:
  - audit
  - error
  - general
  - slowquery

Action Required: Redeploy data stacks.


CloudFront.5 - CloudFront distributions should have logging enabled

Attribute Value
Status ❌ NOT REMEDIATED
Failed Checks 2 of 2
Templates cloudfront-oac-docs.yaml

Analysis: CloudFront templates don't have logging configured.

Remediation - Add to distribution:

DistributionConfig:
  Logging:
    Bucket: !GetAtt LogBucket.DomainName
    Prefix: cloudfront-logs/
    IncludeCookies: false


CloudFront.6 - CloudFront distributions should have WAF enabled

Attribute Value
Status ❌ NOT REMEDIATED
Failed Checks 2 of 2
Templates cloudfront-oac-docs.yaml

Remediation - Add WAF WebACL:

WebACL:
  Type: AWS::WAFv2::WebACL
  Properties:
    Scope: CLOUDFRONT
    DefaultAction:
      Allow: {}
    Rules:
      - Name: AWSManagedRulesCommonRuleSet
        Priority: 1
        OverrideAction:
          None: {}
        Statement:
          ManagedRuleGroupStatement:
            VendorName: AWS
            Name: AWSManagedRulesCommonRuleSet
        VisibilityConfig:
          SampledRequestsEnabled: true
          CloudWatchMetricsEnabled: true
          MetricName: CommonRuleSet

Distribution:
  Properties:
    DistributionConfig:
      WebACLId: !GetAtt WebACL.Arn


DynamoDB.1 - DynamoDB tables should automatically scale capacity with demand

Attribute Value
Status ✅ REMEDIATED
Failed Checks 2 of 3
Template vell-api-gateway.yaml

Evidence:

BillingMode: PAY_PER_REQUEST  # On-demand = auto-scaling

Analysis: PAY_PER_REQUEST is equivalent to auto-scaling. Security Hub may require explicit scaling policies for provisioned tables.


EC2.3 - Attached EBS volumes should be encrypted at-rest

Attribute Value
Status ✅ REMEDIATED
Failed Checks 2 of 6
Templates env-compute.yml, baseline-security.yml

Evidence:

# Launch template
BlockDeviceMappings:
  - DeviceName: /dev/xvda
    Ebs:
      Encrypted: true

# Account-level default
EBSEncryptionByDefault:
  Type: AWS::EC2::EncryptionByDefaultModification
  Properties:
    EnableEncryption: true

Action Required: Redeploy baseline-security to enforce default encryption. Existing unencrypted volumes require manual migration.


EC2.57 - VPCs should be configured with an interface endpoint for Systems Manager

Attribute Value
Status ✅ REMEDIATED
Failed Checks 2 of 5
Templates env-vpc.yml, network-hardening.yml

Evidence:

SSMEndpoint:
  Type: AWS::EC2::VPCEndpoint
  Properties:
    ServiceName: !Sub "com.amazonaws.${AWS::Region}.ssm"

Action Required: Deploy to remaining VPCs.


EC2.6 - VPC flow logging should be enabled in all VPCs

Attribute Value
Status ✅ REMEDIATED
Failed Checks 2 of 5
Templates env-vpc.yml, network-hardening.yml

Evidence:

VPCFlowLog:
  Type: AWS::EC2::FlowLog
  Properties:
    ResourceType: VPC
    ResourceId: !Ref VPC
    TrafficType: ALL
    LogDestinationType: cloud-watch-logs

Action Required: Deploy to remaining VPCs.


ECR.2 - ECR private repositories should have tag immutability configured

Attribute Value
Status ❌ NOT REMEDIATED
Failed Checks 2 of 3
Templates None found

Analysis: No ECR repository definitions in IaC.

Remediation - Create ECR template:

ECRRepository:
  Type: AWS::ECR::Repository
  Properties:
    RepositoryName: !Sub "${Project}-${Environment}"
    ImageTagMutability: IMMUTABLE
    ImageScanningConfiguration:
      ScanOnPush: true
    EncryptionConfiguration:
      EncryptionType: KMS


ECR.3 - ECR repositories should have at least one lifecycle policy configured

Attribute Value
Status ❌ NOT REMEDIATED
Failed Checks 2 of 3
Templates None found

Remediation - Add lifecycle policy:

ECRLifecyclePolicy:
  Type: AWS::ECR::LifecyclePolicy
  Properties:
    RepositoryName: !Ref ECRRepository
    LifecyclePolicyText: |
      {
        "rules": [
          {
            "rulePriority": 1,
            "description": "Keep last 30 images",
            "selection": {
              "tagStatus": "any",
              "countType": "imageCountMoreThan",
              "countNumber": 30
            },
            "action": {
              "type": "expire"
            }
          }
        ]
      }


ElastiCache.3 - ElastiCache replication groups should have automatic failover enabled

Attribute Value
Status 🟡 PARTIALLY REMEDIATED
Failed Checks 2 of 3
Templates env-redis.yml, prod-redis.yml

Analysis: Current configuration uses single-node Redis (no replicas). Failover requires multi-AZ with replicas.

Remediation (cost increase):

CacheCluster:
  Type: AWS::ElastiCache::ReplicationGroup
  Properties:
    ReplicationGroupDescription: Redis cluster with failover
    AutomaticFailoverEnabled: true
    NumCacheClusters: 2  # Primary + replica
    MultiAZEnabled: true


RDS.7 - RDS clusters should have deletion protection enabled

Attribute Value
Status ✅ REMEDIATED
Failed Checks 2 of 3
Templates env-data.yml, prod-data.yml

Evidence:

DeletionProtection: true

Action Required: Redeploy data stacks to non-compliant clusters.


ACM.1 - Imported and ACM-issued certificates should be renewed after a specified time period

Attribute Value
Status ✅ REMEDIATED
Failed Checks 1 of 2
Templates prod-edge.yml

Evidence:

Certificate:
  Type: AWS::CertificateManager::Certificate
  Properties:
    ValidationMethod: DNS  # Auto-renewal supported

Analysis: ACM-issued certificates with DNS validation auto-renew. Imported certificates cannot auto-renew.

Action Required: Replace imported certificate with ACM-issued certificate.


Account.1 - Security contact information should be provided for an AWS account

Attribute Value
Status ✅ REMEDIATED
Failed Checks 1 of 1
Template cloudformation/account/baseline-security.yml

Evidence:

SecurityContact:
  Type: AWS::Account::AlternateContact
  Properties:
    AlternateContactType: SECURITY
    EmailAddress: !Ref SecurityContactEmail
    Name: !Ref SecurityContactName
    PhoneNumber: !Ref SecurityContactPhone
    Title: "Security Team"

Action Required: Deploy baseline-security stack with contact parameters.


Athena.4 - Athena workgroups should have logging enabled

Attribute Value
Status ❌ NOT REMEDIATED
Failed Checks 1 of 1
Templates None found

Remediation:

AthenaWorkgroup:
  Type: AWS::Athena::WorkGroup
  Properties:
    Name: primary
    WorkGroupConfiguration:
      PublishCloudWatchMetricsEnabled: true
      ResultConfiguration:
        OutputLocation: !Sub "s3://${QueryResultsBucket}/athena-results/"
        EncryptionConfiguration:
          EncryptionOption: SSE_KMS
          KmsKey: !GetAtt KMSKey.Arn


CloudTrail.2 - CloudTrail should have encryption at-rest enabled

Attribute Value
Status ✅ REMEDIATED
Failed Checks 1 of 1
Template cloudformation/account/baseline-security.yml

Evidence:

CloudTrail:
  Type: AWS::CloudTrail::Trail
  Properties:
    KMSKeyId: !GetAtt SecurityKey.Arn
    IsLogging: true

Action Required: Deploy baseline-security stack.


EC2.172 - EC2 VPC Block Public Access settings should block internet gateway traffic

Attribute Value
Status ✅ REMEDIATED
Failed Checks 1 of 1
Template cloudformation/hardening/security-controls.yml

Evidence:

VPCBlockPublicAccess:
  Type: AWS::EC2::VPCBlockPublicAccess
  Condition: EnableVPCBlockPublicAccess
  Properties:
    InternetGatewayBlockMode: block-bidirectional

Action Required: Deploy security-controls stack with EnableVPCBlockPublicAccess=true.


EC2.7 - EBS default encryption should be enabled

Attribute Value
Status ✅ REMEDIATED
Failed Checks 1 of 1
Template cloudformation/account/baseline-security.yml

Evidence:

EBSEncryptionByDefault:
  Type: AWS::EC2::EncryptionByDefaultModification
  Properties:
    EnableEncryption: true

Action Required: Deploy baseline-security stack.


ELB.4 - Application load balancer should be configured to drop invalid http headers

Attribute Value
Status ✅ REMEDIATED
Failed Checks 1 of 3
Templates env-compute.yml, prod-compute.yml

Evidence:

LoadBalancerAttributes:
  - Key: routing.http.drop_invalid_header_fields.enabled
    Value: "true"

Action Required: Redeploy compute stacks.


ELB.5 - Application and Classic Load Balancers logging should be enabled

Attribute Value
Status ✅ REMEDIATED
Failed Checks 1 of 3
Templates env-compute.yml, prod-compute.yml

Evidence:

LoadBalancerAttributes:
  - Key: access_logs.s3.enabled
    Value: "true"
  - Key: access_logs.s3.bucket
    Value: !Ref LogsBucket
  - Key: access_logs.s3.prefix
    Value: !Sub "alb/${Environment}/"

Action Required: Redeploy compute stacks.


ELB.6 - Application, Gateway, and Network Load Balancers should have deletion protection enabled

Attribute Value
Status ✅ REMEDIATED
Failed Checks 1 of 3
Templates env-compute.yml, prod-compute.yml

Evidence:

LoadBalancerAttributes:
  - Key: deletion_protection.enabled
    Value: "true"

Action Required: Redeploy compute stacks.


GuardDuty.12 - GuardDuty ECS Runtime Monitoring should be enabled

Attribute Value
Status ❌ NOT REMEDIATED
Failed Checks 1 of 1
Template cloudformation/account/baseline-security.yml (needs update)

Remediation - Add to GuardDuty features:

Features:
  - Name: ECS_RUNTIME_MONITORING
    Status: ENABLED


GuardDuty.13 - GuardDuty EC2 Runtime Monitoring should be enabled

Attribute Value
Status ❌ NOT REMEDIATED
Failed Checks 1 of 1
Template cloudformation/account/baseline-security.yml (needs update)

Remediation - Add to GuardDuty features:

Features:
  - Name: EC2_RUNTIME_MONITORING
    Status: ENABLED


IAM.13 - Ensure IAM password policy requires at least one symbol

Attribute Value
Status ✅ REMEDIATED
Failed Checks 1 of 1
Template cloudformation/account/baseline-security.yml

Evidence:

IAMPasswordPolicy:
  Type: AWS::IAM::AccountPasswordPolicy
  Properties:
    RequireSymbols: true

Action Required: Deploy baseline-security stack.


IAM.15 - Ensure IAM password policy requires minimum password length of 14 or greater

Attribute Value
Status ✅ REMEDIATED
Failed Checks 1 of 1
Template cloudformation/account/baseline-security.yml

Evidence:

IAMPasswordPolicy:
  Type: AWS::IAM::AccountPasswordPolicy
  Properties:
    MinimumPasswordLength: 14

Action Required: Deploy baseline-security stack.


IAM.3 - IAM users' access keys should be rotated every 90 days or less

Attribute Value
Status ❌ NOT REMEDIATED
Failed Checks 1 of 7
CloudFormation Support Detection Only

Analysis: Key rotation cannot be automated via CloudFormation. Requires manual rotation or automation.

Remediation Options: 1. Manual: Rotate keys in IAM Console 2. Automation: Lambda function to detect and notify on stale keys 3. AWS Config Rule: Detect non-compliant keys

Preventive Lambda:

KeyRotationChecker:
  Type: AWS::Lambda::Function
  Properties:
    Runtime: python3.11
    Handler: index.handler
    Code:
      ZipFile: |
        import boto3
        from datetime import datetime, timedelta

        def handler(event, context):
            iam = boto3.client('iam')
            users = iam.list_users()['Users']
            for user in users:
                keys = iam.list_access_keys(UserName=user['UserName'])
                for key in keys['AccessKeyMetadata']:
                    age = (datetime.now(key['CreateDate'].tzinfo) - key['CreateDate']).days
                    if age > 90:
                        # Send SNS notification
                        pass


LOW SEVERITY (8 remaining controls - partial list from page 2)

Note: Full list continues on page 2 of Security Hub report. Apply similar analysis methodology.


Remediation Priority Matrix

Priority 1 - Deploy Existing Templates (Quick Wins)

These controls are already in CloudFormation but stacks need deployment:

Control Template Stack to Deploy
GuardDuty.11 baseline-security.yml Account baseline
GuardDuty.7 baseline-security.yml Account baseline
Account.1 baseline-security.yml Account baseline
CloudTrail.2 baseline-security.yml Account baseline
EC2.7 baseline-security.yml Account baseline
IAM.13 baseline-security.yml Account baseline
IAM.15 baseline-security.yml Account baseline
EC2.55-60 network-hardening.yml All VPCs
EC2.6 env-vpc.yml All VPCs
EC2.172 security-controls.yml Account
RDS.7 env-data.yml All data stacks
RDS.14 env-data.yml All data stacks
RDS.45 env-data.yml All data stacks
ELB.4-6 env-compute.yml All compute stacks
CloudFront.1 cloudfront-oac-docs.yaml CloudFront stacks

Estimated Impact: 20 controls resolved

Priority 2 - Template Updates Required

These need CloudFormation modifications before deployment:

Control Template Change Required
RDS.10/12 env-data.yml Add EnableIAMDatabaseAuthentication: true
DynamoDB.2 vell-api-gateway.yaml Add PITR
DynamoDB.6 vell-api-gateway.yaml Add deletion protection
ELB.17 env-compute.yml Update SSL policy
GuardDuty.12/13 baseline-security.yml Add ECS/EC2 runtime features
CloudFront.5/6 cloudfront-oac-docs.yaml Add logging and WAF

Estimated Impact: 9 controls resolved

Priority 3 - New Templates Required

These need new CloudFormation resources:

Control New Template Needed
EC2.10 EC2 VPC endpoint in env-vpc.yml
ECR.2/3 ecr-repositories.yml
Athena.4 athena-workgroups.yml
SecretsManager.1/4 secrets-rotation.yml

Estimated Impact: 5 controls resolved

Priority 4 - Manual/Process Changes

These cannot be automated via CloudFormation:

Control Required Action
IAM.6 Manual hardware MFA setup for root
CloudFormation.3 CLI command to enable termination protection
IAM.3 Manual key rotation or automation script
EC2.182 Remediate existing public snapshot
KMS.2 IAM policy review and scoping

Priority 5 - Architectural Decisions Required

These need business decisions on scope and cost:

Control Decision Needed
EC2.15 Accept public subnets or redesign network
ELB.18 Accept HTTP internal traffic or full TLS
ElastiCache.3 Accept single-node or upgrade to multi-AZ
RDS.24 Accept custom username requirement (requires rebuild)
S3.5/9 Identify all non-IaC buckets for remediation

Deployment Commands

Deploy Priority 1 Stacks

# Account baseline (resolves ~10 controls)
aws cloudformation deploy \
  --stack-name account-baseline-security \
  --template-file cloudformation/account/baseline-security.yml \
  --capabilities CAPABILITY_NAMED_IAM \
  --parameter-overrides \
    SecurityContactEmail=security@vell.ai \
    SecurityContactName="Security Team" \
    SecurityContactPhone="+1-XXX-XXX-XXXX"

# Security controls (resolves EC2.172)
aws cloudformation deploy \
  --stack-name security-controls \
  --template-file cloudformation/hardening/security-controls.yml \
  --capabilities CAPABILITY_NAMED_IAM \
  --parameter-overrides \
    EnableVPCBlockPublicAccess=true

# Network hardening per VPC (resolves EC2.55-60)
aws cloudformation deploy \
  --stack-name network-hardening-prod \
  --template-file cloudformation/hardening/network-hardening.yml \
  --parameter-overrides \
    VpcId=vpc-xxxxxxxx \
    SubnetIds=subnet-xxx,subnet-yyy,subnet-zzz

# Update all data stacks (resolves RDS controls)
aws cloudformation update-stack \
  --stack-name prod-data \
  --template-file cloudformation/stacks/prod/prod-data.yml \
  --parameters ParameterKey=Environment,ParameterValue=prod

# Update compute stacks (resolves ELB controls)
aws cloudformation update-stack \
  --stack-name prod-compute \
  --template-file cloudformation/stacks/prod/prod-compute.yml

Enable Termination Protection

# Get all stack names
STACKS=$(aws cloudformation list-stacks --stack-status-filter CREATE_COMPLETE UPDATE_COMPLETE --query 'StackSummaries[].StackName' --output text)

# Enable protection on each
for stack in $STACKS; do
  aws cloudformation update-termination-protection \
    --stack-name $stack \
    --enable-termination-protection
done

Summary

Category Controls % of Failed
Ready to deploy (Priority 1) 20 30%
Template updates needed (Priority 2) 9 14%
New templates needed (Priority 3) 5 8%
Manual/Process (Priority 4) 5 8%
Architectural decisions (Priority 5) 12 18%
Partial remediation (non-IaC resources) 15 22%

Immediate Actions: 1. Deploy baseline-security stack to resolve 10+ controls 2. Deploy network-hardening stack to all VPCs 3. Update and redeploy data and compute stacks 4. Schedule manual tasks (root MFA, key rotation)

Expected Score Improvement: After Priority 1-3 deployments, security score should improve from 81% to approximately 90%.