AWS SAA-C03: How to Design Secure Workloads and Applications

1. Secure design mindset for AWS SAA-C03

For SAA-C03, “design secure workloads and applications” is basically a pattern game. You spot the shape, pick the answer that trims credential risk, keeps things off the public internet, leans on AWS-managed controls when they fit, and pulls governance into one place. Small catch, though: the exam is allergic to absolutes. Managed and low-ops is often the move. Not a law of nature.

When you untangle a security question, try five lenses: identity, network, data protection, edge protection, and monitoring/governance. If two choices both seem fine, nudge toward temporary credentials, private connectivity, encryption in transit and at rest, and the option that won’t wake you up at 2 a.m.

2. Shared responsibility model and core principles

The shared responsibility model shifts depending on the service. On EC2, you’re carrying more of the backpack: guest OS, patching, instance security, some network controls. With more abstracted services like S3 or Lambda, AWS takes on more of the plumbing. Still, you own your identities, your data, your access setup, and the way the workload is designed. No escape hatch there.

Good exam instincts: least privilege, defense in depth, separation of duties, account isolation. And “zero trust”? Treat it as a broad security idea, not a magic AWS buzzword. A VPC is not a trust badge. A private subnet isn’t a halo.

Also, keep your control types straight: preventive controls stop trouble, detective controls spot it, responsive controls contain it. Real systems mix all three. Or they should, anyway.

3. Identity architecture: roles first, not long-term keys

IAM roles are the default answer for workloads because AWS STS hands out temporary credentials. That’s a very different beast from long-lived IAM user access keys. For EC2, use instance profiles. For Lambda, execution roles. For ECS, task roles. For EKS, IRSA or EKS Pod Identity depending on the setup. Pick the thing that disappears after use.

For human access, split workforce identity from application identity:

  • IAM Identity Center: the go-to AWS-native workforce SSO pattern for multi-account access with permission sets.
  • IAM users: mostly legacy baggage or break-glass territory.
  • Amazon Cognito user pools: authentication for app users, plus tokens.
  • Cognito identity pools: federated identities that need temporary AWS credentials for direct AWS access.

Classic trap: reaching for Cognito when the question is about employees, or reaching for IAM users when federation or roles would be cleaner. Happens all the time.

4. IAM policy evaluation and cross-account access

IAM evaluation is messier than many guides admit. The safe exam version: AWS considers all applicable policy types together, and any explicit deny in the path wins. Effective permissions come from identity-based policies, resource-based policies, permissions boundaries, session policies, SCPs, and service-specific controls. A whole committee, basically.

Important distinctions:

  • Trust policy controls who can assume a role.
  • Permission policy controls what the role can do after assumption.
  • SCPs cap permissions in member accounts; they do not grant anything.
  • Permissions boundaries cap the maximum permissions a user or role can have.
  • Session policies can narrow an assumed-role session even more.

Resource-based policies matter a lot for S3, KMS, SNS, SQS, and cross-account setups. In the same account, identity policy may be enough for some services. Cross-account? Usually you need both sides to say yes.

{ "Version": "2012-10-17", "Statement": [{ "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::111122223333:role/SourceAppRole" }, "Action": "sts:AssumeRole" }]
}

That trust policy only answers “who gets to assume this role.” The source role still needs permission for sts:AssumeRole, and the resulting session still needs access to the target resources. Annoying, but predictable.

For third-party access, external IDs are the tell. If the prompt says “let a SaaS vendor assume a role securely,” think AssumeRole trust policy with an sts:ExternalId condition.

5. Workload identity patterns and a quick lab

The usual secure move: EC2 in a private subnet needs S3 access. Better answer? Almost always an instance profile with least privilege. Add a bucket policy only when you need extra resource-side restriction, cross-account access, or something like a VPC endpoint condition.

Mini lab: fix EC2-to-S3 access without access keys

  • Create an IAM role with s3:GetObject on arn:aws:s3:::my-bucket/*.
  • Attach the role to the EC2 instance as an instance profile.
  • If the instance is private, add an S3 gateway endpoint and wire it to the right route tables.
  • Test with the AWS CLI by listing bucket contents.
  • If it breaks, check IAM policy, bucket policy, endpoint policy, and whether s3:ListBucket is missing on the bucket ARN.

6. Network security: public vs private by routing, not by label

“Private subnet” is more convention than AWS magic. A subnet is effectively public if its route table points at an internet gateway and its instances can get public reachability as needed. Also, the internet gateway hangs off the VPC, not off a subnet. Easy to blur that one.

Canonical secure three-tier pattern:

  • Internet-facing ALB in public subnets
  • Application tier in private subnets
  • RDS in private subnets

An ALB only needs public subnets if it faces the internet. Internal ALBs stay tucked away.

Security groups vs NACLs: security groups are stateful, live on ENIs, and only allow. NACLs are stateless, work at the subnet level, and can allow or deny. If return traffic gets weird with a NACL, ephemeral ports are usually the gremlin.

A cleaner rule example is:

  • ALB security group: inbound 443 from the internet
  • App security group: inbound app port from the ALB security group
  • DB security group: inbound 3306 from the App security group

7. Private connectivity design patterns

Gateway endpoints are for S3 and DynamoDB. They steer traffic through route tables. Interface endpoints drop ENIs into subnets, use security groups, and run on AWS PrivateLink. Private DNS is often the little hinge that makes the door swing, because standard service names resolve to private endpoint IPs.

Exam-ready distinctions:

  • S3/DynamoDB from private subnets: gateway endpoint is usually the cleanest fit.
  • Secrets Manager, STS, CloudWatch, ECR: interface endpoints.
  • ECR nuance: private image pull often needs ecr.api, ecr.dkr, and usually S3 access too.
  • NAT vs endpoint: if you only need AWS services, endpoints usually mean less exposure and less NAT dependence.

Mini lab: create a private app path to AWS services

  • Place an EC2 or ECS task in a private subnet.
  • Add an S3 gateway endpoint.
  • Add interface endpoints for Secrets Manager and STS with private DNS on.
  • Allow endpoint security groups to accept traffic from the workload subnet or workload security group.
  • Test secret retrieval and S3 access without internet egress.

8. Session Manager and secure administration

Session Manager usually beats a bastion host because it removes inbound SSH/RDP exposure and makes auditing less of a scavenger hunt. Still, it needs its ingredients: SSM Agent, an instance role with Systems Manager permissions, and a path to SSM endpoints through internet/NAT or interface endpoints for ssm, ec2messages, and ssmmessages.

Mini lab: secure a private instance with Session Manager

  • Attach an IAM role such as AmazonSSMManagedInstanceCore.
  • Make sure SSM Agent is installed and running.
  • Create the three interface endpoints in private subnets.
  • Remove inbound SSH from the instance security group.
  • Send session logs to CloudWatch Logs or S3.

If Session Manager falls over, check the agent, the instance role, endpoint DNS, endpoint security groups, and whether the instance can actually resolve and reach the SSM endpoints. The usual suspects.

9. Data protection: encryption choices that actually matter

Encrypt in transit with TLS and at rest with service-native encryption. ACM is the standard answer for certificates on integrated AWS services, but two details tend to snag people: CloudFront certificates must live in us-east-1, and ACM public cert private keys are generally not exportable. If you need private PKI, think AWS Private CA.

Current service nuances worth remembering:

  • S3: new objects are encrypted by default, but you may still choose SSE-S3 or SSE-KMS depending on control needs.
  • EBS: turn on account-level encryption by default.
  • RDS: encryption is usually chosen at creation; converting later often means snapshot-copy-restore or migration.
  • DynamoDB: encrypted at rest by default.
  • EFS: supports encryption at rest and in transit.

10. KMS design and troubleshooting

Keep the three key types separate in your head:

  • AWS owned keys: fully managed by AWS, invisible to you for customer control.
  • AWS managed keys: created in your account for a service; limited control.
  • Customer managed keys: full policy and lifecycle control, better for strict governance and cross-account use.

KMS authorization gets tangled fast. Access can depend on key policy, IAM policy, grants, and conditions like kms:ViaService or encryption context. Don’t flatten it into “just check IAM.” And multi-Region keys? Useful for multi-Region cryptographic setups, but they don’t copy your data. Little detail, huge exam difference.

{ "Version": "2012-10-17", "Statement": [ { "Sid": "EnableAccountAdmin", "Effect": "Allow", "Principal": {"AWS": "arn:aws:iam::123456789012:root"}, "Action": "kms:*", "Resource": "*" }, { "Sid": "AllowAppUse", "Effect": "Allow", "Principal": {"AWS": "arn:aws:iam::123456789012:role/AppRole"}, "Action": [ "kms:Decrypt", "kms:Encrypt", "kms:ReEncrypt*", "kms:GenerateDataKey", "kms:GenerateDataKeyWithoutPlaintext", "kms:DescribeKey" ], "Resource": "*" } ]
}

If KMS decrypt fails, check the Region, the key policy, IAM policy, grants, encryption context, and whether the service is actually using the key you think it is. Usually one tiny mismatch. Infuriating, but tiny.

11. S3 security details that show up on the exam

S3 questions love to pile up IAM, bucket policy, Block Public Access, and KMS in the same basket. Block Public Access is a guardrail against accidental public exposure; it doesn’t replace normal authorization for private access. And bucket-level permissions are not object-level permissions. Easy to miss in a hurry.

{ "Version": "2012-10-17", "Statement": [ { "Sid": "RequireTLS", "Effect": "Deny", "Principal": "*", "Action": "s3:*", "Resource": [ "arn:aws:s3:::my-secure-bucket", "arn:aws:s3:::my-secure-bucket/*" ], "Condition": {"Bool": {"aws:SecureTransport": "false"}} } ]
}

If listing is needed, add s3:ListBucket on the bucket ARN. If uploads use SSE-KMS, the caller may also need KMS permissions. For private content delivery through CloudFront, use OAC for S3 origins instead of flinging the bucket open to the world.

12. Secrets Manager vs Parameter Store

Secrets Manager is the answer when automatic rotation matters. Parameter Store SecureString is still handy for configuration and simpler secret storage, but it doesn’t give you native managed rotation on the same level. Different tool, different job.

Good runtime pattern: the app uses its role to fetch the secret at runtime over TLS, the secret is decrypted through KMS, and the app caches it in memory or with a client-side cache. Less hard-coded junk, fewer repeated lookups.

Mini lab: encrypt application secrets properly

  • Store DB credentials in Secrets Manager.
  • Grant secretsmanager:GetSecretValue to the workload role.
  • Make sure KMS permissions exist if a customer managed key protects the secret.
  • Optionally enable rotation for supported databases.

13. Edge protection: WAF, Shield, CloudFront, and origin hardening

AWS WAF handles Layer 7 trouble: SQL injection, XSS, bad bots, weird request floods. Shield handles DDoS. Shield Standard comes with services like CloudFront and Route 53 and gives baseline protection for supported resources; Shield Advanced adds more muscle and response support.

WAF can attach to CloudFront, ALB, API Gateway, AppSync, and Cognito user pools. If the prompt says “protect against malicious HTTP requests and DDoS,” think WAF plus Shield, often with CloudFront sitting out front like a bouncer with good posture.

CloudFront helps on both security and performance. It can terminate viewer TLS, shrink origin exposure, and pair with WAF. For S3 origins, use OAC. For ALB origins, keep direct access locked down where you can so clients must go through CloudFront instead of sneaking around it.

14. Logging, detection, and governance: what each service actually does

CloudTrail records AWS API activity. For exam depth, remember management events versus data events: object-level S3 activity and some Lambda visibility need data events. CloudWatch is not the audit trail; it’s for metrics, alarms, and log streams like app and system logs.

AWS Config records configuration state and compliance over time. GuardDuty inspects AWS data sources for threats without you building the whole detection machine yourself. Security Hub pulls findings and compliance posture together; it is not a raw log store. Inspector evaluates EC2, container images in ECR, and supported Lambda scanning. Macie looks for sensitive data in S3.

In multi-account setups, use AWS Organizations, often with Control Tower as a landing-zone accelerator, plus a log archive account and a separate security account. Delegate admin for services like GuardDuty and Security Hub. Centralize CloudTrail and Config data, encrypt logs, and make deletion annoyingly hard.

15. Troubleshooting matrix and exam heuristics

AccessDenied on S3: check IAM allow, bucket policy, Block Public Access assumptions, missing s3:ListBucket, VPC endpoint policy, and KMS permissions.

KMS decrypt failure: check key policy, IAM policy, grants, wrong Region, wrong key, and encryption context mismatch.

Private workload cannot reach AWS service: check endpoint type, route tables for gateway endpoints, private DNS for interface endpoints, endpoint security groups, and whether you’re leaning on NAT by accident.

AssumeRole failure: check source permission to call sts:AssumeRole, destination trust policy, external ID condition, and SCP restrictions.

Session Manager failure: check SSM Agent, instance role, endpoint reachability, and logging configuration.

WAF present but origin still exposed: check whether the origin is reachable directly and whether CloudFront/origin restrictions are actually enforced.

16. Most testable distinctions and final checklist

Memorize these distinctions:

  • Roles over IAM user access keys for workloads
  • IAM Identity Center for workforce access; Cognito for app users
  • Security groups are stateful allow-only; NACLs are stateless and can deny
  • Gateway endpoints for S3/DynamoDB; interface endpoints for many other services
  • Secrets Manager for rotation; Parameter Store for simpler secure parameters
  • WAF for web exploits; Shield for DDoS
  • CloudTrail for API audit; Config for configuration history; GuardDuty for threat detection; Security Hub for findings aggregation
  • SCPs restrict but never grant

Final review questions:

  1. Can I replace long-term credentials with a role?
  2. Can I cut public exposure or use private connectivity instead?
  3. Do I need SSE-S3 for simplicity or SSE-KMS for tighter control?
  4. Do I need WAF, Shield, or both?
  5. Have I included CloudTrail, Config, and centralized findings where appropriate?
  6. Which option meets the requirement with the least operational drag?

The exam usually rewards architectures that are private by design, role-based, encrypted, observable, and governed across accounts. Think in layers, stay requirement-driven, and toss out the answers that lean on static keys, public convenience, or extra custom machinery.