SaveMyCert
Log in
5 of 5 free questions left today·for 30 a day
Design Secure Architectures

Securing Workloads: VPC Design, Security Groups vs NACLs, WAF and Shield

30 min readSAA-C03 · Design Secure ArchitecturesUpdated

Designing secure workloads on AWS means controlling who and what can reach each part of an application: which subnets can talk to the internet, which traffic each filter admits, how services are reached privately, which managed service answers each threat, and where credentials live. Task 1.2 covers exactly that — VPCs with public, private, and isolated subnet tiers; security groups, network ACLs, route tables, and NAT gateways; VPC endpoints and PrivateLink; keeping origins private behind CloudFront and filtering egress with AWS Network Firewall; the application security services (Cognito, IAM Identity Center, GuardDuty, Macie, Shield, WAF); Secrets Manager and Parameter Store; and encrypted external connections over VPN and Direct Connect. It sits in Design Secure Architectures, the heaviest SAA-C03 domain, and its scenarios name a threat or an exposure — a database reachable from the internet, a DDoS attack, SQL injection, a load balancer attackers reach around CloudFront, access keys hard-coded in an application — and ask for the design that closes it under a stated constraint. By the end of this lesson you will be able to lay out a three-tier secure VPC from scratch, trace any packet through its route tables and filters, and map any named threat to the service that mitigates it.

What you’ll learn
  • Design a three-tier VPC with public, private, and isolated subnets, choosing zonal or regional NAT gateways and an egress-only internet gateway for IPv6
  • Choose between security groups and network ACLs, write NACL rules that account for statelessness and ephemeral ports, and reference security groups by ID between tiers
  • Distinguish gateway endpoints, interface endpoints, and PrivateLink endpoint services, and lock them down with endpoint policies, private DNS, and aws:SourceVpce
  • Keep origins private behind CloudFront (VPC origins, origin access control) and filter egress by domain with AWS Network Firewall
  • Match threats — DDoS, SQL injection, credential stuffing, compromised instances, exposed sensitive data — to Shield, WAF, GuardDuty, or Macie and configure the right feature
  • Choose between Cognito user pools, identity pools, and IAM Identity Center, and between Secrets Manager, Parameter Store, and AppConfig
  • Design encrypted external connectivity with Site-to-Site VPN, VPN over Direct Connect, and MACsec

Segment the VPC: public, private, and isolated subnet tiers

A subnet's route table decides how exposed it is, so network segmentation on AWS is designed through subnets and their routes. A subnet is not inherently public or private — its routes make it one. A public subnet has a route to an internet gateway, so resources with public IPs in it are reachable from the internet. A private subnet has no internet gateway route; its outbound internet traffic goes to a NAT gateway, which gives instances outbound access — for patches, package downloads, external APIs — while keeping them unreachable from outside, because NAT admits only replies to connections started from inside. An isolated subnet takes the last step: no internet gateway route and no NAT route, so nothing in it can reach or be reached from the internet — the right home for databases that only talk to the application tier.

The design rule the exam rewards is minimal exposure: only components that must accept traffic from the internet belong in public subnets — internet-facing load balancers, zonal NAT gateways, and little else. Application servers sit behind the load balancer in private subnets; data stores sit in isolated subnets. When a scenario mentions "EC2 instances with public IP addresses running the application tier" or "an RDS database in a public subnet," that placement is the flaw.

Zonal vs regional NAT gateways

The classic pattern — and the one most exam items still describe — is the zonal NAT gateway: it lives in one Availability Zone, is created in a public subnet (whose route table points 0.0.0.0/0 at the internet gateway), and each private subnet routes 0.0.0.0/0 to the NAT gateway in its own AZ. For high availability you run one zonal NAT gateway per AZ; a single shared NAT gateway is a single point of failure, and losing its AZ cuts outbound access for every other zone. Since November 2025 a NAT gateway can also be created in regional availability mode: you pick the VPC rather than a subnet, it needs no public subnet, it expands into every AZ where your workloads have network interfaces (and contracts when they leave), and all private subnets can route 0.0.0.0/0 to the one regional NAT gateway ID. The VPC still needs an internet gateway attached; AWS creates the regional NAT gateway's own route table with the route to it. Regional mode is the answer when a policy forbids public subnets or wants AZ-level resilience without per-AZ plumbing; zonal mode is still required for private NAT (translating between private networks), which regional NAT gateways do not support.

NeedComponentRoute in the workload subnet
Outbound-only IPv4, classic designZonal NAT gateway in a public subnet, one per AZ0.0.0.0/0 → NAT gateway in the same AZ
Outbound-only IPv4, no public subnets allowedRegional NAT gateway (VPC still has an internet gateway)0.0.0.0/0 → regional NAT gateway ID
Outbound-only IPv6Egress-only internet gateway::/0 → egress-only internet gateway
Inbound and outbound (public)Internet gateway0.0.0.0/0 and/or ::/0 → internet gateway

IPv6 changes the egress story. IPv6 addresses on AWS are globally unique and publicly routable, so there is no NAT for IPv6-to-IPv6 traffic. Outbound-only IPv6 uses an egress-only internet gateway (a ::/0 route to it), which is stateful in the same way NAT is: replies come back, unsolicited inbound connections do not. Routing ::/0 to the ordinary internet gateway instead exposes every instance's IPv6 address to inbound connections. A NAT gateway's only IPv6 role is NAT64 — letting IPv6-only workloads reach IPv4 destinations (with DNS64). A dual-stack private subnet therefore needs both routes: 0.0.0.0/0 to a NAT gateway and ::/0 to an egress-only internet gateway.

Placement details the exam checks

  • Internet-facing load balancers are mapped to public subnets — one in each AZ where targets run — even though the targets stay private. If an internet-facing load balancer is mapped to private subnets, health checks (which originate inside the VPC) still pass, but internet clients time out because the load balancer's nodes have no route back to the internet. The fix is to change its subnet mappings to public subnets in the same AZs, not to move the instances.
  • A database placed in the application tier's private subnets inherits their NAT route. "No route to the internet at all" requires separate isolated subnets whose route table holds only the local route (plus any gateway endpoints).
  • RDS needs no internet path for patching. AWS applies operating-system patches and minor engine versions (with auto minor version upgrade on) to RDS inside the managed service during the maintenance window — major version upgrades are started by you, but also run inside the service — so the data tier never needs a NAT route or public access for patches. RDS DB instances are not Systems Manager managed nodes, so Patch Manager does not patch them either; only self-managed databases on EC2 need a patch path (NAT, a proxy, or a local repository).

Expect this as placement and reachability logic: which subnet each tier belongs in, why a resource can or cannot be reached, and which single route change exposes or protects a tier. If you can classify any subnet from its routes alone, these questions become fast points.

Security groups vs network ACLs: the stateful/stateless split

Security groups are stateful, allow-only filters on each network interface; network ACLs are stateless, ordered allow-and-deny filters on each subnet — and telling them apart is among the most reliably tested facts on SAA-C03. A security group attaches to a resource's elastic network interface — an EC2 instance, an RDS database, a load balancer — and is stateful: if inbound traffic is allowed, the response is automatically allowed out. Security groups contain allow rules only; anything not allowed is denied, and there is no way to write an explicit deny. All rules are evaluated together, with no ordering. Network Load Balancers have supported security groups since 2023, but those are the same allow-only groups — they cannot carve one malicious range out of an internet-facing listener either.

A network ACL attaches to a subnet and filters traffic entering or leaving it. It supports both allow and deny rules, evaluated in rule-number order with the first match winning, so a low-numbered deny for a CIDR range blocks it before the broader allows are reached. That deny capability defines its role: a NACL is the network-level tool when you must explicitly block an IP address or range, because neither security groups nor routes can (a route chooses where traffic to a destination goes; it cannot drop inbound packets by source).

Stateless means writing both directions

A NACL evaluates each packet on its own, matching the packet's destination port. For a client connecting to a server on 443, the request arrives at destination port 443 — but the server's reply leaves with the client's ephemeral port as its destination. So a subnet serving HTTPS needs inbound 443 and an outbound allow for TCP 1024–65535 to the clients; an outbound rule for port 443 does nothing for replies. The symptom of a missing return rule is connections that start and then hang, while the security groups (stateful) were never the problem. Direction matters for denies too: a deny written only in the outbound rules still lets the attacker's packets in — to stop inbound traffic, the deny belongs in the inbound rules.

The same logic applies when private instances call out through a NAT gateway. The request leaves the private subnet to destination port 443; the reply comes back into the private subnet from the remote server's address to the instance's ephemeral port — the NAT gateway rewrites only the destination back to the instance, not the source. The private subnet's inbound NACL therefore needs TCP 1024–65535 from the remote range (often 0.0.0.0/0), not from the NAT gateway's private IP or the VPC CIDR.

When the deny list is long

NACLs have a rule quota — 20 inbound and 20 outbound rules by default, adjustable up to 40 per direction — and every extra rule is evaluated per packet. A threat feed of hundreds of CIDR ranges in front of an HTTP application does not fit. The scalable alternative is an AWS WAF IP set match rule on the Application Load Balancer or CloudFront distribution: one rule references an IP set holding thousands of ranges, which you update (for example weekly from the feed) without touching the network. WAF cannot attach to a Network Load Balancer, so for NLB-fronted or non-HTTP services the NACL remains the deny tool.

Reference security groups, not addresses

The design technique the exam loves is referencing security groups by ID. Instead of allowing the application subnet's CIDR into the database security group, allow the database port from the application tier's security group. Membership becomes dynamic: any instance carrying the app-tier group can reach the database, and nothing else can — including unrelated workloads sharing the same subnets, which a CIDR rule would admit. Chained tier to tier (ALB SG → app SG on the app port, app SG → DB SG on the database port), this builds least-privilege networking that survives Auto Scaling.

Across VPCs the reference has limits. Over a same-Region VPC peering connection you can reference a peer VPC's security group (prefix it with the account ID, account-id/sg-id, when the peer is in another account). Over inter-Region peering you cannot — the rule must use the peer's CIDR blocks. Security group referencing through a transit gateway is likewise supported only within one Region.

Decision rules: filtering for a specific resource, or allowing by relationship between tiers — security group. Explicitly denying a handful of IPs at the subnet boundary — network ACL. Denying hundreds of ranges in front of HTTP — WAF IP set. Traffic arrives but replies never return — a stateless NACL missing its ephemeral-port rule.

VPC endpoints: keep service traffic off the internet

VPC endpoints let resources in a VPC reach AWS services privately over the AWS network, without an internet gateway, a NAT gateway, or public IP addresses. Scenarios that say "traffic to Amazon S3 must not traverse the public internet" or "instances must reach DynamoDB without a NAT gateway" are endpoint questions before you finish reading them.

There are two kinds, and the split is a standing exam decision. A gateway endpoint is a route-table target: you add it to the subnet's route table and traffic to the service follows that route. Gateway endpoints exist for exactly two services — Amazon S3 and DynamoDB — and carry no charge. An interface endpoint (AWS PrivateLink) is an elastic network interface with a private IP in your subnet, protected by a security group; it supports most other AWS services (and S3), and bills per hour and per GB processed. Interface endpoints are not route-table targets — traffic reaches them through DNS.

The decision rule: for S3 and DynamoDB from inside the VPC, use the gateway endpoint — free and purpose-built, so a cost-qualified question makes the S3 interface endpoint a deliberate distractor. Interface endpoints earn their keep everywhere else — SQS, Secrets Manager, Systems Manager, KMS, API Gateway — and where a gateway endpoint cannot reach, such as S3 from on premises over VPN or Direct Connect, since gateway endpoints only serve their own VPC's route tables. A gateway endpoint also cannot be used across a VPC peering connection, which is part of a wider rule: VPC peering does not support edge-to-edge routing. A peered VPC cannot use its peer's internet gateway, NAT gateway, VPN connection, or gateway endpoint, so isolated subnets that need AWS services get their own interface endpoints rather than a route through a "shared NAT" VPC over peering.

Private DNS: no code changes

With private DNS enabled on an interface endpoint, the service's default regional hostname (for example the standard SQS endpoint the SDK uses) resolves to the endpoint's private IPs inside the VPC, so applications move to the endpoint without any code or configuration change. Private DNS requires the VPC attributes enableDnsSupport and enableDnsHostnames to be true. If either is off, or private DNS is disabled, the default hostname still resolves to public IPs and the traffic keeps flowing through the NAT gateway — a common "we created the endpoint but nothing changed" scenario.

Locking endpoints down against data exfiltration

Endpoints carry endpoint policies — resource-style policies that limit what can be done through them. An S3 gateway endpoint policy that allows actions only on the company's bucket ARNs stops instances from copying data to an attacker's bucket through the endpoint. Pair it with bucket policies that deny requests whose aws:SourceVpce is not your endpoint ID (or aws:SourceVpc not your VPC), and the data is reachable only from inside the VPC, to approved buckets. Do not try this with aws:SourceIp: requests that arrive through a VPC endpoint do not carry the instance's private address in aws:SourceIp — the private address is in aws:VpcSourceIp — so a private-CIDR SourceIp condition never matches.

PrivateLink for your own services, and private APIs

PrivateLink also works provider-side. A VPC endpoint service placed in front of a Network Load Balancer (or a Gateway Load Balancer for appliances) exposes one service to consumers, each of whom creates an interface endpoint in their own VPC. Traffic stays on the AWS network, only that one service is exposed (not the provider's whole VPC), the provider can require acceptance of each connection, and overlapping CIDR ranges do not matter — which rules out VPC peering and transit gateways when hundreds of customers reuse the provider's address space.

For Amazon API Gateway, a private REST API is reachable only through an execute-api interface endpoint and must have a resource policy, typically allowing execute-api:Invoke only when aws:SourceVpce (or aws:SourceVpc) matches. There is no gateway endpoint for API Gateway. A Regional (public) API called from private subnets arrives from the NAT gateway's public IP, so a resource policy keyed to the VPC CIDR never matches — making the API private is the fix when it must be callable from one VPC and nowhere else.

The three-tier secure VPC: a reference architecture walkthrough

The default secure architecture on SAA-C03 is a web application across two Availability Zones with web, application, and database tiers in separate subnet tiers — six subnets in total. Assemble it from the pieces above.

Public subnets (tier 1) hold the internet-facing Application Load Balancer and, in the classic design, one zonal NAT gateway per AZ (with a regional NAT gateway, the public subnets hold only the load balancer). The ALB's security group allows inbound 443 from 0.0.0.0/0 — it is the single designed entry point for user traffic. The route table sends 0.0.0.0/0 to the internet gateway.

Private subnets (tier 2) hold the application instances in an Auto Scaling group. Their security group allows inbound only from the ALB's security group on the application port — referenced by ID, so scaling events change nothing. Instances have no public IPs; their route table sends 0.0.0.0/0 to the NAT gateway in their own AZ (or to the regional NAT gateway), giving outbound access for patches and external APIs while remaining unreachable from the internet. Calls to S3 and DynamoDB flow through free gateway endpoints instead of the NAT path.

Isolated subnets (tier 3) hold the RDS database (Multi-AZ). The DB security group allows inbound only from the application tier's security group on the database port. The route table has no internet gateway or NAT route: the database cannot initiate or receive internet traffic, and RDS still receives its patches in the maintenance window. NACLs stay at their defaults unless a requirement demands an explicit deny — the security-group chain is the working control.

Administrative access without exposure

The classic bastion host — a public instance with port 22 open and SSH keys distributed — is exposed infrastructure that must itself be patched, monitored, and key-managed. The modern answer is AWS Systems Manager Session Manager: the SSM Agent on each instance connects outbound to the service, so administrators open shells through IAM-authenticated, logged sessions (to S3 or CloudWatch Logs) with no inbound ports, no bastion, and no SSH keys. It needs an instance profile whose role includes AmazonSSMManagedInstanceCore, and an outbound path to Systems Manager. In isolated subnets with no NAT or proxy, that path is interface endpoints for ssm, ssmmessages, and ec2messages, with a security group allowing HTTPS from the instances.

EC2 Instance Connect Endpoint is the other no-bastion option: it lets administrators reach instances that have no public IP over SSH or RDP, authorized by IAM, without an internet gateway or bastion. Unlike Session Manager, it is still SSH — the instance's security group must allow inbound port 22 from the endpoint (and the user authenticates with a key, which EC2 Instance Connect can push as a short-lived one). When the requirement says no inbound rules at all, no SSH keys, and logged sessions, Session Manager is the only fit; hardening a bastion is the distractor.

Protecting origins and filtering egress: CloudFront VPC origins, OAC, and Network Firewall

Edge protections only work if attackers cannot go around them, so the origin behind CloudFront must accept traffic only from CloudFront, and outbound traffic from private subnets should be limited to approved destinations.

Private origins behind CloudFront

CloudFront VPC origins (since November 2024) let a distribution use an internal Application Load Balancer, Network Load Balancer, or EC2 instance in a private subnet as its origin. The origin needs no public IP and no internet-facing load balancer; you allow inbound traffic from the CloudFront-managed VPC origins security group, and the VPC must have an internet gateway attached even though the origin's subnets do not route to it. This closes the classic bypass where attackers discover an internet-facing ALB's DNS name and send requests to it directly, skipping the WAF web ACL on the distribution. An internal ALB cannot simply be added as a custom origin: its DNS name resolves to private IPs that CloudFront's edge cannot reach. Custom origins must be publicly reachable; private origins need a VPC origin. (The older workaround — keeping the ALB internet-facing and requiring a secret custom header that CloudFront adds — still appears in exam items, but it leaves the load balancer publicly addressable.)

For S3 origins, use origin access control (OAC): CloudFront signs its requests to the bucket's REST API endpoint, and the bucket policy allows s3:GetObject to the cloudfront.amazonaws.com service principal only when AWS:SourceArn equals the distribution's ARN. Block Public Access stays on, and direct S3 URLs stop working. OAC does not work with the S3 static website endpoint, which CloudFront treats as a custom origin. IP-based grants are not a substitute: bucket policies cannot reference a managed prefix list, and CloudFront's IP ranges are shared by every distribution, so an IP allow would admit other customers' distributions too.

Egress filtering with AWS Network Firewall

Security groups and NACLs filter by IP address and port; they cannot express "HTTPS to these 40 domain names and nowhere else." AWS Network Firewall is a managed, stateful network firewall deployed as endpoints in dedicated firewall subnets, with stateful domain list rule groups (matching the TLS SNI or HTTP Host), Suricata-compatible rules, and intrusion prevention. Traffic is inspected only if routing sends it through the firewall endpoints, and the routing must be symmetric. With a NAT gateway, a common layout is: workload subnets route 0.0.0.0/0 to the NAT gateway; the NAT gateway's subnet routes 0.0.0.0/0 to the firewall endpoint; the firewall subnet routes 0.0.0.0/0 to the internet gateway; and an edge route table associated with the internet gateway sends the NAT subnet's CIDR back to the firewall endpoint, so replies are inspected on the way in as well. Across many VPCs the same firewall can be centralized in an inspection VPC behind a transit gateway.

Application identity: Cognito user pools vs identity pools

When the users in a scenario are customers of an application rather than employees, the identity service is Amazon Cognito; when they are the company's own workforce, it is IAM Identity Center. Cognito itself has two components with confusable names, and distinguishing them is a recurring exam point.

A user pool is a user directory that handles authentication: sign-up with email or username and password, sign-in, password policies, MFA, and account recovery, plus social and enterprise sign-in through external identity providers such as Google, Apple, or a SAML/OIDC IdP. After sign-in it issues JSON Web Tokens that the application presents to prove identity; API Gateway authorizers validate them directly. A user pool has no unauthenticated access — every user in it signs in.

An identity pool handles authorization to AWS itself: it exchanges an identity token — from a user pool, a social provider directly, or a SAML/OIDC IdP — for temporary AWS credentials under an IAM role, letting the app call AWS services directly. Identity pools also support unauthenticated (guest) identities with a deliberately narrow role — guest access is always an identity-pool feature. What an identity pool cannot do is be a user directory: it offers no email/password sign-up, so a requirement for app accounts with passwords needs a user pool.

The compressed rule: user pool = who are you (sign-up, sign-in, JWTs); identity pool = what can you touch in AWS (temporary credentials, IAM roles, guests). Real architectures chain them — the user pool authenticates, the identity pool trades the token for credentials so the mobile app can upload to S3 without embedded access keys.

Requirement phrasings map cleanly: "add sign-up and sign-in to a web or mobile app" or "issue tokens our API validates" points to a user pool; "the app must call S3 or DynamoDB directly" or "let guest users browse before signing in" points to an identity pool. Shipping long-term IAM access keys inside a mobile or browser app is always the anti-pattern — anyone who unpacks the app gets them; identity pools exist to replace them with short-lived, scoped credentials.

Adding sign-in without changing the application

An Application Load Balancer can authenticate users before requests reach the targets. An HTTPS listener rule with an authenticate-cognito action (backed by a user pool, which can enforce MFA) or an authenticate-oidc action (any OIDC provider) signs the user in, then forwards the request with the user's claims in headers. This is the answer when a vendor or legacy application's code cannot change but must sit behind sign-in.

Customers vs workforce in one design

IAM Identity Center is the workforce side: employees sign in once — with Identity Center's own directory, Active Directory, or an external IdP such as Okta or Microsoft Entra ID — to an access portal that lists both their AWS accounts (through permission sets) and SAML 2.0 business applications such as Salesforce. Many applications need both: shoppers sign up through a Cognito user pool that issues the tokens the app's APIs validate, while support staff use their corporate Okta credentials through Identity Center to reach the AWS accounts. Cognito is the wrong tool for employees' AWS console access, and Identity Center is the wrong tool for public customer sign-up. Workforce access to AWS accounts in depth — permission sets, multi-account roles — is taught in the Task 1.1 lesson on IAM and Organizations.

Threat vectors and the mitigation map: Shield, WAF, GuardDuty, Macie

Each external threat maps to the service that operates at its layer: Shield for network-layer DDoS, WAF for malicious web requests, GuardDuty for active threats in the account, Macie for exposed sensitive data. A large share of Task 1.2 questions name a threat and ask which service answers it.

DDoS splits by OSI layer. AWS Shield Standard defends against common network and transport layer (layer 3/4) attacks — SYN floods, UDP reflection — automatically and at no cost for every AWS customer. AWS Shield Advanced is the paid tier: protections tuned to each protected resource, near-real-time visibility, 24/7 access to the Shield Response Team, cost protection against scaling charges incurred during an attack, and automatic application layer (layer 7) mitigation. AWS WAF operates at layer 7: a web application firewall associated with HTTP-facing resources — CloudFront, Application Load Balancers, API Gateway REST APIs, AppSync, Cognito user pools, App Runner, Amplify, and Verified Access — filtering requests with managed and custom rules for SQL injection, cross-site scripting, IP reputation, geography, and request rate. WAF cannot be associated with a Network Load Balancer. "SQL injection" or "filter malicious web requests" means WAF; Shield does not inspect payloads, and WAF does not stop SYN floods.

Detection services split by what they watch. Amazon GuardDuty is threat detection for accounts and workloads: it continuously analyzes CloudTrail events, VPC Flow Logs, and DNS query logs (plus optional protection plans for S3, EKS, runtime, RDS, and more) for signals like cryptocurrency mining, credential exfiltration, or traffic to known command-and-control hosts — with nothing to install. Amazon Macie watches data, not behaviour: it discovers and classifies sensitive data in S3 — PII, credentials, financial records — and flags buckets that are public, shared, or unencrypted. "Detect compromised instances or anomalous account activity" is GuardDuty; "identify where PII is stored in S3" is Macie. Amazon Inspector, a frequent distractor, scans for software vulnerabilities rather than active threats.

Threat / requirementServiceWhy
Network/transport DDoS (SYN flood, UDP reflection)Shield Standard (automatic) / Shield Advanced (response team, cost protection)Layer 3/4 mitigation at the AWS edge
HTTP floods against a web appShield Advanced automatic L7 mitigation + WAF rate-based rulesLayer 7 request-pattern rules
SQL injection, XSS, bot/rate abuse against a web appAWS WAF on CloudFront, ALB, or API GatewayLayer 7 request inspection and rules
Compromised instance, unusual API activity, crypto-miningAmazon GuardDutyThreat detection over CloudTrail, flow logs, DNS logs
Sensitive data (PII) exposed in S3Amazon MacieSensitive-data discovery and classification
Block a few malicious IP ranges at the subnetNetwork ACL deny ruleSecurity groups cannot express deny
Block hundreds of ranges in front of HTTPWAF IP set match ruleScales past the NACL rule quota
Credentials hard-coded in application codeIAM roles + Secrets Manager / Parameter StoreEliminate long-lived secrets from code
Database reachable from the internetIsolated subnet + SG referencing the app tierSegmentation removes the exposure

Exam answers follow this table almost mechanically — the traps are cross-layer swaps: WAF offered for a layer 3 flood or attached to an NLB, GuardDuty offered for finding PII, Macie offered for detecting intrusions. Match the layer and the watched surface, and the distractors eliminate themselves.

WAF and Shield in practice: rule types, protected resources, and Firewall Manager

Choosing WAF or Shield is half the answer; the other half is the feature that meets the stated constraint — a scoped rate limit, a country block with an exception, a protected resource type, or central management across accounts.

AWS WAF rules that come up

  • AWS managed rule groups give tested protection without writing signatures: the core rule set covers common web exploits including cross-site scripting, and the SQL database rule group covers SQL injection patterns. Others cover known bad inputs, IP reputation, and bots.
  • Rate-based rules count requests per client IP (or other key) over a time window and block those above the limit. A scope-down statement limits what is counted — for example only POST requests to /login — so a credential-stuffing campaign that hammers one path is blocked while normal browsing from the same addresses is untouched. Because the rule keys on behaviour, it keeps working when the attacking IPs change daily, which a static IP list does not.
  • IP set match rules reference a list of up to thousands of CIDR ranges you update in place — the scalable deny list.
  • Logical statements: WAF rule statements combine with AND, OR, and NOT. "Block these three countries except the partner's addresses" is a geo match statement AND NOT an IP set match. CloudFront's built-in geographic restrictions only allow or block whole countries, with no exceptions, and need a distribution — WAF on the ALB is the answer when there is no CloudFront or when an exception is required.

Shield Advanced: what it protects and when it acts

Shield Advanced protects specific resource types: CloudFront distributions, Route 53 hosted zones, Global Accelerator accelerators, Application and Classic Load Balancers, and Elastic IP addresses (which covers EC2 instances and Network Load Balancers addressed through them). A UDP game server reached directly through Elastic IPs gets tuned DDoS protection, the response team, and cost protection by adding its Elastic IPs as protected resources — WAF and CloudFront do not apply to raw UDP.

Automatic application layer DDoS mitigation requires the protected CloudFront distribution or ALB to have a WAF web ACL. When Shield Advanced detects an HTTP flood — request volume deviating sharply from the resource's learned baseline — it creates and places WAF rules that match the attack's request signatures, in count or block mode. It does not inspect payloads (SQL injection is still the SQL database managed rule group's job), and it does not fire for a targeted, low-volume attack that keeps total traffic at normal levels, such as credential stuffing on one path — a scoped rate-based rule is the control there.

AWS Firewall Manager

AWS Firewall Manager centrally defines and enforces security policies across the accounts of an AWS Organization: WAF web ACLs, Shield Advanced protections, security groups, Network Firewall, and DNS Firewall policies, applied automatically to existing and new accounts and resources. It is a policy-management layer — it provides no DDoS response team or cost protection of its own (those come from Shield Advanced) — and it is the answer when the requirement is "every ALB in every account must have this WAF rule set, including future ones."

Detection at scale: GuardDuty across accounts and Macie discovery

GuardDuty and Macie only help if they run everywhere and someone acts on their findings, so Task 1.2 questions also test how to roll them out across an organization and wire them to a response.

GuardDuty: organization-wide and automated

In AWS Organizations, the management account designates a GuardDuty delegated administrator (typically a security tooling account). That account can turn on auto-enable for all member accounts — existing and newly created — and sees and manages every member's findings in one place. Security Hub CSPM can aggregate GuardDuty findings alongside other sources, but it does not enable GuardDuty in accounts. GuardDuty itself detects; it does not block. To respond automatically, GuardDuty publishes findings to Amazon EventBridge, where a rule matching the finding type invokes a Lambda function or a Systems Manager Automation runbook — for example to swap a compromised instance's security groups for a quarantine group that allows nothing. Suppression rules do the opposite of responding: they automatically archive findings that match criteria you consider expected noise, and take no action on resources.

Macie: automated discovery vs jobs

Automated sensitive data discovery gives continuous, cost-controlled visibility across a large estate: Macie samples objects from your buckets daily, including new buckets, and maintains a sensitivity score for each bucket so you can see where sensitive data is likely to be. Sensitive data discovery jobs — one-time or scheduled — perform full or targeted scans of chosen buckets when you need every object analyzed. Macie's managed data identifiers recognize common types (names, credit card numbers, credentials). For an organization-specific format, create a custom data identifier: a regular expression, optionally with keywords that must appear near the match and words to ignore. An allow list is the inverse — it names text or patterns Macie should not report, such as public sample data — so it cannot make Macie detect anything new.

Credential security: Secrets Manager vs Parameter Store, and no keys in code

Application credentials must never live in code, configuration files committed to repositories, or AMIs: compute uses IAM roles for AWS access, and everything else is fetched at runtime from Secrets Manager or Parameter Store. For AWS API access, compute gets IAM roles — instance profiles, Lambda execution roles, ECS task roles — so there are no access keys to store. For database passwords, third-party API keys, and certificates, the application retrieves the secret at runtime, over an interface endpoint if it runs in a private subnet.

AWS Secrets Manager is purpose-built for secrets. Its defining feature is automatic rotation: managed rotation for secrets that RDS, Aurora, and Redshift create and manage for you (such as an RDS master-user password), managed external secrets for onboarded SaaS partners, and a Lambda rotation function for everything else — AWS supplies rotation function templates for databases such as RDS engines and DocumentDB, and you write a custom function for other services. Secrets are KMS-encrypted, retrieval is IAM-controlled and logged in CloudTrail, and it is priced per secret per month plus per API call.

The classic shape: a database password hard-coded in application source is fixed by moving it into Secrets Manager with rotation turned on, and granting the instance role (or Lambda execution role) permission to read that one secret — the code then fetches the current value at runtime and never holds a long-lived copy.

Rotation strategies

  • Single-user rotation changes the password of one database user. The old password stops working immediately, so clients that cached it fail to open new connections until they refresh the secret.
  • Alternating-users rotation keeps two users and switches the secret between them, so the previous credentials remain valid for one more rotation period — cached clients keep working. The rotation function needs permission to change the other user's password, so it uses a separate secret holding admin (superuser) credentials.

Sharing secrets across accounts and Regions

To let a role in another account read a secret, two things are needed: a resource-based policy on the secret allowing that role secretsmanager:GetSecretValue, and a customer managed KMS key whose key policy grants the role kms:Decrypt. The default aws/secretsmanager key's policy cannot be edited, so a secret encrypted with it cannot be read from another account — re-encrypt it with a customer managed key. Secret replication copies a secret to other Regions within the same account (for multi-Region applications and recovery); it is not a cross-account sharing mechanism.

Parameter Store and AppConfig

AWS Systems Manager Parameter Store is a general configuration store that also holds secrets as KMS-encrypted SecureString parameters. Standard parameters have no storage charge, which makes Parameter Store the cost-effective answer for configuration values — endpoints, AMI IDs, feature settings, even hundreds of them — and for static secrets that do not need managed rotation — it has no native rotation. Parameters form hierarchies such as /dev/, /test/, and /prod/, and IAM policies can grant access to a path ARN (for example parameter/prod/*), so production functions read only production values and development roles cannot read production at all.

AWS AppConfig (also part of Systems Manager) is for configuration that changes at runtime and must be rolled out safely — feature flags and operational settings with validators, gradual deployment strategies, and automatic rollback on alarms. It complements rather than replaces a secret store: credentials still belong in Secrets Manager or SecureString parameters.

The decision rule: automatic rotation or cross-account secret sharing selects Secrets Manager; cost-effective storage of configuration or static secrets selects Parameter Store; safe, gradual rollout of changing configuration selects AppConfig. A subtle trap inverts the qualifier: choosing Secrets Manager "because it is more secure" when the requirement was cost and no rotation was demanded — both stores encrypt with KMS and gate access with IAM; the differentiators are rotation, cross-account sharing, and price.

Securing external connections: Site-to-Site VPN and Direct Connect

On-premises networks connect to a VPC securely through AWS Site-to-Site VPN (encrypted IPsec over the internet), AWS Direct Connect (a private dedicated link), or a combination of the two. AWS Site-to-Site VPN establishes IPsec-encrypted tunnels over the internet between your customer gateway device and a virtual private gateway or transit gateway. It is quick to set up — often the same day — inexpensive, and encrypted by construction, but it rides the internet, so bandwidth and latency vary. Each connection has two tunnels for redundancy. A standard tunnel carries up to about 1.25 Gbps; large bandwidth tunnels (up to 5 Gbps per tunnel) also exist on transit gateway and Cloud WAN attachments (not on a virtual private gateway), and ECMP across tunnels on a transit gateway adds aggregate bandwidth — but a single flow stays on one tunnel.

AWS Direct Connect is a dedicated private connection from your network into AWS. It bypasses the internet, delivering consistent latency and high bandwidth — the choice for large steady transfers and predictable performance. It takes weeks to provision, not days. The security nuance the exam checks: a Direct Connect connection is private, but your traffic on it is not encrypted by default. AWS encrypts data at the physical layer as it travels between Direct Connect locations and AWS Regions, but that does not cover the segment between your router (or your partner's) and the Direct Connect location, and it is not encryption you control.

When traffic between the data center and AWS must be encrypted in transit, there are two designs:

OptionLayerFits whenLimits
Site-to-Site VPN over Direct ConnectIP (IPsec), end to end between your gateway and AWSEncryption at the IP layer is required, or the connection is a hosted connectionPer-tunnel throughput caps; a single multi-gigabit stream does not fit
MACsec on the Direct Connect connectionLayer 2, between your router and the AWS Direct Connect deviceDedicated 10, 100, or 400 Gbps connections needing line-rate encryptionNot available on hosted connections; needs a MACsec-capable router and a CKN/CAK key pair configured on both ends

VPN also serves as a failover path for a Direct Connect link when connectivity must survive the dedicated line failing — cheaper than a second Direct Connect connection, at reduced performance during failover.

Read these questions on three axes: performance (Direct Connect), encryption (IPsec VPN or MACsec), and lead time and cost (VPN). A branch office needing encryption within a week at low cost resolves to plain Site-to-Site VPN; high-bandwidth private connectivity to Direct Connect; encryption over Direct Connect to VPN over Direct Connect, or MACsec when the streams are multi-gigabit on a dedicated connection. Options claiming Direct Connect "is encrypted because it is private" are the designated trap.

Worked scenarios: reasoning through Task 1.2 questions

Scenario 1. A company runs a self-managed PostgreSQL database on an EC2 instance. The instance sits in a public subnet with an Elastic IP, and its security group allows inbound 5432 from the office CIDR and from the application servers' current private IP addresses. Auditors want the database unreachable from the internet, and the operations team needs it to keep receiving OS patches. What design addresses both?

Reasoning: Separate the reachability problem from the patching problem. Reachability: move the instance into a private subnet, release the Elastic IP, and replace the IP-based rules with an inbound rule allowing 5432 from the application tier's security group by ID — the rule then follows the instances through scaling and replacement instead of breaking when IPs change; administrators reach it through SSM Session Manager or a VPN rather than a public address. Patching: unlike RDS, a database on EC2 is your operating system to patch, so the subnet needs an outbound path — a NAT gateway route for the package repositories (or VPC endpoints for Systems Manager when Patch Manager uses a local repository). Answers that only narrow the CIDR or add a NACL leave the instance internet-addressable; answers that move it to an isolated subnet with no egress at all break patching.

Scenario 2. A public-facing application behind an Application Load Balancer is being disrupted by two simultaneous problems: volumetric floods at the network layer, and requests containing SQL injection attempts reaching the application. The company also wants 24/7 access to AWS DDoS experts during attacks and protection against Auto Scaling costs incurred while absorbing one. Which combination addresses all requirements?

Reasoning: Decompose by layer. The volumetric layer 3/4 floods are Shield's territory — and the two extra requirements, a response team and cost protection, are the exact differentiators of Shield Advanced over the free Standard tier. SQL injection is a layer 7 payload problem no amount of Shield addresses: it needs AWS WAF attached to the ALB (or a CloudFront distribution in front of it) with SQL-injection managed rules, plus a rate-based rule for abusive clients. The correct combination is Shield Advanced + WAF; single-service options fail one layer each, and GuardDuty in an option is a detector, not a blocker — it would report the attack, not stop it.

Scenario 3. Instances in a private subnet process confidential objects from S3. Compliance requires that this traffic never traverse the public internet, and finance wants the NAT gateway data-processing charges gone. The team also SSHes to these instances through a bastion host the auditors have flagged. What changes satisfy everyone?

Reasoning: S3 from inside a VPC with "no internet" and "lower cost" in the same sentence is the signature of a gateway VPC endpoint — free, private, added to the subnet's route table; an interface endpoint would work but fails the cost qualifier, and the S3 traffic stops flowing through the NAT gateway entirely. For the auditors, replace the bastion with SSM Session Manager: IAM-authenticated, logged sessions with no inbound ports and no keys — with an interface endpoint for Systems Manager if the subnet must stay fully offline. The pattern to internalize: each named constraint (no internet, cost, audited access) maps to one specific mechanism, and the correct option is the one that hits all three without adding exposed infrastructure.

Tip. SAA-C03 probes this task by naming an exposure or a threat and demanding the design that closes it under a stated constraint: a database in a public subnet or in the app tier's NAT-routed subnets (move it to an isolated subnet, reference security groups by ID), a policy forbidding public subnets (regional NAT gateway) or outbound-only IPv6 (egress-only internet gateway), S3 traffic that must avoid the internet and cost (gateway endpoint with endpoint and bucket policies), an endpoint that changes nothing (private DNS), attackers reaching an ALB or bucket around CloudFront (VPC origin, origin access control), SQL injection, credential stuffing, or DDoS (WAF managed and scoped rate-based rules vs Shield Advanced), and hard-coded credentials (roles plus Secrets Manager or Parameter Store, split by rotation and cost). Classic shapes include the NACL connectivity mystery (missing ephemeral-port rule, often on the return path through NAT), the hybrid link requiring encryption (VPN over Direct Connect, or MACsec on a dedicated link), and admin access with no inbound ports (Session Manager with its endpoints). Traps are near-twins: WAF on an NLB, a security group deny, an outbound-only NACL deny, an internal ALB as a custom origin, an identity pool for password sign-up, GuardDuty for finding PII. Match the layer, the watched surface, and the constraint, and one option remains.

Key takeaways
  • A route table defines the subnet: internet gateway route = public, NAT route = private, neither = isolated; only internet-facing load balancers and zonal NAT gateways belong in public subnets.
  • Zonal NAT gateways sit in a public subnet, one per AZ; a regional NAT gateway needs no public subnet and spans AZs; outbound-only IPv6 uses an egress-only internet gateway.
  • Security groups are stateful and allow-only (NLB groups too); NACLs are stateless, ordered allow/deny, and need ephemeral-port return rules — and long deny lists in front of HTTP belong in a WAF IP set.
  • Reference security groups by ID between tiers; across inter-Region peering, use the peer CIDR instead.
  • Gateway endpoints (S3, DynamoDB) are free route-table entries; interface endpoints need private DNS (plus VPC DNS attributes) to be transparent; endpoint policies plus aws:SourceVpce stop exfiltration.
  • Keep origins private: CloudFront VPC origins for internal ALBs/instances, OAC with the S3 REST endpoint; AWS Network Firewall filters egress by domain name with symmetric routing.
  • Shield = layer 3/4 DDoS (Advanced adds response team, cost protection, L7 auto-mitigation with a web ACL); WAF = layer 7 on CloudFront/ALB/API Gateway, never an NLB — use scoped rate-based rules and AND/NOT logic.
  • GuardDuty detects (delegated admin + auto-enable, EventBridge for response); Macie finds sensitive S3 data (automated discovery, custom data identifiers).
  • Cognito user pool = app sign-up/sign-in and JWTs (no guests); identity pool = temporary AWS credentials and guest access; IAM Identity Center = workforce accounts and SaaS apps.
  • Secrets Manager for rotation (alternating users for zero-downtime) and cross-account access (customer managed KMS key); Parameter Store for cheap config with path-scoped IAM; Direct Connect is private but not customer-encrypted — add VPN over it or MACsec.

Frequently asked questions

What is the difference between a security group and a network ACL?

A security group attaches to a resource (an instance, database, or load balancer network interface) and is stateful: allowed inbound traffic gets its response out automatically, and it supports allow rules only. A network ACL attaches to a subnet and is stateless: each direction needs its own rule, so replies to clients need an outbound allow for ephemeral ports 1024-65535, and it supports both allow and deny rules evaluated in numbered order. Use security groups as the primary per-resource control and for tier-to-tier references by group ID; use a NACL when you must explicitly deny a few IP ranges at the subnet boundary. For hundreds of ranges in front of a web application, use an AWS WAF IP set instead.

When should I use a gateway VPC endpoint vs an interface endpoint?

Use a gateway endpoint for Amazon S3 and DynamoDB access from inside the VPC: those are the only two services it supports, it works as a route-table entry, and it is free. Use an interface endpoint (AWS PrivateLink) for private access to most other AWS services, such as SQS, KMS, Secrets Manager, and Systems Manager, or to reach S3 privately from on premises over Direct Connect or VPN, which a gateway endpoint cannot serve. Interface endpoints bill hourly plus per GB, and with private DNS enabled (and the VPC DNS attributes on) applications use them without code changes.

What is the difference between AWS Shield and AWS WAF?

They defend different layers. AWS Shield mitigates DDoS attacks at the network and transport layers, such as SYN floods and UDP reflection. Shield Standard is automatic and free; Shield Advanced adds tuned protection for specific resources, 24/7 access to the Shield Response Team, cost protection, and automatic layer 7 DDoS mitigation when the resource has a WAF web ACL. AWS WAF is a web application firewall that inspects HTTP(S) requests on CloudFront, an Application Load Balancer, API Gateway, AppSync, and similar HTTP-facing resources, blocking SQL injection, cross-site scripting, bad IPs, and abusive request rates. WAF cannot be attached to a Network Load Balancer. A public web app typically uses both.

What is the difference between Cognito user pools and identity pools?

A user pool is a user directory that authenticates people into your application, with sign-up, sign-in, MFA, and social or SAML/OIDC login, and issues JSON Web Tokens the app uses for sessions and API authorization; it has no unauthenticated access. An identity pool authorizes access to AWS itself: it exchanges an identity token for temporary AWS credentials under an IAM role, and it can give limited credentials to unauthenticated guest users, but it cannot provide email/password sign-up. Shorthand: the user pool answers "who are you" for the app; the identity pool answers "what AWS resources can you touch," such as letting a mobile app upload to S3.

Should I use Secrets Manager or Parameter Store for secrets?

Choose AWS Secrets Manager when the requirement includes automatic rotation (managed rotation for secrets that RDS, Aurora, or Redshift manage, or a Lambda rotation function — from an AWS template for databases such as DocumentDB, or custom — for other secrets) or cross-account access through a resource policy plus a customer managed KMS key. It charges per secret and per API call. Choose Systems Manager Parameter Store for cost-effective storage of configuration values or static secrets: SecureString parameters are KMS-encrypted and IAM-controlled, standard parameters have no storage charge, and path hierarchies such as /prod/ let IAM scope access per environment, but there is no built-in rotation.

Is AWS Direct Connect encrypted?

Not by default in a way you control. Direct Connect is a dedicated private connection, so traffic bypasses the internet, and AWS encrypts data at the physical layer between Direct Connect locations and AWS Regions. That does not cover the link between your router and the Direct Connect location. When traffic must be encrypted in transit, either run an IPsec Site-to-Site VPN over the Direct Connect connection, or enable MACsec (layer 2 encryption between your router and the AWS device) on a dedicated 10, 100, or 400 Gbps connection. MACsec suits multi-gigabit streams that exceed a VPN tunnel; it is not available on hosted connections.

What is the most secure way to SSH into EC2 instances in a private subnet?

Use AWS Systems Manager Session Manager. The SSM Agent on the instance connects outbound to Systems Manager, so administrators open shell sessions authenticated by IAM and logged to S3 or CloudWatch Logs with no bastion host, no inbound ports, and no SSH keys. The instance needs a role with AmazonSSMManagedInstanceCore, and subnets with no internet path need interface endpoints for ssm, ssmmessages, and ec2messages. EC2 Instance Connect Endpoint also avoids a bastion and public IPs, but it is still SSH and needs inbound port 22 from the endpoint.

How do I stop users from bypassing CloudFront and reaching my origin directly?

Make the origin reachable only from CloudFront. For an Application Load Balancer, Network Load Balancer, or EC2 instance, use a CloudFront VPC origin so the origin can be internal in a private subnet with no public address, and allow inbound traffic only from the CloudFront VPC origins security group. For an S3 bucket, use origin access control with the bucket REST endpoint and a bucket policy that allows the cloudfront.amazonaws.com principal only when AWS:SourceArn is your distribution, keeping Block Public Access on. Then the WAF rules on the distribution cannot be bypassed.

Source

This lesson covers the "Design Secure Architectures" domain of the official SAA-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?