Skip to main content
emnode
Compliance Medium severity

AWS Security Hub · ECS

ECS.12: ECS clusters should use Container Insights

Written and reviewed by Emnode · Last reviewed

What does AWS Security Hub ECS.12 check?

ECS.12 checks whether each ECS cluster has CloudWatch Container Insights enabled, via the Config rule ecs-container-insights-enabled. It fails any cluster whose containerInsights setting is off.

Why does ECS.12 matter?

An unmonitored cluster is a liability that surfaces at the worst moment. When a service starts thrashing memory or restarting in a loop, the team with Container Insights sees it on a dashboard with alarms; the team without it is reading raw task logs at 2am reconstructing what happened. It is also the data you need to right-size Fargate task sizes: without it, every container is sized by guesswork.

How do I fix ECS.12?

  1. Enable Container Insights on each cluster: set the cluster's containerInsights setting to enabled or enhanced with `aws ecs update-cluster-settings --cluster <name> --settings name=containerInsights,value=enhanced`.
  2. Set the account-level default (`aws ecs put-account-setting-default --name containerInsights --value enhanced`) so new clusters inherit it. Note this does not retroactively enable Container Insights on existing clusters, which you must still update individually.
  3. Build dashboards and alarms on the per-service CPU, memory, and restart-failure signals it produces.

Remediation script · bash

# Inventory: flag containers running as root or with a writable root filesystem.
for fam in $(aws ecs list-task-definition-families --status ACTIVE \
    --query 'families[]' --output text); do
  aws ecs describe-task-definition --task-definition "$fam" \
    --query "taskDefinition.containerDefinitions[?user==null || user=='root' || user=='0' || readonlyRootFilesystem!=\`true\`].{Family:'$fam',Name:name,User:user,ReadOnly:readonlyRootFilesystem}" \
    --output text
done

# Harden at the source. Dockerfile:
#   RUN addgroup -S app && adduser -S -G app appuser
#   USER appuser
# Task definition: non-root user, read-only root with one narrow tmpfs, secrets via ARN.
#   "user": "1000:1000",
#   "readonlyRootFilesystem": true,
#   "mountPoints": [{ "sourceVolume": "scratch", "containerPath": "/tmp", "readOnly": false }],
#   "secrets": [{ "name": "DB_PASSWORD",
#     "valueFrom": "arn:aws:secretsmanager:us-east-1:123456789012:secret:prod/checkout/db-AbCdEf" }]

# Register the hardened revision and roll it out (tasks only update on redeploy).
aws ecs register-task-definition --cli-input-json file://checkout-api-hardened.json
aws ecs update-service --cluster prod --service checkout-api \
  --task-definition checkout-api --force-new-deployment

Full walkthrough (console steps, edge cases and verification) in the lesson Harden ECS container workloads.

Is ECS.12 a false positive?

Two common surprises, neither of which is a true false positive. First, enabling the account-level default (containerInsights via put-account-setting-default) only affects clusters created afterward: it does not retroactively turn on Container Insights for pre-existing clusters, so ECS.12 keeps reporting FAILED on those until you update each one with update-cluster-settings. Second, the containerInsights setting accepts either 'enabled' (basic Container Insights) or 'enhanced' (Container Insights with enhanced observability); the control passes on either value, so you don't need 'enhanced' just to clear the check. A genuinely suppressible case is when the same observability is already delivered another way, for example ECS metrics and container telemetry shipped through an ADOT/OpenTelemetry collector or a third-party platform like Datadog or Prometheus. That is a legitimate, intentional state; document the alternative telemetry pipeline and set the finding to SUPPRESSED in Security Hub rather than turning on Container Insights purely to satisfy the check and duplicating the metric spend.

Part of the learning path Lock down access
  • ECS.2 An ECS service auto-assigns public IPs to tasks
  • ECS.3 A task definition shares the host PID namespace
  • ECS.4 A container runs in privileged mode
  • ECS.5 A container has a writable root filesystem
  • ECS.8 Secrets are passed as plaintext container env vars
  • ECS.9 A task definition has no logging configuration
  • ECS.10 Fargate services should run latest platform version
  • ECS.16 An ECS task set auto-assigns public IPs
  • ECS.18 ECS task defs should encrypt EFS volumes in transit
  • ECS.19 Capacity providers managed termination protection
  • ECS.20 Linux containers should run as non-root users
  • ECS.21 Windows containers should run as non-admin users