SaveMyCert
Log in
5 of 5 free questions left today·for 30 a day
Infrastructure Security

Edge Security on AWS: WAF, Shield, and CloudFront as Controls

26 min readSCS-C03 · Infrastructure SecurityUpdated

Edge security on AWS is a layered perimeter: AWS WAF filters HTTP requests with web ACLs, AWS Shield absorbs DDoS traffic, and CloudFront itself is a security control that hides and hardens your origins. Task 3.1 tests whether you can select the right edge protection for an anticipated threat — an OWASP Top 10 exploit, an L7 request flood, a volumetric L3/4 attack, a bot or scraper — implement it with the right building blocks, and troubleshoot the design when legitimate users get blocked or attackers slip through. This lesson works through WAF web ACLs and where they can attach, managed and Marketplace rule groups, rate-based rules and client fingerprinting (JA3/JA4), Bot Control, geography rules, count-mode tuning with WAF logs and labels, Shield Standard versus Shield Advanced and the Anti-DDoS managed rule group, origin cloaking with OAC, secret headers and CloudFront VPC origins, signed URLs and cookies, response headers policies and Amazon S3 CORS, API Gateway edge protections, AWS IoT Core policies, and feeding edge data into OCSF-based tools such as Amazon Security Lake.

What you’ll learn
  • Select the edge control that matches an anticipated threat — Shield for L3/4, WAF rate-based and managed rules for L7, Bot Control for automation — and know where each can be inserted.
  • Design AWS WAF web ACLs: attachment points and scope, priority order, managed (AWS and Marketplace) versus custom rules, scope-down statements, and labels.
  • Implement rate limiting, client fingerprinting (JA3/JA4), Bot Control and geography rules that stop abuse without blocking legitimate clients.
  • Tune WAF safely using Count mode, WAF logs (terminating rule and rule group fields) and per-rule overrides.
  • Choose between Shield Standard and Shield Advanced, and roll out Shield Advanced protections, cost protection, SRT access and Anti-DDoS rules at organization scale.
  • Lock origins to CloudFront with OAC, secret origin headers or VPC origins, and protect content with signed URLs or cookies.
  • Apply CloudFront response headers policies, Amazon S3 CORS, API Gateway throttling and mutual TLS, and least-privilege AWS IoT Core policies.
  • Integrate edge services with third-party WAF rules and OCSF-based tooling such as Amazon Security Lake.

Choosing the edge control for the anticipated threat

Pick an edge control by asking two questions: at which layer does the attack work, and where can a control be inserted in front of this workload? Network and transport layer floods (SYN floods, UDP reflection) never look like HTTP, so only AWS Shield and the scale of the AWS edge absorb them. Application layer threats arrive as valid-looking HTTP requests, so they need AWS WAF — and WAF can only sit on a supported resource.

Anticipated threatPrimary controlNotes
L3/4 volumetric (SYN flood, UDP reflection)Shield Standard (automatic) on the AWS edge; Shield Advanced for tuned detection, SRT and cost protectionNon-HTTP workloads (UDP game servers, custom TCP) cannot use CloudFront or WAF; Shield Advanced protects them through their Elastic IPs or Global Accelerator
L7 request floodWAF rate-based rules and the AWS WAF Anti-DDoS managed rule groupEach request looks legitimate; volume is the signal
Exploit payloads (SQL injection, XSS, LFI, known CVEs)AWS managed rule groups matched to the stack, plus custom rulesCovers much of the OWASP Top 10 at the edge
Bots and scrapersBot Control (Common or Targeted), CAPTCHA/Challenge, JA3/JA4 fingerprint rulesTargeted level and tokens need client integration
Credential stuffing, fake sign-upsRate-based rule scoped to the login path; account takeover prevention (ATP) and account creation fraud prevention (ACFP) managed groupsScope-down keeps the rest of the site unaffected
Direct-to-origin bypassOrigin cloaking: OAC for S3, VPC origins or prefix list + secret header for custom originsA web ACL on the distribution is worthless if the origin is reachable directly

When a workload has no WAF insertion point (for example it sits behind a Network Load Balancer or is an API Gateway HTTP API), the usual design move is to put CloudFront in front of it and attach a global web ACL to the distribution — that adds both the L7 inspection point and the DDoS-absorbing edge without changing the workload.

Where AWS WAF sits: web ACLs and attachment points

AWS WAF evaluates HTTP and HTTPS requests before they reach your application. The unit of deployment is the web ACL — an ordered collection of rules with a default action (Allow or Block) that applies when no rule matches. You associate a web ACL with a supported resource, including an Amazon CloudFront distribution, an Application Load Balancer, an Amazon API Gateway REST API stage, an AWS AppSync GraphQL API, an Amazon Cognito user pool, an AWS App Runner service, an AWS Verified Access instance, an Amazon Bedrock AgentCore gateway, or an AWS Amplify app. WAF does not associate with EC2 instances, Network Load Balancers, or API Gateway HTTP APIs — those need a supported resource, typically CloudFront, in front of them.

Scope matters and is a recurring trap. A web ACL for CloudFront (and Amplify) must be created with the CloudFront (global) scope in US East (N. Virginia); web ACLs for ALBs, API Gateway, AppSync, Cognito, App Runner and Verified Access are Regional and must live in the same Region as the resource. Scope is fixed by where the protected resource lives, not by where its traffic ends up: a Regional web ACL can never be attached to a distribution, and a global web ACL can never be attached to a Regional resource. So "the WAF rules exist but the resource is unprotected" often means the web ACL was built in the wrong scope or simply never associated.

Each rule consumes web ACL capacity units (WCUs), a complexity budget: managed rule groups publish their WCU cost, and a web ACL has a capacity ceiling — another reason to add only the rule groups that match your stack. Rules are evaluated in priority order (lowest number first), and the first terminating action ends evaluation: Allow and Block always terminate, and CAPTCHA/Challenge terminate when the request lacks a valid token. Count is non-terminating: the request is recorded as a match (and labelled), and evaluation continues. A rule's action applies regardless of whether it is custom or managed — a managed rule group does not outrank an earlier custom Allow. That ordering drives both tuning and troubleshooting later in this lesson.

Building the rule set: managed rule groups, custom rules, and scope-down statements

AWS Managed Rules are the fast path to OWASP Top 10 coverage, and they are organised by purpose so you add only what matches your application:

CategoryRule groupWhat it covers
BaselineCore rule set (CRS)General web exploits such as cross-site scripting, local and remote file inclusion, size restrictions. It does not contain SQL injection rules.
BaselineAdmin protectionRequests for exposed administrative pages
BaselineKnown bad inputsRequest patterns tied to known vulnerabilities, including the Log4j remote code execution patterns
Use caseSQL databaseSQL injection — the group to add for any SQL backend (MySQL, PostgreSQL, SQL Server, Aurora)
Use caseLinux operating systemLinux-specific exploits such as local file inclusion of Linux system files. AWS says to use it together with the POSIX group
Use casePOSIX operating systemExploits common to any POSIX-like OS (Linux included): Unix shell command injection, local file inclusion and path traversal
Use caseWindows operating systemWindows-specific exploits: Windows shell (cmd) and PowerShell command injection and remote command execution
Use casePHP applicationPHP-specific exploits such as unsafe function injection
Use caseWordPress applicationWordPress-specific exploits
IP reputationAmazon IP reputation list; Anonymous IP listKnown malicious sources; VPNs, Tor exit nodes, hosting providers

Choose groups from the stack in front of you: the operating system groups follow the servers' OS — Linux servers get the Linux and POSIX groups, other Unix-like servers get POSIX, and Windows servers get the Windows group, since each OS group covers command injection for its own shell family. The application groups follow the language or CMS, and the SQL database group follows the presence of a SQL backend — whatever the server OS. Bot Control, ATP and ACFP are separately priced intelligent threat mitigation groups, not exploit signatures. Managed rule groups are versioned (you can stay on the default version or pin a static one), and you can override the action of individual rules inside a group — typically to Count — without discarding the rest of the group.

Custom rules match on request components: URI path, query string, headers, cookies, body, HTTP method, source IP (via IP sets), country (geo match), ASN, JA3/JA4 fingerprint, labels, and regex pattern sets. String-match rules can apply text transformations such as lowercasing and URL decoding before matching, which defeats trivial evasion. Logical statements (AND, OR, NOT) combine conditions into precise rules — for example, block requests to /admin unless they arrive from the corporate IP set.

A scope-down statement narrows what a rule even considers. Inside a rate-based rule, only the matching subset of traffic is counted toward the limit — rate-limit only POST /login, not the whole site. Inside a managed rule group such as Bot Control, it restricts the (comparatively expensive) inspection to the paths that need it. A scope-down is evaluated before the group's rules, and requests it excludes skip every rule in the group — so it is not the tool for silencing one noisy rule; a per-rule override is.

Labels connect rules. Many rules — managed and custom — add labels to the requests they match (for example a Bot Control category label or a geolocation label), and a label match statement in a later rule can act on them. Two behaviours matter: a rule overridden to Count still adds its labels, and a label match statement only sees labels added by rules that were evaluated earlier — that is, rules with a lower priority number. The standard way to give a managed rule a custom action is therefore: override it to Count, then add a rule with a higher priority number than the rule group that matches its label and applies your action (Block, CAPTCHA, or a custom response).

Rate limiting and client fingerprinting: rate-based rules and JA3/JA4

A rate-based rule counters L7 request floods and brute-force patterns that content-matching rules cannot see, because each individual request looks legitimate. WAF counts requests per aggregation key over an evaluation window you choose (1, 2, 5 or 10 minutes) and applies the rule's action to keys that exceed your threshold, releasing them automatically when their rate falls back below it. A rate-based rule set to Count only records; to stop the abuse its action must be Block (or CAPTCHA/Challenge).

Aggregation keys decide what "one client" means:

  • Source IP (the default) — the address of the connection WAF sees. On a web ACL attached to CloudFront, that is already the viewer's address.
  • Forwarded IP — an address read from a header such as X-Forwarded-For. Use it only when the web ACL sits behind a trusted proxy — for example a Regional web ACL on an ALB that is itself behind CloudFront, where the ALB's source IPs are CloudFront's. On an internet-facing web ACL a client can write whatever it likes into that header, so keying on it lets an attacker rotate fake values and evade the limit.
  • Custom keys — up to five components such as a header, cookie, query argument, URI path, HTTP method, label namespace, ASN, or the JA3 or JA4 fingerprint, alone or combined with IP. A composite key counts each combination separately: JA4 + IP splits a bot that rotates IPs back into many small buckets, while JA4 alone groups every request from the same TLS client stack together.
  • Count all — no per-client grouping; one counter for every request that matches the scope-down, useful to cap total traffic to an expensive path.

Scope-down plus a low threshold is the precise tool. A single broad limit has to be set high enough for your busiest legitimate client, so it is blind to abuse spread thinly across many keys. A second rate-based rule with a scope-down statement counts only the requests that share some trait — a sensitive endpoint, a request method, a label from an earlier rule — and can therefore carry a far lower threshold without touching the rest of your traffic. Layering a broad rule with narrow, low-threshold ones is the general pattern.

Client fingerprinting. AWS WAF computes JA3 and JA4 fingerprints from each request's TLS Client Hello — a hash of how the client's TLS stack negotiates, which stays the same when a bot rotates IP addresses. Fingerprints are available for web ACLs on CloudFront and Application Load Balancers (where WAF sees the TLS handshake). You can match a fingerprint exactly in a string match statement, or aggregate a rate-based rule on it. A fingerprint identifies a TLS client stack, not a person: unrelated clients built on the same library or browser share it. Treat it as a strong signal to combine with other evidence (rate, path, labels) rather than as an identity, and prefer actions whose impact scales with behaviour over blanket blocks.

Bots: Bot Control, CAPTCHA, Challenge, and tokens

AWS WAF Bot Control is a managed rule group that classifies automated traffic and lets you allow, block, count, or challenge it by category. It has two inspection levels:

CommonTargeted
DetectsSelf-identifying bots — scraping frameworks, HTTP libraries, automated browsers, crawlers — using static request analysis; verifies good bots such as search engine crawlers so you can keep allowing themEverything in Common, plus sophisticated bots that do not identify themselves, using browser interrogation, fingerprinting and behavioural (including machine learning) analysis
Client integrationNoneIts token-based protections rely on clients acquiring AWS WAF tokens — through the challenge script or JavaScript SDK in browsers, or the mobile SDK in native apps
CostLower Bot Control feeHigher fee

CAPTCHA presents an interactive puzzle a human can solve; Challenge runs a silent browser interrogation that scripts without a real browser environment fail. Both issue an AWS WAF token with an immunity period, so verified clients are not repeatedly interrupted. They suit browser-facing endpoints where you want to slow abuse without cutting off real users — login, signup, search.

Tokens and non-browser clients. A native iOS or Android app, or any API client, cannot run the challenge script, so a CAPTCHA, Challenge or Targeted token check breaks it. The fix that keeps the protection on is the AWS WAF mobile SDK, which the app integrates to acquire and send tokens. The web ACL's token domain list only controls which domains accept a token the client already holds (for example across sibling subdomains); it cannot give a token to a client that never acquired one. For the same reason, CAPTCHA and Challenge are never a safe way to evaluate a new rule: they interrupt users and break non-browser traffic, whereas Count observes without touching anyone.

Geography and geolocation: CloudFront geo restriction vs WAF geo match

There are two places to enforce country rules at the edge, and they differ in granularity:

CloudFront geo restrictionAWS WAF geo match statement
ScopeThe whole distribution — not configurable per cache behavior or pathAny rule in the web ACL, combinable with other statements
LogicOne allow list or one block list of countries, with no exceptionsAND/OR/NOT with paths, IP sets, headers; country and region (subdivision) labels for later rules
Typical useLicensing or sanctions: serve only to approved countriesCountry plus path, country except a partner IP set, region-level rules

They compose: use geo restriction for the distribution-wide allow list, and a WAF rule such as geo match country X AND URI path starts with /regulated → Block for a path-specific restriction. An exception ("block this country except our partner's office") is a WAF rule — geo match AND NOT IP set → Block — because geo restriction has no exceptions. Route 53 geolocation routing chooses which endpoint answers a DNS query; it is routing, not an access control, because a client can still reach any endpoint directly.

Tuning without an outage: count mode, WAF logs, and false-positive triage

Deploying a strict rule set straight to Block on production traffic is how edge security causes its own incident. The professional pattern is count first: run new rules (or an entire managed rule group, via rule action overrides) in Count mode against real production traffic, watch the sampled requests and per-rule CloudWatch metrics, and flip to Block only after confirming the matches are genuinely malicious. Count is the only rule action that leaves every request's outcome unchanged while still recording and labelling matches, and production traffic is the only place a rule meets the real mix of clients it will judge.

Real triage runs on WAF logs, delivered to Amazon CloudWatch Logs, Amazon S3, or Amazon Data Firehose — they are the only log source that carries rule-level match detail for each request. Each log record includes the request metadata, the action, the terminating rule, any non-terminating (Count) matches, and the labels applied. Read the terminating fields carefully:

  • terminatingRuleId names the rule in the web ACL that ended evaluation. If that was a custom rule, it is the rule itself.
  • If a rule inside a rule group decided, terminatingRuleId holds the rule group, and the specific rule is in ruleGroupList[].terminatingRule.ruleId.

The false-positive workflow follows from that: filter the logs for the affected requests with action BLOCK, find the deciding rule, and if it lives in a managed group override that one rule to Count — keeping every other rule in the group active on those requests. A higher-priority Allow for the path or a scope-down that excludes it would also stop the false positive, but they exempt those requests from every rule in the group. Note that WAF inspects only a limited portion of the request body and you configure oversize handling for larger payloads — inspection limits are a legitimate reason a payload rule fails to match, and size rules such as the Core rule set's body-size rule are a common source of false positives on uploads.

Two habits keep tuning honest: never assume a rule protects you while it is still in Count, and re-check priorities after every change — an early terminating Allow silently bypasses everything below it.

DDoS layers: Shield Standard vs Shield Advanced

DDoS defense on AWS starts with architecture. CloudFront, Route 53 and Global Accelerator are massively distributed edge services: volumetric L3/4 attacks are spread across the global edge and absorbed far from your origin, which is why "put CloudFront in front of it" is itself a DDoS answer. On top of that sit two Shield tiers:

CapabilityShield StandardShield Advanced
Cost and enrollmentAutomatic and free for every AWS customerPaid subscription with a one-year commitment; each resource must be added as a protection
ProtectionAlways-on mitigation of common network and transport layer (L3/4) attacksEnhanced L3/4 mitigations; L7 protection through AWS WAF on the protected resource
Protected resource typesAll AWS resources implicitlyCloudFront distributions, Route 53 hosted zones, Global Accelerator accelerators, ALBs, Classic Load Balancers, and Elastic IP addresses (the way to protect EC2 instances and NLBs)
DetectionBaseline network flow monitoringDetection tuned to each resource's traffic baseline, and health-based detection using Route 53 health checks
ResponseAutomatic mitigation onlyShield Response Team (SRT) access and optional proactive engagement — both require a Business or Enterprise Support plan
Cost protectionNoneCredits for scaling charges (data transfer, Auto Scaling, Route 53 queries and similar) caused by a DDoS attack on protected resources

Coverage follows the protection list. Protecting a distribution does not protect its ALB origin — cost protection and tuned detection apply only to resources you add as protections, so a distribution and its origin each need one. An NLB is not a protected resource type; you protect its Elastic IPs. Protection groups only aggregate resources that are already protected (so detection and mitigation treat them as one), they do not add protection.

SRT and proactive engagement. With proactive engagement the SRT contacts you when an event it detects is affecting your application; it needs the support plan, proactive engagement contacts, and a Route 53 health check associated with each protection. Proactive engagement is not triggered by events that the AWS WAF Anti-DDoS managed rule group detects.

L7 floods: the Anti-DDoS managed rule group. Since 26 March 2026 the AWS WAF Anti-DDoS managed rule group is AWS's default protection against HTTP request floods, added to a web ACL like any managed group. It supersedes Shield Advanced automatic application layer DDoS mitigation, which is now a legacy feature: existing users can keep it, but new Shield Advanced customers must ask AWS Support for it.

At organization scale, an AWS Firewall Manager Shield Advanced policy applies protections across member accounts, including resources created later. It needs auto remediation turned on to add the protections and associate an empty web ACL with in-scope resources that lack one — with auto remediation off it only reports non-compliant resources. Firewall Manager is the organization-wide mechanism for continuously applying Shield Advanced protections (and WAF rules) to existing and newly created resources in every in-scope account.

CloudFront as a security control: cloaking, TLS, and private content

CloudFront is not just a cache — it is the layer that lets you hide your origins entirely. For S3 origins, origin access control (OAC) is the current mechanism (successor to the legacy origin access identity): CloudFront signs origin requests with SigV4, and the bucket policy allows the cloudfront.amazonaws.com service principal only with an AWS:SourceArn condition naming your distribution. Without that condition, any distribution — including one in another account — could read the bucket. The bucket keeps Block Public Access on; only your distribution can read it. For custom origins such as ALBs, see the origin-locking scenario below.

CloudFront also enforces encryption in transit at both hops. The viewer protocol policy forces HTTPS from clients (redirect or require); the security policy sets the minimum TLS version and ciphers viewers may negotiate; the origin protocol policy should be HTTPS-only so the edge-to-origin hop is encrypted too. Certificate details and ACM live in Domain 5 — here, know which knob enforces which hop.

Private content: signed URLs vs signed cookies. Both grant time-limited access and are verified against public keys in a trusted key group. A signed URL carries the signature in the query string of each URL, so it suits one object or a download link. Signed cookies are sent with every request to the domain without changing any URL, so they suit many objects — a subscriber area, or streaming formats such as HLS and DASH, where a manifest references hundreds of segments by relative path and those segment requests would not carry the manifest's signed query string. Each uses a policy:

Canned policyCustom policy
ResourceOne exact object URLCan use wildcards (for example a whole title's path)
ConditionsExpiry time onlyStart and end date-time, and optionally a viewer IP range
FitsA single file for a limited timeMany files, a validity window, or IP-bound access

OAC and signed URLs/cookies solve different problems and are often used together: OAC keeps the bucket private behind the distribution; signed URLs or cookies decide which viewers the distribution serves. Two further edge features: field-level encryption encrypts specific sensitive POST fields at the edge with a public key so only the component holding the private key can decrypt them, and Route 53 DNSSEC signs your DNS zone so resolvers can detect spoofed responses directing users away from your edge.

CloudFront headers and Amazon S3 CORS

CloudFront has four header-related policies and settings, and each acts on a different hop:

SettingActs onSecurity use
Response headers policyResponses CloudFront sends to viewersAdd security headers, CORS headers, custom headers; remove headers
Origin custom headersRequests CloudFront sends to the originSecret header that proves a request came through your distribution
Origin request policyWhich viewer headers, cookies and query strings are forwarded to the origin (without affecting the cache key)Forward what the origin needs to decide, such as Origin
Cache policyThe cache key (values in it are also forwarded)Make the cache vary on a header so one viewer's response is not served to another

Response headers policies are the way to add browser security headers without touching the origin or its objects: the security headers section covers Strict-Transport-Security, Content-Security-Policy, X-Content-Type-Options, X-Frame-Options, X-XSS-Protection and Referrer-Policy, and AWS publishes a managed SecurityHeadersPolicy. Each header has an origin override setting. When the origin does not send the header, CloudFront adds the policy's value either way. When the origin does send it, override on replaces it with the policy's value, and override off lets the origin's header pass through. A response header set in an origin request policy or origin custom header never reaches the viewer — those act on the request to the origin.

Amazon S3 CORS is a bucket configuration of rules — AllowedOrigins, AllowedMethods, AllowedHeaders, ExposeHeaders, MaxAgeSeconds — that tells browsers which other origins' scripts may read responses (S3 answers with Access-Control-Allow-Origin and related headers, and handles preflight OPTIONS requests). CORS is not access control. It is enforced by the browser on scripts running in a web page; curl, server-side code or any non-browser client ignores it, and S3 still serves every request its bucket policy, ACLs and Block Public Access allow. To stop downloads you restrict access (bucket policy, OAC, signed URLs), not CORS.

CORS through CloudFront. S3 returns CORS headers only when the request carries an Origin header, and the allowed-origin value it returns is specific to that origin. So the Origin header must reach S3 and the cache must vary on it — put Origin in the cache policy (which also forwards it). The managed CORS-S3Origin origin request policy forwards Origin on cache misses but does not add it to the cache key, so the first cached response — with one site's allow-origin header, or none — is served to every site. The alternative is to have CloudFront itself answer with CORS headers through the CORS section of a response headers policy, which moves the allowed-origin list from the bucket to CloudFront.

Scenario: locking an ALB origin so it only accepts CloudFront traffic

The requirement reads: "The origin must only accept traffic that has passed through CloudFront and AWS WAF; requests sent directly to the ALB must be rejected." There are two designs: keep the ALB internet-facing and cloak it in two layers, or remove its public endpoint with a VPC origin.

Layer 1 — network path. Edit the ALB's security group to allow HTTPS only from the AWS-managed prefix list for CloudFront origin-facing servers (com.amazonaws.global.cloudfront.origin-facing), and remove the 0.0.0.0/0 ingress rule. The prefix list is maintained by AWS, so you never chase changing edge IP ranges. But this is insufficient alone: those edge IPs serve every CloudFront customer, so an attacker can create their own distribution pointing at your ALB and arrive from an allowed address — bypassing your web ACL entirely.

Layer 2 — origin authentication. Configure your distribution to add a custom origin header — for example X-Origin-Verify with a long random value stored in Secrets Manager. On the ALB listener, a rule forwards to the target group only when that header matches, and the listener's default action returns a fixed 403. Rotate the secret periodically by updating the distribution and listener rule. Now only your distribution's traffic is honored, and since your web ACL is attached to that distribution, nothing reaches the origin unfiltered.

The alternative: CloudFront VPC origins. Since November 2024, CloudFront can use an internal ALB, an internal NLB, or an EC2 instance in a private subnet as a VPC origin. The origin has no public IP or internet-facing listener at all, so there is no direct path to bypass and no shared secret to rotate; the web ACL on the distribution becomes the only way in. Choose VPC origins for new designs where the origin can be private; use the prefix list plus secret header when the origin must stay internet-facing.

Verification and pitfalls. Request the ALB DNS name directly — expect a rejection; request via the distribution — expect success. If requests appear in the ALB access logs but never in the distribution's WAF logs, the origin is being bypassed: look for a lingering 0.0.0.0/0 rule, or a listener whose default action forwards instead of rejecting. The origin's identity can also leak through DNS history or certificate transparency logs, so treat cloaking as enforcement by the security group and listener, not as secrecy.

API Gateway at the edge, WAF vs Network Firewall, and the troubleshooting playbook

API Gateway brings its own edge protections. Throttling applies token-bucket rate and burst limits at three levels: the account limit per Region (shared by every API in the account there), stage defaults, and method-level overrides in the stage settings — so capping one expensive method uses a method-level limit, not the account limit. Usage plans add per-client throttling and quotas (per day, week or month): you create a plan per tier, and associate each customer's API key with the plan for that customer's tier. An API key enforces nothing until it is associated with a usage plan, usage-plan throttles and quotas are applied on a best-effort basis (not a hard billing or security limit), and API keys identify and meter clients — they are not authentication. Resource policies restrict who can invoke the API by source IP, VPC or VPC endpoint, or AWS account. REST API stages accept a Regional WAF web ACL; HTTP APIs do not.

Mutual TLS makes callers present an X.509 certificate chained to a truststore you upload to Amazon S3. It is configured on a Regional custom domain name using the TLS_1_2 security policy, is not supported for private APIs, and applies only to that domain — so you must disable the default execute-api endpoint, or callers simply bypass it. Do not confuse it with a stage client certificate: that certificate is presented by API Gateway to your backend so the backend can verify that calls come from API Gateway; it does not authenticate callers.

WAF versus Network Firewall is a layering question, not a rivalry. AWS WAF is L7-only, inspecting HTTP(S) at supported edge and Regional resources. AWS Network Firewall (Task 3.3) is a stateful, managed firewall deployed in VPC subnets with Suricata-compatible rules and domain-based egress filtering for all traffic, not just web requests. Use WAF for inbound web exploits and floods; use Network Firewall for VPC ingress/egress inspection and non-HTTP protocols.

The troubleshooting playbook. Legitimate traffic blocked: WAF logs → the terminating rule (and ruleGroupList for a rule inside a group) → override that rule to Count or add a narrowly prioritized exception; check priority order for an early terminating rule. Attacks getting through: confirm the web ACL is associated and in the correct scope, the rule isn't still in Count, rate thresholds aren't above the attack's per-key rate (add a scoped-down rule or a better aggregation key), and body inspection limits aren't hiding the payload. Origin directly reachable: look for an open security group rule, a missing prefix-list restriction, a listener default action that forwards, an enabled execute-api endpoint, or a leaked origin address.

AWS IoT Core policies: least privilege at the device edge

AWS IoT Core policies are JSON policies attached to a device's X.509 certificate (or other principal) that authorize MQTT actions. Least privilege depends on using the right resource type for each action:

ActionResource typeChecked against
iot:Connectclient/<clientId>The MQTT client ID used to connect
iot:Publishtopic/<topic>The topic of each published message
iot:Subscribetopicfilter/<filter>The topic filter the client asks to subscribe to
iot:Receivetopic/<topic>The topic of each message delivered to the client

Subscribing and receiving are authorized separately: a policy that puts iot:Subscribe on a topic/ resource never authorizes any subscription, because subscriptions are evaluated against topicfilter/ resources. In policy resources, * is the policy wildcard, while the MQTT wildcards # and + are treated literally — so topicfilter/cmd/device1/# authorizes exactly the filter cmd/device1/#.

One policy for every device comes from thing policy variables — IoT-specific variables populated from the device's connection, certificate and registry entry. ${iot:Connection.Thing.ThingName} resolves to the name of the registered thing behind the connection (when the client ID equals the thing name, or when the certificate is attached exclusively to one thing), so a single policy can let each device connect only as itself and publish or subscribe only under topics that contain its own name. Wildcard resources such as topicfilter/cmd/* or topic/sensors/*/telemetry break that isolation — every device could read or write every other device's topics.

Integrations: third-party WAF rules and OCSF data in Security Lake

Third-party (AWS Marketplace) managed rule groups plug into a web ACL exactly like AWS managed groups, after you subscribe in AWS Marketplace. Their rules are hidden — you cannot view or copy their logic — but you can still override individual rule actions (or the whole group) to Count. The seller owns the rules, their versioning and support, so a false positive is handled by overriding the rule to Count and asking the seller (not AWS Support) to tune it. Subscriptions are per account: to deploy one through an AWS Firewall Manager AWS WAF policy, every account in the policy scope must subscribe. Charges continue until the group is removed from every web ACL and Firewall Manager policy and the subscription is cancelled.

OCSF integration. The Open Cybersecurity Schema Framework (OCSF) is an open schema for security events, and Amazon Security Lake is AWS's OCSF data lake (the new AWS Security Hub also represents findings in OCSF, while Security Hub CSPM uses ASFF). Edge data arrives in two ways:

  • Native AWS sources — AWS WAFv2 logs are a natively supported Security Lake source, alongside CloudTrail, VPC Flow Logs, Route 53 Resolver query logs, Security Hub CSPM findings and EKS audit logs. Security Lake collects them across the organization and converts them to OCSF in Apache Parquet itself — no transformation code.
  • Custom sources — third-party data, such as events from another vendor's CDN or WAF, must arrive already converted to OCSF as Apache Parquet, written under the prefix Security Lake assigns to the source and partitioned by region, accountId and eventDay, with one OCSF event class per custom source. Security Lake does not convert raw vendor JSON; it creates the writer IAM role, the Lake Formation table and a Glue crawler for the source.

Once the data is in Security Lake, subscribers — Athena queries, or third-party SIEM and analytics tools — read edge, network and API activity in one schema.

Tip. Task 3.1 questions are threat-to-control matching under constraints. Expect to choose controls by layer (Shield for L3/4, WAF for L7) and by insertion point (which resources take a web ACL, in which scope, and CloudFront in front of those that cannot); to pick managed rule groups from an application stack; to read rule priority, Count, labels and WAF log fields when traffic is wrongly blocked or wrongly allowed; and to design rate-based rules with the right aggregation key and scope-down. Shield Advanced items turn on what is actually protected, support-plan prerequisites, health checks and organization-wide rollout, with automatic L7 mitigation now legacy. CloudFront items cover origin cloaking (OAC, VPC origins, prefix list plus secret header), signed URL versus cookie and canned versus custom policies, geo restriction versus WAF geo match, response headers policies and CORS caching. Also in scope: API Gateway throttling, usage plans and mutual TLS, IoT Core policy resource types and variables, Marketplace rule groups, and OCSF ingestion into Security Lake.

Key takeaways
  • Match the control to the layer: Shield for L3/4 floods, WAF rate-based rules and the Anti-DDoS managed rule group for L7 floods, managed rule groups for exploits, Bot Control for automation — and put CloudFront in front of anything WAF cannot attach to.
  • Web ACLs attach to CloudFront and Amplify (global scope, us-east-1) and to Regional ALBs, API Gateway REST APIs, AppSync, Cognito, App Runner and Verified Access — never to NLBs, EC2 or HTTP APIs.
  • Rules run in ascending priority and the first terminating action ends evaluation; Count is non-terminating but still adds labels, which only later rules can match.
  • Pick managed groups by stack: the Core rule set has no SQL injection rules (add SQL database), Log4j patterns are in Known bad inputs, and OS and application groups follow the servers and frameworks.
  • On a CloudFront web ACL the source IP is the viewer; key rate-based rules on a forwarded IP only behind a trusted proxy, and use scope-downs and custom keys such as JA3/JA4 for distributed or IP-rotating floods.
  • Count is the safe evaluation mode; triage false positives from WAF logs (terminatingRuleId, plus ruleGroupList for rules inside a group) and override the one rule to Count.
  • Shield Advanced covers only resources added as protections (NLBs through their Elastic IPs); SRT and proactive engagement need Business or Enterprise Support; Firewall Manager with auto remediation protects new resources org-wide; L7 auto-mitigation is now legacy.
  • Lock origins with OAC plus an AWS:SourceArn condition for S3, VPC origins for private ALB/NLB/EC2, or the origin-facing prefix list plus a listener-verified secret header for internet-facing ALBs.
  • Response headers policies add security headers for viewers (origin override decides who wins); S3 CORS is browser-enforced, not access control, and needs Origin in the CloudFront cache key.
  • IoT policies use client/ for Connect, topic/ for Publish and Receive, topicfilter/ for Subscribe, scoped by ${iot:Connection.Thing.ThingName}; WAFv2 logs are a native Security Lake source, third-party data must already be OCSF Parquet.

Frequently asked questions

What is the difference between AWS WAF, Shield Standard, and Shield Advanced?

AWS WAF filters individual HTTP(S) requests using web ACL rules you configure — it counters exploits, request floods, and bots at layer 7. Shield Standard is free, automatic protection against common network and transport layer (L3/4) DDoS attacks for all AWS customers. Shield Advanced is a paid subscription for resources you add as protections: enhanced and tuned detection and mitigation, DDoS cost protection, health-based detection, and Shield Response Team access (with a Business or Enterprise Support plan). For HTTP floods, AWS now recommends the AWS WAF Anti-DDoS managed rule group, which superseded Shield Advanced automatic application layer mitigation in March 2026.

How do I make my ALB only accept traffic from CloudFront?

If the ALB can be internal, use a CloudFront VPC origin: the ALB sits in a private subnet with no public endpoint, so CloudFront is the only way in. If it must stay internet-facing, use two controls together: restrict the ALB security group to the AWS-managed CloudFront origin-facing prefix list, and have your distribution add a secret custom header that an ALB listener rule requires before forwarding, with the listener's default action returning 403. The header is essential because the prefix list admits every CloudFront customer's distribution.

How do I find which WAF rule is blocking legitimate users?

Enable AWS WAF logging to CloudWatch Logs, S3, or Data Firehose and filter for the affected requests with action BLOCK. The terminatingRuleId field names the web ACL rule that ended evaluation; when the deciding rule is inside a rule group, terminatingRuleId holds the group and ruleGroupList[].terminatingRule.ruleId names the rule. Override just that rule's action to Count rather than removing the whole group or exempting the path from it.

Should a rate-based rule behind CloudFront aggregate on the forwarded IP?

Not when the web ACL is attached to the CloudFront distribution: there the source IP is already the viewer's address, and X-Forwarded-For is a header the client can forge. Forwarded-IP aggregation is for a web ACL that sits behind a trusted proxy, such as a Regional web ACL on an ALB that only receives traffic from CloudFront. For floods that rotate IP addresses, aggregate on a custom key such as the JA3 or JA4 fingerprint, and use a scope-down statement to count only the suspect traffic.

Can AWS WAF protect a Network Load Balancer, EC2 instance or API Gateway HTTP API directly?

No. AWS WAF associates with HTTP-layer resources, including CloudFront distributions, Application Load Balancers, API Gateway REST API stages, AppSync GraphQL APIs, Cognito user pools, App Runner services, Verified Access instances, Bedrock AgentCore gateways and Amplify apps. To inspect traffic to an NLB, an EC2 instance or an HTTP API, put a CloudFront distribution in front of it and attach a global web ACL (created in us-east-1) to the distribution. Non-HTTP workloads rely on Shield instead, with Shield Advanced protecting their Elastic IPs.

What is the difference between CloudFront signed URLs and signed cookies?

Both grant time-limited access to private content and are verified against a trusted key group. A signed URL carries the signature in each URL, so it suits a single file or download link. Signed cookies cover many files without changing any URL, so they suit subscriber areas and HLS or DASH streaming, where segment requests do not carry the manifest URL's signature. A canned policy covers one exact resource with an expiry; a custom policy can use wildcards, a start and end time, and an IP range.

Does an S3 CORS configuration stop other sites from downloading my files?

No. CORS only tells browsers whether a web page from another origin may let its scripts read a response. Tools such as curl, server-side code and other non-browser clients ignore it, and Amazon S3 still serves any request its bucket policy, ACLs and Block Public Access allow. To restrict who can download objects, use access controls such as a bucket policy, CloudFront origin access control, or signed URLs and cookies.

How do I get AWS WAF and third-party WAF logs into Amazon Security Lake?

AWS WAFv2 logs are a natively supported Security Lake source: enable the source and Security Lake collects and converts them to OCSF in Apache Parquet, with no code. A third-party CDN or WAF is added as a custom source, and its events must already be converted to OCSF Parquet, written under the prefix Security Lake assigns, partitioned by region, accountId and eventDay, with one OCSF event class per custom source.

Source

This lesson covers the "Infrastructure Security" domain of the official SCS-C03 exam guide. Vendors revise their guides — check the source for the current version.

Test yourself on this topic
Practice now

Sign up free to mark lessons complete, bookmark topics and track your exam readiness.

Spotted a mistake in this lesson?