Securing Compute Workloads: EC2, Containers, and Lambda
Compute workload security is where infrastructure hardening meets identity: every EC2 instance, container task, and Lambda function runs with credentials, an attack surface, and a patch state you are responsible for. Task 3.2 tests whether you can harden each compute form factor — IMDSv2 and golden AMIs on EC2, scanned and immutable images in ECR, correctly split task and execution roles on ECS, IRSA on EKS, least-privilege execution and resource policies on Lambda — and then troubleshoot the failures those controls produce, from an instance SSM cannot reach to a task that cannot read its secret. This lesson works through EC2 credential protection and image hardening, vulnerability management with Amazon Inspector, container and Kubernetes security controls, Lambda's permission model including the confused-deputy problem, and a diagnostic playbook for the classic exam failure modes. The recurring theme: give each workload exactly one tightly-scoped identity, and know which role does which job.
On this page8 sections
- IMDSv2: closing the SSRF door to instance credentials
- Golden AMIs and patching: Image Builder, Patch Manager, and encrypted defaults
- Amazon Inspector: continuous vulnerability management as a loop
- ECR: securing the image supply chain
- ECS and Fargate: task roles, execution roles, and task hardening
- EKS essentials: pod identity, audit logs, and the private control plane
- Lambda security: execution roles, resource policies, and the confused deputy
- Troubleshooting compute controls: the four classic failures
- Enforce IMDSv2 across EC2 fleets — tokens, hop limits, AMI and account defaults, and IAM conditions — to shut down SSRF credential theft.
- Build hardened, patched compute images with EC2 Image Builder and SSM Patch Manager, with encryption on by default for EBS and AMIs.
- Design a vulnerability-management loop with Amazon Inspector across EC2, ECR images, and Lambda, feeding Security Hub and automated remediation.
- Distinguish ECS task roles from execution roles and apply Fargate isolation, secrets injection, and read-only filesystems correctly.
- Secure Lambda with least-privilege execution roles and resource-based policies that block confused-deputy invocation.
- Troubleshoot compute security failures: unmanaged SSM instances, unscanned resources, image-pull and secret-read errors, and denied invocations.
IMDSv2: closing the SSRF door to instance credentials
The instance metadata service at 169.254.169.254 hands out the temporary credentials for an instance's IAM role — which makes it the highest-value target on any EC2 host. With IMDSv1, a single GET request returns credentials, so any server-side request forgery (SSRF) flaw, misconfigured proxy, or open redirect that can coax the application into fetching an internal URL becomes credential theft. This is not hypothetical: it is the mechanism behind some of the most famous cloud breaches, and the exam expects you to name the fix immediately.
IMDSv2 makes metadata access session-oriented. A client must first send a PUT request with the X-aws-ec2-metadata-token-ttl-seconds header to obtain a token, then present that token in the X-aws-ec2-metadata-token header on every read. Typical SSRF primitives can issue simple GETs but cannot send a custom-header PUT, so the attack chain breaks. The default hop limit of 1 adds a second defense: the token-bearing response's TTL prevents it from being forwarded past the instance itself — though containerized workloads using the instance's IMDS need the hop limit raised to 2.
Enforcement is layered. At launch, set HttpTokens=required in the instance's metadata options. Bake the default into images with the AMI's ImdsSupport=v2.0 setting, and set Region-wide instance metadata defaults at the account level. Enforce organizationally with an SCP or IAM condition using ec2:MetadataHttpTokens on RunInstances. Detect drift with AWS Config, and remember the correlated GuardDuty signal: UnauthorizedAccess:IAMUser/InstanceCredentialExfiltration.OutsideAWS fires when an instance role's credentials are used from outside AWS — the smoke that says the metadata service already leaked. Always prefer instance roles over static access keys on hosts; rotation and revocation come free.
Golden AMIs and patching: Image Builder, Patch Manager, and encrypted defaults
Fleet hardening starts before boot. EC2 Image Builder turns AMI creation into a pipeline: a base image, an ordered list of build components (install agents, remove packages, apply CIS or STIG hardening — Amazon publishes managed STIG components), test components that validate the result, and distribution of the finished golden AMI across Regions and accounts. Because the pipeline runs on a schedule or on new-CVE triggers, the golden image stays current instead of decaying into a snowflake, and every instance launched from it inherits the same hardened baseline — including IMDSv2-required metadata defaults and pre-installed SSM and CloudWatch agents.
Running fleets still drift, which is Systems Manager Patch Manager's job: patch baselines define which patch classifications and severities are approved (with optional auto-approval delays), patch groups map baselines to instance tags, and maintenance windows schedule the Scan or Scan and install operations. Compliance state per instance flows into Systems Manager Compliance and on to Security Hub, so "show me every instance missing critical patches" is a query, not an audit project. Pair this with Session Manager and EC2 Instance Connect for administrative access — auditable, IAM-gated shells with no inbound port 22 and no long-lived SSH keys.
Storage defaults close the loop. Enable EBS encryption by default per Region so every new volume and snapshot is KMS-encrypted without per-launch diligence, and build AMIs from encrypted snapshots so the golden image itself is encrypted. Deeper KMS mechanics — key policies, cross-account snapshot sharing — belong to Domain 5; here the exam wants the operational posture: encrypted by default, hardened by pipeline, patched by schedule.
Amazon Inspector: continuous vulnerability management as a loop
Amazon Inspector is the vulnerability scanner across all three compute form factors, and its defining trait is that it is continual — you enable it (organization-wide via a delegated administrator) and it discovers and assesses resources automatically rather than running one-off assessments.
For EC2, Inspector scans instances managed by Systems Manager — the SSM Agent is the collection path — inventorying packages and comparing them against CVE databases, with an agentless option that assesses EBS snapshots for instances SSM cannot manage. For ECR, enhanced scanning assesses container images on push and then continuously: when a new CVE is published, already-stored images are re-evaluated, so a clean image can legitimately develop critical findings a month later. For Lambda, standard scanning covers dependency vulnerabilities in the function's packages, and code scanning inspects your own function code for embedded secrets and injection-style flaws.
Findings carry an Inspector score — a contextualized severity that adjusts the CVSS base score using environmental factors like network reachability and whether an exploit is available — so a critical CVE on an isolated, unreachable instance ranks below a moderate one on an internet-facing host. Prioritize by that score, not raw CVSS.
The design pattern the exam rewards is the remediation loop: Inspector findings flow to Security Hub for aggregation and to EventBridge for action — trigger Patch Manager to patch the CVE, kick off an Image Builder pipeline to rebuild the golden AMI, notify the owning team, or fail a deployment. Complementing Inspector's static view, GuardDuty Runtime Monitoring watches what workloads actually do at runtime; and in the pipeline itself, Amazon CodeGuru Security and Amazon Q Developer surface code-level vulnerabilities before anything ships.
ECR: securing the image supply chain
Every container control downstream depends on trusting what is in the registry, so Amazon ECR is where container security starts. Four controls matter for the exam.
Scanning. ECR offers basic scanning (on push or on demand, OS packages only) and enhanced scanning, which delegates to Amazon Inspector for the on-push plus continuous rescanning behavior described above, covering both OS and programming-language packages. "Images must be re-checked automatically when new CVEs are published" is enhanced scanning, full stop.
Immutable tags. With tag immutability enabled, a tag can never be overwritten to point at a different image. Without it, an attacker (or an accident) can push a new image as myapp:prod, and every task definition referencing that tag silently deploys the replacement — a supply-chain attack that scanning alone does not stop. Immutability forces new content to arrive under new tags, making deployments auditable and pinnable; referencing images by digest is the strictest variant of the same idea.
Repository policies. ECR repositories carry resource-based policies, which is how you grant cross-account pull to workload accounts without creating roles in the registry account — grant ecr:BatchGetImage and ecr:GetDownloadUrlForLayer to the consuming principals, and nothing more. Keep push rights confined to the CI/CD pipeline's role.
Encryption. Repositories encrypt images at rest with AES-256 or KMS; choose a customer managed key when you need key-level access control and CloudTrail visibility of decryption. Round out hygiene with lifecycle policies that expire stale images — an unscanned, forgotten image from two years ago is exactly what gets redeployed in an incident. Image signing and verification exist at mention level (Signer with Notation); know they address provenance, not vulnerabilities.
ECS and Fargate: task roles, execution roles, and task hardening
The most reliably tested distinction in container security is the two roles attached to an ECS task — because they answer different questions:
| Aspect | Task execution role | Task role |
|---|---|---|
| Who uses it | The ECS agent / Fargate infrastructure, on your behalf | Your application code inside the containers |
| When | Task startup: pulling the image, setting up logging, injecting secrets | Runtime: every AWS API call the app makes |
| Typical permissions | ecr:GetAuthorizationToken, image pull actions, logs:CreateLogStream/PutLogEvents, secretsmanager:GetSecretValue for secrets referenced in the task definition | DynamoDB, S3, SQS — whatever the workload actually needs, least-privilege |
| Failure mode when wrong | Task fails to start: cannot pull image, cannot inject secret | Running app gets AccessDenied on its own API calls |
The trap: secrets referenced in the task definition's secrets block — injected as environment variables from Secrets Manager or SSM Parameter Store at startup — are fetched by the execution role. Secrets fetched by application code at runtime use the task role (delivered via the container credentials endpoint, per-task, so co-located tasks never share credentials). Granting the wrong role is the classic broken deployment, walked through in the final section.
Fargate hardens the substrate: each task runs in its own isolated environment with a dedicated kernel — no shared host to escape to, no privileged containers, no host-path mounts, and AWS patches the underlying infrastructure. Within any task, set readonlyRootFilesystem in the container definition so a compromised process cannot modify its own filesystem, drop non-root users in the image, and keep containers from running with elevated Linux capabilities.
EKS essentials: pod identity, audit logs, and the private control plane
EKS security at specialty level reduces to three controls; deep Kubernetes administration is out of scope, but these are fair game.
Least-privilege pod identity. The anti-pattern is giving the node's instance role every permission any pod might need — every pod on the node then holds the union. The fix is per-pod credentials: IAM Roles for Service Accounts (IRSA) associates an IAM role with a Kubernetes service account through the cluster's OIDC identity provider — pods assume the role with sts:AssumeRoleWithWebIdentity using a projected service account token, and the role's trust policy names the specific service account. The newer EKS Pod Identity feature reaches the same goal with less setup: an EKS-run agent and a direct association between role and service account, no per-cluster OIDC provider registration. Either way, the exam answer to "one pod needs S3 access, others must not have it" is pod-level identity, never node-role inflation. Blocking pods from the node's instance metadata (or enforcing IMDSv2 with hop limit 1) closes the fallback path to node credentials.
Control-plane audit logs. EKS can ship five control-plane log types to CloudWatch Logs — api, audit, authenticator, controllerManager, and scheduler. They are off by default; the audit and authenticator streams are the ones that answer "who did what to the cluster," and GuardDuty's EKS audit log monitoring consumes this activity for threat detection.
Private endpoint. The cluster API server endpoint is public by default. Disable public access (or restrict it to allowlisted CIDRs) and enable the private endpoint so kubectl and node-to-control-plane traffic stay inside the VPC — an internet-reachable API server is an unnecessary attack surface even with authentication in front of it.
Lambda security: execution roles, resource policies, and the confused deputy
Lambda has two independent permission surfaces, and questions turn on which one is broken. The execution role governs what the function can do — assumed by the service at invocation, its credentials handed to your code. Least privilege means one role per function, not a shared "lambda-role" with accreted permissions; a function that reads one DynamoDB table should hold exactly that.
The resource-based policy governs who may invoke the function. When S3, SNS, or EventBridge invokes a function, the service principal (for example s3.amazonaws.com) must be granted lambda:InvokeFunction in the function's policy. That grant creates the confused-deputy risk: any S3 bucket — including one in a stranger's account — could otherwise trigger your function through the trusted service. The fix is scoping the grant with aws:SourceArn (the specific bucket ARN) and aws:SourceAccount, so the service may only pass through invocations originating from your resource. This pattern generalizes to every service-to-service resource policy on the exam.
VPC attachment is about egress, not ingress. Attaching a function to a VPC controls where its outbound traffic goes (via Hyperplane-managed ENIs) and lets it reach private resources like RDS — but it removes default internet access (add a NAT gateway or VPC endpoints) and does not change who can invoke the function; invocation always flows through the Lambda API and IAM. Environment variables are encrypted at rest with KMS — use a customer managed key for auditable access control, but prefer Secrets Manager for actual secrets so rotation exists. At mention level: code signing with AWS Signer lets Lambda reject unsigned or modified deployment packages, and GuardDuty Lambda Protection surfaces findings such as CryptoCurrency:Lambda/BitcoinTool.B when a hijacked function starts mining.
Troubleshooting compute controls: the four classic failures
Instance unreachable by SSM. An instance missing from Fleet Manager (so Session Manager, Patch Manager, and Inspector's SSM-based scanning all fail) has one of three causes: the SSM Agent is not running; the instance profile lacks the AmazonSSMManagedInstanceCore permissions; or there is no network path to the SSM endpoints. For private subnets, that path means interface VPC endpoints for ssm, ssmmessages, and ec2messages (or NAT egress). Check agent, role, path — in that order.
Inspector not scanning an instance. Usually the same root cause: Inspector's EC2 scanning rides on SSM management, so an unmanaged instance is invisible to it. Fix SSM coverage first; agentless snapshot-based assessment is the fallback for hosts that cannot run the agent.
Scenario: the task that cannot read its secret. A new ECS service's tasks stop immediately with ResourceInitializationError: unable to pull secrets or registry auth. Walk it: the failure is at startup, so this is execution-role territory, not the task role. Check, in order: (1) the execution role grants secretsmanager:GetSecretValue on the specific secret ARN referenced in the task definition's secrets block — and kms:Decrypt on the key if the secret uses a customer managed key; (2) the same role can pull the image (ecr:GetAuthorizationToken plus the pull actions, and the cross-account repository policy if ECR lives elsewhere); (3) tasks in private subnets can reach Secrets Manager and ECR — interface endpoints for secretsmanager, ecr.api, and ecr.dkr, plus the S3 gateway endpoint ECR needs for image layers. The distractor answer adds the permission to the task role; startup failures make that wrong every time.
Lambda AccessDenied on invoke. The caller is refused before the function runs, so inspect the resource-based policy: the invoking service or account needs lambda:InvokeFunction, with aws:SourceArn matching the actual triggering resource. The execution role is irrelevant to who may invoke.
Tip. Task 3.2 scenarios test whether you can map a symptom to the right identity or control. "An SSRF flaw exposed instance credentials" → enforce IMDSv2 (HttpTokens required, ec2:MetadataHttpTokens condition). "The task can't pull the image" or "can't read its secret at startup" → the execution role (or missing VPC endpoints), never the task role. "Images must be rescanned when new CVEs appear" → ECR enhanced scanning with Inspector; "prevent the prod tag from being overwritten" → tag immutability. "AccessDenied invoking the function" → the Lambda resource-based policy, scoped with aws:SourceArn against confused deputies, and "instance not visible to Session Manager or Inspector" → SSM Agent, instance profile, or the ssm/ssmmessages/ec2messages endpoints.
- IMDSv2 defeats SSRF credential theft by requiring a token from a custom-header PUT; enforce it with HttpTokens=required, AMI ImdsSupport v2.0, account-level metadata defaults, and the ec2:MetadataHttpTokens IAM condition — and raise the hop limit to 2 only for containers on EC2.
- Golden AMIs come from EC2 Image Builder pipelines with hardening (STIG) and test components; running fleets stay compliant via Patch Manager baselines, patch groups, and maintenance windows, with EBS encryption on by default.
- Amazon Inspector is continual: SSM-based EC2 scanning, ECR enhanced scanning on push and again when new CVEs publish, and Lambda dependency plus code scanning — findings flow to Security Hub and EventBridge for automated remediation.
- Prioritize by the Inspector score, which adjusts CVSS for context like network reachability and exploit availability.
- ECR hardening = enhanced scanning, immutable tags (no silent overwrite of prod tags), least-privilege repository policies for cross-account pulls, and KMS encryption.
- Execution role acts at task startup (pull image, write logs, inject secrets); task role serves the running application's API calls — startup failures implicate the execution role, runtime AccessDenied implicates the task role.
- On EKS, grant AWS access per pod with IRSA or EKS Pod Identity, never by inflating the node instance role; enable control-plane audit logs and prefer a private API endpoint.
- Lambda's execution role decides what the function can do; its resource-based policy decides who can invoke it — scope service grants with aws:SourceArn and aws:SourceAccount to kill the confused deputy.
Frequently asked questions
How does IMDSv2 prevent SSRF attacks from stealing EC2 credentials?
IMDSv2 requires a session token obtained via a PUT request carrying the X-aws-ec2-metadata-token-ttl-seconds header, and that token must accompany every metadata read in the X-aws-ec2-metadata-token header. Typical SSRF vulnerabilities let an attacker trigger simple GET requests but not custom-header PUTs, so the attacker can never obtain the token needed to read the instance role's credentials. The default hop limit of 1 additionally stops the token from being usable beyond the instance itself.
What is the difference between an ECS task role and a task execution role?
The task execution role is used by the ECS agent and Fargate infrastructure to start your task: pulling the container image from ECR, creating and writing CloudWatch log streams, and fetching secrets referenced in the task definition for injection as environment variables. The task role is assumed by your application code at runtime for its own AWS API calls, delivered through the per-task container credentials endpoint. Startup failures (image pull, secret injection) point at the execution role; runtime AccessDenied errors point at the task role.
Why does my ECS task fail with 'unable to pull secrets or registry auth'?
This is a startup-time ResourceInitializationError, so the task execution role or the network path is at fault. Verify the execution role has secretsmanager:GetSecretValue on the referenced secret (plus kms:Decrypt if it uses a customer managed key) and the ECR pull permissions; check any cross-account ECR repository policy; and for tasks in private subnets, confirm interface endpoints for secretsmanager, ecr.api, and ecr.dkr plus the S3 gateway endpoint exist. Adding permissions to the task role will not fix a startup failure.
How does Amazon Inspector scan EC2, ECR, and Lambda?
Inspector runs continually once enabled. EC2 instances are scanned through Systems Manager — the SSM Agent inventories packages, with an agentless EBS-snapshot option for unmanaged hosts. ECR enhanced scanning assesses images on push and rescans stored images automatically when new CVEs are published. Lambda scanning covers dependency vulnerabilities in function packages, and code scanning additionally inspects your function code for issues like embedded credentials. Findings carry a contextualized Inspector score and integrate with Security Hub and EventBridge.
Does putting a Lambda function in a VPC make it more secure?
Only for outbound traffic. VPC attachment controls where the function's egress goes — it can reach private resources such as RDS, loses default internet access unless you add NAT or VPC endpoints, and its traffic is subject to your network controls. It does not change who can invoke the function: invocation always goes through the Lambda API and is governed by IAM and the function's resource-based policy. To restrict invokers, scope the resource-based policy with aws:SourceArn and aws:SourceAccount.
How do pods on EKS get least-privilege access to AWS services?
Use IAM Roles for Service Accounts (IRSA) or the newer EKS Pod Identity. IRSA links an IAM role to a Kubernetes service account through the cluster's OIDC provider, and pods assume it via sts:AssumeRoleWithWebIdentity using a projected token; Pod Identity achieves the same per-pod credentials through an EKS-managed agent and a direct role-to-service-account association without per-cluster OIDC setup. Both avoid the anti-pattern of granting permissions to the node instance role, where every pod on the node would inherit them.
Sign up free to mark lessons complete, bookmark topics and track your exam readiness.