Amazon SCS-C02: Container & Serverless Security — Study Guide
Part of the AWS Security Specialty SCS-C02 — Study Guide. Practice with verified answers in the Amazon exam hub, or take timed practice tests on ExamRoll.io.
ECS Exec and Runtime Inspection Without SSH
ECS Exec provides an interactive shell into a running container — including Fargate tasks — without exposing SSH, bastion hosts, or public IPs. It works by riding on the SSM agent that AWS injects into the task’s sidecar execution environment. Because there is no SSH daemon, no key material, and no inbound network path to secure, the operational overhead is minimal and every session is auditable through CloudTrail and (optionally) logged to S3 or CloudWatch Logs.
Three requirements must all be satisfied for ECS Exec to work:
Task role permissions: the task role (not the execution role) needs
ssmmessages:CreateControlChannel,ssmmessages:CreateDataChannel,ssmmessages:OpenControlChannel, andssmmessages:OpenDataChannel. The execution role only pulls images and writes logs; runtime SSM traffic flows through the task role because that is the identity the container process assumes.Service or task configuration: the service must be created or updated with
--enable-execute-command. This flag flipsenableExecuteCommandon new tasks; existing tasks must be replaced.Container image support: the container needs a shell (
/bin/shor/bin/bash) present in the image.
A typical inspection flow looks like this:
aws ecs update-service --cluster prod --service api \
--enable-execute-command --force-new-deployment
aws ecs execute-command --cluster prod \
--task 5f8c...c2 --container api \
--interactive --command "/bin/sh"
From that shell an engineer can copy logs to S3, trigger a heap dump, or read /proc for forensics. The alternative — attempting to reach the container over SSH or restarting the task to enable a debug agent — either fails on Fargate or destroys the evidence you were trying to collect.
Blocking IMDS Access from Containers on EC2
A common misconception is that IMDSv2 hop-limit settings on the EC2 instance protect containers on that instance. They do not, at least not by default in bridge or host network mode: containers share the host’s network namespace or a NAT bridge and can reach 169.254.169.254 and retrieve the instance profile credentials, which are typically far more privileged than the task role. That defeats least privilege entirely.
The fix, when Fargate migration is not possible, has two parts:
Use
awsvpcnetwork mode for tasks. Each task gets its own ENI and network namespace. IMDS traffic no longer transparently reaches the host’s link-local endpoint.Set
ECS_AWSVPC_BLOCK_IMDS=truein/etc/ecs/ecs.configon the container instance. This tells the ECS agent to install an iptables rule that drops packets from awsvpc tasks destined for169.254.169.254.
echo 'ECS_AWSVPC_BLOCK_IMDS=true' >> /etc/ecs/ecs.config
systemctl restart ecs
Combine that with a minimal instance profile (essentially just what the ECS agent needs: AmazonEC2ContainerServiceforEC2Role) and per-task IAM roles for application permissions. Setting the instance’s IMDS hop limit to 1 with IMDSv2 required is a useful defense-in-depth measure but is not a substitute — bridge-mode containers can still reach IMDS at hop 1 because the request originates from the host.
GuardDuty Runtime Monitoring, EKS Protection, and Control Plane Logs
GuardDuty offers layered container detection:
EKS Protection analyzes EKS audit logs to detect suspicious Kubernetes API activity — anonymous access, privileged pod creation, exec into system pods.
Runtime Monitoring deploys an eBPF-based sensor (as a managed add-on for EKS, or an SSM-managed agent for ECS/Fargate) that observes process, file, and network activity inside containers. It surfaces findings like reverse shells, cryptomining binaries, and credential exfiltration from within a Pod or task.
EKS Protection is worthless unless the EKS control plane audit log is actually being emitted to CloudWatch Logs. Enable at least audit and authenticator log types on the cluster:
aws eks update-cluster-config --name prod \
--logging '{"clusterLogging":[{"types":["api","audit","authenticator","controllerManager","scheduler"],"enabled":true}]}'
Without that, GuardDuty has no data plane to inspect for EKS Protection findings — a trap that frequently appears because operators enable the GuardDuty feature but leave the cluster’s logging config off, then wonder why no Kubernetes findings appear.
Image Scanning with ECR Enhanced Scanning
ECR Enhanced Scanning is powered by Amazon Inspector and provides continuous scanning of container images for OS and language-package CVEs (Python, Node, Java, Go, Ruby). Basic scanning is one-shot at push time and covers only OS packages; enhanced is continuous and includes application dependencies, which is where most modern vulnerabilities live.
Findings flow automatically to Security Hub when both services are enabled, giving a single pane of glass for compliance and letting you write EventBridge rules that fail CI/CD builds. A typical enforcement pattern:
### Practical Problem: Use-Case Scenario
**Scenario:** NovaTech Corp runs customer-facing microservices across mixed compute: several ECS clusters on EC2, an EKS cluster for data processing, and serverless Lambdas for event handling. Images are stored in ECR, operations use SSM for host access, and GuardDuty/CloudWatch are enabled but visibility is uneven across containers and control plane components.
**Challenge:** A production container exhibited suspicious outbound connections and an engineer discovered a pod could reach the EC2 instance metadata service, risking credential exfiltration; image vulnerabilities and insufficient control plane logging may hide the root cause.
**Recommended Approach:**
1. Enable ECS Exec for tasks and require AWS Systems Manager Session Manager for host and container runtime inspection (ECS Exec + SSM), removing need for SSH and ensuring session activity is logged to CloudTrail and CloudWatch Logs.
2. Enforce IMDSv2 on EC2 instances (Instance Metadata Service HttpTokens=required, hop limit=1) and apply host-level network rules to block 169.254.169.254 from container network namespaces so containers cannot query instance metadata.
3. Turn on Amazon GuardDuty runtime monitoring and Malware Protection for containers and Lambda, forward findings to Security Hub and EventBridge for automated containment playbooks.
4. Harden EKS by enabling control plane logs (audit, authenticator, controllerManager, scheduler) to CloudWatch Logs, adopt IAM Roles for Service Accounts (IRSA), and enforce admission controls (Pod Security or OPA Gatekeeper) to limit risky capabilities.
5. Activate Amazon ECR enhanced image scanning (Inspector/ECR scanning) with scan-on-push and integrate findings into CI to block/ quarantine images via EventBridge + Lambda for enforcement.
6. Centralize telemetry: send CloudTrail, GuardDuty findings, EKS control plane logs, and ECR scan results to a centralized S3/Lambda/Security Hub pipeline and feed AWS Config rules for continuous compliance.
**Rationale:** This sequence removes SSH-based access, prevents metadata credential theft, provides runtime detection and automated response, enforces image hygiene, and delivers control-plane visibility — aligning with AWS best practices of least privilege, defense in depth, and centralized observability.
## CodeBuild buildspec fragment
post_build:
commands:
- aws ecr describe-image-scan-findings \
--repository-name api --image-id imageTag=$TAG \
--query 'imageScanFindings.findingSeverityCounts' > findings.json
CRIT=$(jq '.CRITICAL // 0' findings.json)
if [ "$CRIT" -gt 0 ]; then echo "Critical CVEs present"; exit 1; fi
Integration into the pipeline is what turns scanning from a dashboard exercise into a real control.
Lambda: Authorizers, Secrets, and Execution Roles
Lambda function-level security has three planes that are frequently conflated:
Resource policy (function policy): controls which principals (API Gateway, EventBridge, other accounts) can invoke the function. Lambda Authorizers on API Gateway are the identity gate for HTTP callers — they return an IAM policy that API Gateway caches and enforces before invoking the backend function.
Execution role: the identity the function code assumes at runtime. Its trust policy must include
lambda.amazonaws.com, and it must grantlogs:CreateLogGroup,logs:CreateLogStream, andlogs:PutLogEventsfor CloudWatch Logs to work. If logs are missing, the fix is almost always the execution role — not the Lambda console, which merely renders whatever logs CloudWatch received. Relying on “console logs alone” is a diagnostic trap: no execution-role permission means no log stream, and the console shows nothing.Secrets retrieval: never bake credentials into environment variables in plaintext. Store them in Secrets Manager or SSM Parameter Store SecureString and fetch them at cold start:
import boto3, os, json
_ssm = boto3.client("ssm")
_cached = None
def get_db_password():
global _cached
if _cached is None:
r = _ssm.get_parameter(Name=os.environ["DB_PWD_PARAM"], WithDecryption=True)
_cached = r["Parameter"]["Value"]
return _cached
The execution role needs ssm:GetParameter and kms:Decrypt on the CMK. Cache in module scope so warm invocations avoid the API call; use the Secrets Manager Lambda extension for automatic rotation-aware caching in higher-throughput functions.
ECR Encryption and Repository Protection
Amazon ECR encrypts all images at rest by default using AES-256 with an AWS-managed key, but regulated workloads typically require a customer-managed KMS key so that key rotation, key policies, and CloudTrail auditability are under the customer’s control. KMS encryption is configured only at repository creation time; an existing ECR repository cannot be flipped from AES-256 to KMS after the fact. Migration therefore requires creating a new KMS-encrypted repository, replicating or re-pushing the images, updating downstream consumers, and deleting the old repository. Cross-account consumers pulling from a KMS-encrypted repository must be granted kms:Decrypt on the CMK in addition to ECR read permissions, or the pull will fail with a KMS access error even if the repository policy allows the principal.
{
"encryptionConfiguration": {
"encryptionType": "KMS",
"kmsKey": "arn:aws:kms:us-east-1:111122223333:key/abcd-...-ef01"
},
"imageScanningConfiguration": { "scanOnPush": true },
"imageTagMutability": "IMMUTABLE"
}
Immutable tags prevent tag-hijack attacks where a validated v1.2.3 tag is silently overwritten by a malicious image after scanning.
Image Scanning: Basic, Enhanced, and Inspector
ECR offers two scanning modes. Basic scanning uses the open-source Clair CVE database, runs only on push (or manual invocation), and returns findings in the ECR console. It is free, but it does not perform continuous rescans, does not cover OS + programming-language packages together, and has no native integration with Security Hub. Enhanced scanning is powered by Amazon Inspector and covers both operating system packages and application language packages (Python, Java, Node.js, Go, Ruby, .NET). Inspector continuously monitors pushed images against updated vulnerability intelligence, so a CVE disclosed a week after the image was pushed still produces a finding without a rebuild.
Enhanced scanning is enabled at the registry level (per Region), with per-repository inclusion filters using wildcard patterns such as prod-* or team-a/*. This is the correct control for the common requirement of “scan most repositories but exclude sandbox/experimentation ones” — you define positive filters listing what should be scanned rather than negative exclusions on individual repos.
aws ecr put-registry-scanning-configuration \
--scan-type ENHANCED \
--rules '[{
"scanFrequency": "CONTINUOUS_SCAN",
"repositoryFilters":[{"filter":"prod-*","filterType":"WILDCARD"}]
},{
"scanFrequency": "SCAN_ON_PUSH",
"repositoryFilters":[{"filter":"dev-*","filterType":"WILDCARD"}]
}]'
Inspector Integration and Security Hub Aggregation
Amazon Inspector must be enabled in each account and Region where scanning is required. In an AWS Organizations setup, the security tooling account is designated as the delegated administrator for Inspector, which allows it to enable scanning, set auto-enroll for new member accounts, and view aggregated findings. Forgetting to delegate — or forgetting to toggle auto-enroll — is a subtle failure mode: new accounts joining the org silently ship containers to ECR that never get scanned, breaking coverage guarantees without any error surface.
Inspector findings flow into AWS Security Hub automatically when both services are enabled and Security Hub’s Inspector integration is turned on. Security Hub then normalizes findings into the AWS Security Finding Format (ASFF), correlates them with GuardDuty, Macie, and Config findings, and — when combined with a delegated Security Hub administrator plus cross-Region aggregation — presents a single pane of glass. EventBridge rules on Security Hub findings can route critical CVEs to Lambda for automated ticket creation, tag the offending image with a quarantine=true label, or block deployment via a pipeline gate.
Centralized Scanning and Cross-Account CI/CD
The recommended pattern for multi-account container workloads places a hardened central registry account at the core:
- Central account: hosts KMS-encrypted ECR repositories with enhanced scanning, immutable tags, and image signing (via Notation/Sigstore integrated with AWS Signer).
- Build accounts: run CodeBuild/CodePipeline jobs that build, push to central ECR, wait for Inspector findings, and gate on severity thresholds.
- Workload accounts (dev/stage/prod): pull images from the central registry via cross-account permissions.
Cross-account read access requires two layers: an IAM policy in the consuming account granting ecr:GetDownloadUrlForLayer, ecr:BatchGetImage, and ecr:GetAuthorizationToken, plus a repository policy on the ECR repo in the central account allowing the specific consumer account or role.
{
"Version": "2012-10-17",
"Statement": [{
"Sid": "AllowProdPull",
"Effect": "Allow",
"Principal": {"AWS":"arn:aws:iam::444455556666:role/EcsTaskExecutionRole"},
"Action": ["ecr:BatchGetImage","ecr:GetDownloadUrlForLayer"]
}]
}
Because ECR repository policies are resource-based, the intersection of identity and resource policy determines access — omitting either layer produces AccessDeniedException. When KMS is involved, the KMS key policy must also grant kms:Decrypt to the cross-account principal.
EKS Control Plane Logging and Observability
For EKS, the managed control plane is not directly accessible, so security-relevant Kubernetes events are exposed only when control plane logging is explicitly enabled. Five log types are available: api, audit, authenticator, controllerManager, and scheduler. The audit log is the highest-value security artifact — it records every API call to the cluster with the caller identity resolved via the IAM authenticator — and authenticator records the IAM-to-Kubernetes RBAC mapping decisions. All types stream to CloudWatch Logs in a /aws/eks/<cluster>/cluster log group, from which they can be subscribed to Kinesis Data Firehose, forwarded to S3, or shipped to a SIEM.
aws eks update-cluster-config --name prod-cluster \
--logging '{"clusterLogging":[{"types":["api","audit","authenticator",
"controllerManager","scheduler"],"enabled":true}]}'
Complement control plane logs with GuardDuty EKS Protection (runtime threat detection on nodes), and use IRSA (IAM Roles for Service Accounts) rather than node instance profiles so audit logs attribute AWS API activity to specific pods.
Common Traps
Relying only on scan-on-push: Basic scan-on-push catches vulnerabilities known at push time but does nothing about CVEs disclosed later against images already in the registry. Audit frameworks such as PCI DSS and FedRAMP require ongoing vulnerability assessment, which mandates enhanced scanning with CONTINUOUS_SCAN frequency plus Security Hub aggregation. A once-a-push snapshot fails the control.
Skipping KMS on ECR when encryption-at-rest is required: The default AES-256 encryption is real encryption, but compliance regimes that demand customer-managed keys, key rotation records, and per-principal kms:Decrypt audit trails cannot be satisfied by AWS-owned keys. Because encryption type is immutable per repository, this must be addressed at creation — “we’ll turn it on later” is impossible without repo recreation.
Forgetting Inspector delegated admin or auto-enroll: Without a delegated administrator for Inspector, each account owner must independently enable scanning and forward findings, which is operationally infeasible and produces coverage gaps. Without auto-enable for new member accounts, every new account created via Control Tower or Organizations starts with Inspector disabled, so its ECR images are unscanned even though Security Hub in the central account shows no findings — a silent false-negative rather than an obvious error.
Practical Problem: Use-Case Scenario
Scenario: Meridian Financial operates a multi-account AWS environment with production EKS clusters, ECS services, and multiple ECR registries spread across prod, dev, and a dedicated security account. Their engineering teams push container images via CI/CD pipelines into ECR and deploy to EKS/ECS while security maintains a centralized account for monitoring and compliance.
Challenge: A recent deployment delivered a container with a high-severity vulnerability that was not detected before production, and investigators found limited EKS control plane logs and fragmented scan results across accounts, slowing remediation.
Recommended Approach:
- Enable ECR repository-level protections: enforce image tag immutability, apply repository policies limiting push/pull by specific IAM roles, and encrypt repositories at rest with a dedicated AWS KMS customer managed key (CMK).
- Turn on image scanning on push (basic) and enable Amazon Inspector enhanced image scanning for ECR to produce vulnerability findings; integrate Inspector with AWS Security Hub for centralized aggregation of severities across accounts.
- Implement centralized cross-account scanning: configure ECR replication or grant a security-account CodeBuild/CodePipeline role cross-account pull permissions so the security account scans every image with Inspector and any additional SCA/DAST tools, storing artifacts in a centralized S3 bucket encrypted with the security account CMK.
- Enforce CI/CD gating: add a pipeline scan stage (CodeBuild/CodePipeline or GitHub Actions with STS assume-role) that queries Inspector/Security Hub findings and automatically blocks or requires approval for images with high/critical findings.
- Improve EKS observability: enable EKS control plane logs (API, Audit, Authenticator, ControllerManager, Scheduler) to CloudWatch Logs in a centralized logging account, enable CloudTrail for EKS API events, and use Container Insights and GuardDuty for runtime monitoring.
Rationale: This approach applies defense-in-depth: encrypting and protecting registries, automating enhanced scanning with Inspector, centralizing findings in Security Hub for consistent policy enforcement, gating deployments in CI/CD, and enabling EKS control plane logs for rapid detection and forensics, aligning with AWS least-privilege and centralized monitoring best practices.
← Vulnerability · All domains · Incident Response →
Practice these questions → · Timed practice on ExamRoll.io →
Pass the whole exam — not just this question
You found this answer. Get every verified question and explanation in one place, and save hours of prep. Free to start.
Pass your exam →