AWS Core Services and Architecture Questions
Amazon Web Services' core service catalog and how the pieces compose into a working system: EC2, Lambda, S3, VPC, IAM, RDS, and the managed-service ecosystem. Covers service selection within AWS, common reference architectures, the AWS Well-Architected Framework pillars, and operational patterns specific to the platform. For provider-agnostic compute or storage trade-offs, see the cross-cloud entries.
You detect a suspicious IAM assume-role event, for example a role assumed from an unusual region or IP. Walk through how you'd detect this, contain it (revoke or limit the session, tighten the trust policy), and make sure the automation that does this can't itself be abused.
Sample Answer
Direct answer
Treat this as a security incident, not a policy edit: use CloudTrail-derived signals, correlated through GuardDuty and AWS Config, to detect and score the anomalous AssumeRole call, contain it by cutting off that specific session's future permissions (not by editing the role's trust policy, which only affects future AssumeRole calls), and lock the containment automation itself down so a false positive or a compromised detector can't turn into its own incident.
Structured elaboration
Detect
- CloudTrail records every
AssumeRole/AssumeRoleWithWebIdentity/AssumeRoleWithSAMLcall with source IP, region, and user agent. Route these events through an EventBridge rule into a triage Lambda or Step Functions state machine. - GuardDuty (Amazon's threat-detection service) ingests those CloudTrail management events plus its own threat intelligence and flags IAM / AWS Security Token Service (STS) anomalies: impossible-travel geography, an unfamiliar network for that principal, or an API call the principal has never made before. Treat a GuardDuty finding as one scored input, not the sole trigger.
- AWS Config runs as the compliance/drift layer in parallel: it snapshots the role's trust policy and permission boundary over time, so you can tell whether this AssumeRole succeeded because of a recent, possibly unauthorized trust-policy change, versus a genuine anomaly against a policy that hasn't moved.
Contain (the session, not the role)
- You cannot revoke an already-issued STS session token directly. AWS's actual mechanism: IAM's "Revoke active sessions" action attaches an inline policy named
AWSRevokeOlderSessionsto the role, denying all actions to any session whoseaws:TokenIssueTimepredates the revoke timestamp (with roughly 30 seconds of clock-skew tolerance), while leaving brand-new AssumeRole calls unaffected. - For a narrower blast radius than "deny the whole role," attach a Deny statement keyed on
aws:TokenIssueTimecombined withaws:PrincipalArnoraws:SourceIdentity, so only the flagged session is cut off, not every legitimate caller of that role. - Editing the trust policy is a separate control: it stops future AssumeRole calls, it does nothing to a session already issued. Don't rely on it as the primary containment step.
- Escalate on high confidence: rotate the credentials of the upstream calling principal (IAM user, federation provider, or CI system), since the assumed-role session is a symptom, not the root cause.
Keep the automation from being abused
- Run the detector/containment workflow from a dedicated account, with a role scoped to "attach exactly this deny statement to exactly the flagged role ARN" and nothing broader: no
iam:CreateRole, no wildcardiam:AttachRolePolicy, noiam:PassRole. - Session tags on the automation's own assumed role record who or what triggered each action, so every containment step is attributable in CloudTrail.
- Stage the response: a narrow, low-confidence "soft deny" (block only the riskiest actions) can auto-execute; a full
AWSRevokeOlderSessions-style lockout requires a human-approval step (a Step Functions callback, for example) unless confidence crosses a high threshold. This bounds the automation's own worst-case blast radius, a false positive can't turn into a self-inflicted denial-of-service on a production role.
Worked example
Role data-sync-role is normally assumed only from a corporate CIDR range in us-east-1. CloudTrail shows an AssumeRole call for that role from an unfamiliar region with a new user agent string. GuardDuty correlates this with its anomaly detection and raises a finding; AWS Config confirms the role's trust policy hasn't changed recently, ruling out an authorized-but-undocumented change. The EventBridge rule fires the containment Lambda, which attaches a Deny statement scoped to aws:TokenIssueTime before now and aws:SourceIdentity matching that specific session. A follow-up CloudTrail query confirms subsequent calls under that session now fail with AccessDenied, while other legitimate sessions on the same role continue working. A ticket opens for a human to decide whether the upstream credential (the CI system or federated user that called AssumeRole) also needs rotation.
Trade-offs & pitfalls
- Staged containment avoids an overly broad deny becoming a self-inflicted denial-of-service on a legitimate, high-traffic role; don't wire auto-hard-deny until the anomaly-scoring signal is tuned.
AWSRevokeOlderSessionsdenies the entire role by default, not just the flagged session, unless you narrow the condition withaws:PrincipalArn/aws:SourceIdentity: decide up front whether that blast radius is acceptable for the specific role.- The automation account's own permissions are themselves an attack surface: scope it to specific role ARNs, never a wildcard resource.
- Store every generated deny policy and its triggering event in an immutable log so a later incident review can reconstruct exactly what containment did and when.
Design an EventBridge-driven automated response: when a GuardDuty finding fires (say, an EC2 instance making suspicious outbound connections), how would you wire EventBridge rules to trigger containment via Lambda or Systems Manager, and what least-privilege considerations apply to the automation itself?
Sample Answer
Direct answer
Wire an EventBridge rule to match GuardDuty findings by type and severity, routing matched events to a Lambda "triage" function and to Security Hub for tracking. The triage Lambda enriches the finding (instance tags, attached AWS Identity and Access Management (IAM) role, Virtual Private Cloud (VPC) context, your own isolated network in AWS) and invokes a Systems Manager (SSM) Automation document to contain the instance, typically by attaching a quarantine security group that blocks egress while preserving SSM connectivity, rather than terminating it outright, so evidence isn't destroyed. Every role in that chain (EventBridge target, the triage Lambda, the SSM Automation execution role) gets the minimum permissions to do exactly its one step, nothing broader, since the automation itself is now a privileged actor that needs to be as trustworthy as any human responder.
Structured elaboration
flowchart LR
GD["GuardDuty finding
(suspicious outbound traffic)"] --> EB["EventBridge rule
matches finding type/severity"]
EB --> TR["Triage Lambda
enrich: tags, IAM role, VPC, recent CloudTrail"]
TR --> SH["Security Hub
finding updated, workflow status set"]
TR --> SSM["SSM Automation document
runs on the instance via SSM Agent"]
SSM --> QSG["Attach quarantine security group
(block egress, allow SSM only)"]
SSM --> SNAP["EBS snapshot +
CloudTrail/VPC Flow Log export to S3"]
QSG --> NOTIFY["SNS to on-call / ticket"]
SNAP --> NOTIFY
NOTIFY --> APPROVE{"Analyst
approval"}
APPROVE -->|approve remediation| CLEAN["Rotate credentials,
rebuild instance, restore SG"]
APPROVE -->|false positive| REVERT["Remove quarantine SG,
close finding"]
Detection and routing: the EventBridge rule's event pattern filters on the GuardDuty finding's type and severity fields so only findings above your response threshold trigger automation; lower-severity findings can route to Security Hub for visibility without triggering containment.
Containment: attaching a quarantine security group (deny all egress except to SSM endpoints) is generally preferred over immediately terminating the instance, because termination destroys the evidence you need for the next step. The same pattern applies whether the finding is outbound network activity or, in a related variant, an EC2 instance showing suspicious PutObject patterns against S3 (a data-exfiltration signature): the response is still containment-first, not termination-first.
Forensic data collection: capture an Elastic Block Store (EBS) snapshot of the instance's volumes before any remediation, and export the artifacts that let an analyst reconstruct what happened: CloudTrail (API-level activity, including who/what made the suspicious calls), S3 access logs (for the exfiltration-to-S3 variant, showing which objects were read or written and from where), and VPC Flow Logs (network-level record of the suspicious connections GuardDuty flagged). Store all of it in a locked-down forensic S3 bucket with versioning and access logging of its own.
Credential handling: if the finding suggests the instance's IAM role or an associated credential may be compromised (either variant: outbound C2-style traffic or S3 exfiltration), revoke or rotate the exposed credentials as an explicit containment step, not just a follow-up cleanup task; a still-valid credential is an ongoing exposure even after the instance itself is quarantined.
Cross-account scoping: in a multi-account setup, the automation should be able to act on the affected account's resources without requiring standing, account-wide privileges. Use a dedicated automation/security-tooling account whose Lambda and SSM roles assume narrowly-scoped, temporary cross-account roles into the affected account, limited to the specific containment actions (attach SG, run SSM document, create snapshot) and denied everything else, including account-wide administrative actions.
Least-privilege for the automation itself: separate the Lambda execution role (read GuardDuty/EC2/SSM metadata, start SSM Automation executions, write to the forensic S3 prefix, update Security Hub) from the SSM Automation role (act only on the specific, tag- or ARN-scoped target instance, where an ARN, Amazon Resource Name, is AWS's unique identifier for a specific resource). Neither role should hold broad iam:*, ec2:*, or s3:* permissions; scope by resource ARN and, where possible, by condition keys tied to the finding's specific instance.
Reporting and prevention (mapped to Well-Architected pillars): close the loop with a written incident report and feed findings back into architecture, framed against four Well-Architected concerns:
- Detection: was the GuardDuty finding type/severity threshold right, or did this near-miss a lower bucket that wouldn't have triggered automation?
- Least privilege: did the compromised instance's IAM role have more access than the workload needed, and should its policy be tightened?
- Automation: did the playbook run cleanly end-to-end, or were there manual steps that should be automated for the next incident?
- Governance: are the account boundaries, tagging, and approval gates around this automation documented and enforced, so this response pattern is repeatable and auditable, not tribal knowledge?
Worked example
GuardDuty fires Backdoor:EC2/C&CActivity.B (suspicious outbound to a known command-and-control IP) for instance i-0123456789. EventBridge routes it to the triage Lambda, which tags the finding as IN_PROGRESS in Security Hub and invokes the SSM Automation document. The document attaches the quarantine security group, takes an EBS snapshot, exports the instance's last hour of CloudTrail and VPC Flow Log entries to the forensic bucket, and revokes the instance profile's temporary credentials by detaching and reissuing under a new role. An analyst is paged via SNS, reviews the captured evidence, confirms it's a genuine compromise (not a false positive from a legitimate but newly-added external integration), and approves the remediation branch: the instance is rebuilt from a known-good AMI rather than "cleaned in place," and the incident report goes into the next architecture review under the four pillars above.
Trade-offs and pitfalls
- Fully automated, unapproved termination is tempting for speed but destroys evidence and risks taking down a false positive in production; a human-approval gate before destructive remediation (not before containment) is the right balance for most environments.
- If the automation's own IAM role is over-privileged, an attacker who compromises the automation path (rather than the original instance) inherits broad account access, which is a worse outcome than the original finding; this is why the automation's roles get the same least-privilege scrutiny as the workload they're protecting.
- Snapshotting and log export take time and add cost; prioritize capturing the volatile, hard-to-recover evidence (memory-adjacent artifacts, recent flow logs) before slower steps, and don't let evidence collection delay containment (attaching the quarantine SG) which is the step that actually stops ongoing damage.
- Test the playbook against synthetic findings in a non-production account; a badly-scoped SSM document run for the first time against a real incident is a poor place to discover it also quarantines the bastion host used to investigate it.
What S3 security best practices would you apply to protect sensitive data in a bucket? Cover Block Public Access, bucket policies vs IAM policies, server-side encryption options, enforcing TLS, and how you'd let another account read from the bucket without making it public.
Sample Answer
Layer the controls rather than relying on one: deny public access by default at both the account and bucket level, prefer IAM (Identity and Access Management) and bucket policies over ACLs (Access Control Lists) for access control, encrypt at rest (SSE-S3: Server-Side Encryption with Amazon S3-managed keys, as a baseline; SSE-KMS: Server-Side Encryption with AWS Key Management Service keys, with an auditable key policy for sensitive data), require TLS (Transport Layer Security) on every request, and for another account that needs read access, grant a scoped IAM role and bucket-policy combination rather than making anything public.
Block Public Access
Enable S3 Block Public Access at both the account level and the bucket level. Account-level coverage matters because bucket-level settings alone leave every other bucket in the account exposed to a future misconfiguration. Avoid ACLs entirely for new designs; they're the legacy mechanism and bucket policies/IAM give more precise, auditable control.
Bucket policies vs. IAM policies
IAM policies are principal-scoped: attach them to the users/roles that should have access. Bucket policies are resource-scoped and are the right tool for cross-account access or for conditions that must apply regardless of which principal is making the request, such as denying non-TLS traffic. In practice, sensitive buckets use both: IAM policies for your own account's principals, and a bucket policy carrying explicit deny statements (non-TLS, non-org principals) as a backstop.
Server-side encryption options
- SSE-S3: S3-managed keys, no extra setup, a reasonable baseline for non-sensitive data.
- SSE-KMS: keys managed in KMS, with a separate key policy controlling who can decrypt, and CloudTrail logging of every KMS usage. This is the right choice for sensitive data because it adds a second, independently auditable permission system on top of S3's own.
- SSE-C: the client supplies and transmits the encryption key on every request. It's operationally fragile (the key isn't stored by AWS at all) and rarely worth choosing over SSE-KMS.
Enforce TLS
Add a bucket policy statement that denies any request where aws:SecureTransport is false, so plaintext HTTP requests are rejected outright rather than relying on clients to always use HTTPS.
Cross-account read without making the bucket public
The pattern is: the consuming account gets an IAM role scoped to exactly what it needs, and the bucket policy grants that specific role (not the whole account, and never *) read access to a specific prefix.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowCrossAccountReadViaRole",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::222222222222:role/PartnerReadRole"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::acme-shared-reports/exports/*",
"Condition": {
"StringEquals": {
"aws:SourceAccount": "222222222222"
}
}
},
{
"Sid": "DenyInsecureTransport",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::acme-shared-reports",
"arn:aws:s3:::acme-shared-reports/*"
],
"Condition": {
"Bool": {
"aws:SecureTransport": "false"
}
}
}
]
}
If the objects are SSE-KMS encrypted, the bucket policy alone isn't enough: the KMS key policy also has to grant kms:Decrypt to that same role, because S3 permissions and KMS permissions are two separate systems that both have to say yes.
Serving both private documents and public static assets from the same platform
Don't try to solve this with one bucket and per-object ACL exceptions to Block Public Access; a single misconfigured object exposes data. Use two buckets: a private bucket for sensitive documents, kept fully behind Block Public Access and accessed only via presigned URLs or app-tier logic, and a separate public-assets bucket served through CloudFront using Origin Access Control (OAC), the current recommended mechanism (replacing the older Origin Access Identity, OAI) for letting only CloudFront read a bucket that itself still blocks all direct public access. "Public" delivery then flows through CloudFront's edge, not through a bucket that's actually open to the internet.
Trade-offs and pitfalls
- Forgetting the KMS side of a cross-account grant is the single most common cause of "the bucket policy says allow, but I still get Access Denied" for SSE-KMS objects.
- Using OAI on a new CloudFront-to-S3 setup instead of OAC is legacy practice; OAC is the current recommendation and integrates better with SSE-KMS.
- Bucket-level Block Public Access without the account-level setting leaves other buckets in the account exposed to future mistakes.
- SSE-C's client-managed-key model is rarely worth the operational fragility versus SSE-KMS for anything beyond a narrow compliance requirement that specifically mandates it.
Walk through AWS KMS key concepts: symmetric vs asymmetric CMKs, customer-managed vs AWS-managed keys, key policies vs IAM policies, and automatic rotation. What changes when you need cross-account access to a key, or a strict separation-of-duties requirement across a multi-account environment?
Sample Answer
Direct answer
AWS Key Management Service (KMS) is the managed service that creates, stores, and controls cryptographic keys. AWS now calls these KMS keys (you'll still hear the older term CMK, customer master key, used interchangeably). A KMS key is either symmetric (one key used for both encrypt and decrypt, the default for almost everything) or asymmetric (a public/private key pair, used for signing or for cases where encryption has to happen outside KMS). Separately, a key can be AWS managed (AWS creates and rotates it for you, you get no policy control) or customer managed (you own the key policy, rotation schedule, and lifecycle). Access to a key is governed first by its key policy, a resource policy attached directly to the key, and only within what that policy allows can AWS Identity and Access Management (IAM) policies grant identities permission to use it.
Structured elaboration
Key types
- Symmetric keys: AES-256, used for the vast majority of workloads (S3 SSE-KMS, EBS, RDS, EFS). KMS never lets the symmetric key material leave the service; you always call KMS to encrypt or decrypt.
- Asymmetric keys: RSA or elliptic-curve pairs, used for digital signatures or when a public key must be shared with a system outside AWS. Slower and not meant for bulk data.
- Neither key type rotates the same way: automatic annual rotation is available for customer managed symmetric keys as an opt-in setting; asymmetric and HMAC keys are rotated manually, by creating a new key and repointing an alias.
Key ownership tiers
| Tier | Who controls the key policy | Rotation | Typical use |
|---|---|---|---|
| AWS owned key | AWS | AWS-controlled | Backing some AWS service internals, invisible to you |
| AWS managed key | AWS | Automatic, AWS-controlled | Default encryption when you don't specify a key (e.g., default EBS or S3 encryption) |
| Customer managed key | You | Optional automatic rotation you enable | Anything needing custom access control, cross-account sharing, or a compliance-driven audit trail |
Key policies vs IAM policies: the key policy is the resource-level gate and is evaluated first; if it doesn't allow an action, no IAM policy can override that. Most customer managed keys use a key policy that delegates day-to-day permission management to IAM (a policy statement enabling the account's IAM policies), so you don't have to touch the key policy for every new role, only for cross-account or unusual grants.
Envelope encryption: services like S3, EBS, and RDS don't send your bulk data to KMS. They call GenerateDataKey to get a plaintext data key plus an encrypted copy, encrypt the data locally with the plaintext key, discard the plaintext key, and store only the encrypted data key alongside the ciphertext. This is why KMS-backed encryption scales to large objects without becoming a network bottleneck.
Grants: a lighter-weight, revocable way to hand a specific principal or service permission to use a key for defined operations, without editing the key policy. Grants are how many AWS service integrations, and cross-account or cross-service delegation, work under the hood.
A distinct, easily-confused option: SSE-C. S3 also supports server-side encryption with customer-provided keys (SSE-C), where you supply your own raw AES-256 key on every request and AWS never stores it at all. That is a different model from a customer managed KMS key: with SSE-C, if you lose the key, AWS cannot help you recover the data, and there's no KMS audit trail because KMS isn't involved.
Encryption options across storage services
| Service | Encryption options |
|---|---|
| S3 | SSE-S3 (AWS owned key), SSE-KMS (AWS managed or customer managed key), SSE-C (customer-supplied key, not stored by AWS) |
| EBS | Encryption at rest backed by a KMS key (AWS managed or customer managed); can be enabled by default per account/region |
| EFS | Encryption at rest via KMS, encryption in transit via TLS between clients and mount targets, independent of the at-rest setting |
Cross-account access: the key's owning account must add a key policy statement naming the external account or role ARN (Amazon Resource Name, AWS's unique identifier string for a resource) and the allowed actions (e.g., kms:Decrypt), and the calling account's IAM policy must separately allow that same action on the key's ARN. Both sides have to agree; missing either one fails closed.
Multi-account separation of duties: a common pattern is a dedicated security/key-management account that owns all customer managed keys. The key policy grants a narrow "key user" role to workload accounts (encrypt/decrypt only) and a separate "key administrator" role, kept out of the workload accounts entirely, for managing the key policy and lifecycle. That way no single workload-account operator can both encrypt data and change who's allowed to decrypt it, and CloudTrail in the central security account gives one place to audit every key use across the organization.
Data residency: KMS keys are regional by default, the key material never leaves the region it was created in. AWS also offers multi-Region keys, a set of replica keys sharing the same key material across regions, purely to support disaster-recovery re-encryption without touching ciphertext. If the requirement is data residency or sovereignty rather than DR, that's a reason to deliberately avoid multi-Region keys and keep a single regional key, since the whole point of a residency requirement is that the key material must not exist anywhere else.
Worked example
Account A (a workload account) needs to decrypt S3 objects encrypted with a customer managed key that lives in Account B (the security account). Both sides need an explicit statement. The key policy in Account B must include something like:
{
"Sid": "AllowWorkloadAccountDecrypt",
"Effect": "Allow",
"Principal": { "AWS": "arn:aws:iam::111111111111:role/workload-read-role" },
"Action": ["kms:Decrypt", "kms:DescribeKey"],
"Resource": "*"
}
And the IAM policy attached to workload-read-role in Account A must independently allow:
{
"Effect": "Allow",
"Action": ["kms:Decrypt", "kms:DescribeKey"],
"Resource": "arn:aws:kms:us-east-1:222222222222:key/EXAMPLE-KEY-ID"
}
If either statement is missing, the decrypt call fails, which is exactly the separation-of-duties property the multi-account pattern is designed to give you: Account A's own admins cannot grant themselves that access unilaterally.
Trade-offs & pitfalls
The most common trap is forgetting that key policy and IAM policy are both required, an IAM policy alone is not sufficient, which shows up as confusing access-denied errors when only one side was updated. A second common decision point is one shared key versus one key per workload or data classification: a single customer managed key is simpler to audit but concentrates blast radius (a compromised principal with decrypt access can read everything protected by that key), while per-workload keys shrink blast radius at the cost of more policies to manage and, at very high request volumes, more KMS API calls that can approach service request-rate limits. Deleting a customer managed key is intentionally hard to reverse quickly, KMS enforces a waiting period before actual deletion, specifically because losing the key means losing every object it protects; that pending window is a safety net, not a formality to route around. Finally, using an asymmetric key for bulk data encryption is a real anti-pattern seen in the field, it's slower and not what asymmetric keys are designed for; reach for envelope encryption with a symmetric key instead.
Design a layered network security posture using Security Groups, NACLs, AWS WAF, AWS Shield, and Firewall Manager. Where does each control belong, and what are the common misconfigurations to avoid when centralizing enforcement across multiple accounts?
Sample Answer
A layered AWS network security posture applies controls at increasingly broad scopes: Security Groups filter traffic per resource, Network Access Control Lists (NACLs) add a coarse subnet-level backstop, AWS Web Application Firewall (WAF) filters application-layer requests at the edge, AWS Shield absorbs Distributed Denial of Service (DDoS) attacks, and AWS Firewall Manager centrally enforces all of the above across every account in an AWS Organization. No single control is sufficient alone: Security Groups stop most unwanted traffic, but WAF and Shield exist specifically because Security Groups cannot see inside a Hypertext Transfer Protocol (HTTP) request or absorb a flood, and Firewall Manager exists because per-account discipline stops scaling past a handful of accounts.
Where each control belongs
flowchart TB
Internet["Internet traffic"] --> Shield["AWS Shield Standard/Advanced\nedge DDoS absorption"]
Shield --> Edge["CloudFront / Application Load Balancer"]
Edge --> WAF["AWS WAF\napplication-layer filtering, rate-based rules"]
WAF --> NACL["Subnet NACL\nstateless, coarse allow/deny"]
NACL --> SG["Security Group\nstateful, per-resource least privilege"]
SG --> App["Application tier: EC2 / ECS / Lambda"]
App --> DBSG["Database-tier Security Group"]
DBSG --> DB["RDS / database"]
FM["AWS Firewall Manager"] -.enforces policy on.-> WAF
FM -.enforces policy on.-> Shield
FM -.enforces policy on.-> SG
Org["AWS Organizations + Service Control Policies"] -.governs.-> FM
Control-by-control role
- Security Groups (host/resource): a stateful firewall attached to Elastic Network Interfaces (ENIs), Amazon Elastic Compute Cloud (EC2) instances, and load balancers. Reference other security groups by ID instead of Classless Inter-Domain Routing (CIDR) ranges wherever possible, so a rule survives an IP address change.
- NACLs (subnet): stateless, evaluated in rule-number order, and applied to everything in the subnet. Use them as a blunt secondary backstop, for example blocking a known-bad CIDR range, rather than the primary control, since being stateless means you must explicitly allow the return traffic too.
- AWS WAF (application layer): sits in front of CloudFront or an Application Load Balancer and inspects the actual HTTP request. Use managed rule groups for common attack patterns plus rate-based rules to throttle a client hammering an endpoint. This layer also matters for serverless front doors: an API Gateway or Lambda function URL behind WAF gets the same rate-based throttling against a flood of malformed or maliciously injected events trying to drive up invocation cost, protection a Security Group cannot provide since Lambda has no traditional network ingress to filter.
- AWS Shield: Shield Standard is free and automatically protects every CloudFront distribution and Application Load Balancer against common network and transport-layer DDoS traffic. Shield Advanced adds continuous access to the DDoS Response Team, cost protection against scaling charges caused by an attack, and broader detection, worth the added cost for internet-facing production endpoints where downtime or an attack-driven bill spike is unacceptable.
- AWS Firewall Manager: centralizes WAF rule sets, Shield Advanced protections, security group policies, and DNS Firewall rules across every account in an AWS Organization from one security admin account, so a new account automatically inherits the baseline instead of relying on someone to configure it by hand.
Common misconfigurations
- Security Groups open to the entire internet on administrative or database ports, usually left over from initial setup and never tightened.
- Treating the NACL as the primary control: because NACLs are stateless, forgetting the ephemeral-port return-traffic rule silently breaks legitimate connections, and teams then "fix" it by opening the NACL wide, defeating its purpose.
- Applying WAF to the Application Load Balancer but exposing a second entry point, like a CloudFront distribution serving a static site or a direct storage-service website endpoint, that bypasses WAF entirely.
- Enabling Shield Advanced generally but not on the specific resources that need it, then discovering during an attack that the DDoS Response Team engagement and cost protection only apply to protected resources.
- Rolling out Firewall Manager policies without first mapping which accounts and organizational units are in scope, which either misses new accounts or breaks a legitimate account that needed an exception.
Worked example
A public checkout API sits behind CloudFront and an Application Load Balancer, backed by ECS tasks and an RDS database, across twenty AWS accounts in one Organization. Shield Standard covers CloudFront and the load balancer automatically. Shield Advanced is added because a DDoS-driven CloudFront bill spike during a past sale directly cost the business money. WAF sits on the CloudFront distribution with a managed rule group plus a rate-based rule capping any single IP address at a fixed request rate over a five-minute window. The load balancer's security group only allows inbound traffic from CloudFront's managed prefix list, not the open internet. The ECS task security group only allows inbound traffic from the load balancer's security group by reference, and the RDS security group only allows inbound traffic from the ECS task security group. Firewall Manager, run from the security account, pushes the same WAF rule set and Shield Advanced protection to every account tagged "production" in the Organization, so the twentieth account gets the same baseline as the first without a manual step.
Trade-offs and pitfalls
- Defense in depth adds real operational complexity: every layer is one more place a legitimate request can be blocked and one more thing to debug. Automate the rollout, through Firewall Manager, CloudFormation StackSets, or an infrastructure-as-code module, rather than hand-configuring each account, or the layers drift out of sync.
- WAF on CloudFront gives global, edge-level protection and lower origin latency; WAF on the Application Load Balancer is regional and sees traffic after it has already passed the content delivery network. Decide deliberately rather than bolting WAF onto whichever resource is convenient.
- Shield Advanced's cost protection only applies to resources it is actively protecting, so scoping it correctly matters as much as enabling it.
- Centralizing enforcement through Firewall Manager and Organizations Service Control Policies is powerful, but an overly broad policy can block legitimate exceptions, like a development account intentionally testing without WAF. Pair centralization with a documented, auditable exception process.
Unlock Full Question Bank
Get access to all 10 AWS Core Services and Architecture interview questions and detailed answers.
Sign in to ContinueJoin thousands of developers preparing for their dream job.