AWS Security Architecture

Comprehensive security mechanism flow

Defense-in-depth reference with all architectural diagrams — edge to data layer, IAM OIDC federation, STS chains, SCPs, ABAC, VPC endpoints, WAF rules, and detection pipelines.

Request flow through defense layers Internet request Layer 1 — Edge & perimeterRoute 53 → CloudFront → WAF → Shield (DDoS) Layer 2 — Network securityVPC → NACLs → Security groups → PrivateLink Layer 3 — Identity & accessIAM → STS → OIDC federation → SCPs → ABAC Layer 4 — Data protectionKMS → S3 encryption → TLS in transit → Secrets Manager Continuous monitoring across all layers: CloudTrail → GuardDuty → Config → Security Hub → EventBridge → SNS
Defense in depth

Key principle

Each layer provides independent protection. A request must pass through every layer. If one layer is bypassed or compromised, subsequent layers still enforce security. Continuous detection services monitor across all layers simultaneously.

Policy evaluation at identity layer: explicit deny → SCP boundary → permission boundary → identity ∩ resource policy intersection. Deny at any point = denied.

Edge security: request lifecycle Client request AWS Shield (always-on L3/L4 DDoS protection) Route 53 DNS resolution CloudFront edge location TLS termination (ACM) AWS WAF rule evaluation Managed rulesAWS + marketplace Custom rulesRate / geo / regex Rule priority (lowest first) BLOCK ALLOW CAPTCHA Origin (ALB / S3 / API)
Rules

WAF actions

BLOCK — 403. ALLOW — pass. COUNT — log only (test before enforcement). CAPTCHA — challenge. Challenge — silent JS challenge. Deploy new rules in COUNT → analyze logs → flip to BLOCK.

Web ACL budget: 5,000 WCU. Core Rule Set ~700 WCU. Rules consume WCU so you can't stack unlimited groups.

WAF web ACL rule evaluation order HTTP request arrives Priority 0: IP reputationKnown botnets, scannersManaged rule group Priority 1: Rate limitingPer-IP request thresholdCustom rate rule Priority 2: Geo restrictionCountry-level block/allowCustom geo rule Priority 3: Core rule setXSS, SQLi, SSRF, LFIAWS managed CRS Priority 4: Bad inputsLog4j, Java deserializationAWS managed group Default actionALLOW (if no rule matched) Any match= stop + act

Shield standard vs advanced

Standard (free)
Advanced ($3k/mo)
Scope
L3/L4 DDoS
L3/L4 + L7 application-layer
DRT
No access
24/7 DDoS Response Team
Cost protect
None
Scaling credits for DDoS spikes
WAF
Separate charge
Included at no extra cost
Detection
Automatic inline
ML anomaly + health-based
Interview

Shield Advanced critical detail

Shield Advanced requires Route 53 health checks on protected resources. Without health checks, it can't distinguish DDoS from legitimate traffic spikes.

5 mechanisms

CloudFront security features

TLS termination — ACM free certs, TLS 1.2/1.3, TLSv1.2_2021 policy. Origin Access Control (OAC) — replaces OAI, IAM-based S3 auth, supports SSE-KMS. Signed URLs/cookies — RSA key pairs in Key Groups. Geo restrictions — binary allow/deny by country. Field-level encryption — encrypt POST fields at edge with your public key.

Network security: request path through VPC Internet Internet gateway VPC (10.0.0.0/16) Route table evaluation NACL (stateless)Numbered rules, subnet-level Public subnet Security group (stateful) ALB / NLB Private subnet Security group (stateful) App (EKS) RDS VPC flow logs capture all ENI traffic → CloudWatch / S3 for analysis

NACLs vs security groups

NACL (stateless)
Security group (stateful)
Scope
Subnet boundary
ENI (instance/pod) level
State
Stateless — eval both dirs
Stateful — return auto-allowed
Rules
Allow + deny
Allow only (implicit deny)
Order
Numbered, lowest first
All rules evaluated together
Default
Allow all (custom VPC)
Deny all inbound
Association
1 NACL per subnet
Up to 5 SGs per ENI
Ref SGs
No
Yes (SG chaining)
Interview trap

Ephemeral port gotcha

NACLs are stateless: allow inbound 443, but response goes back on random port 1024-65535. Outbound rules must allow that range. SGs don't have this problem — stateful means return traffic auto-allowed.

Security group chaining: micro-segmentation Internet (0.0.0.0/0) sg-alb Inbound: 443 from 0.0.0.0/0 Only HTTPS in sg-app (EKS pods) Inbound: 8080 from sg-alb only References sg-alb sg-db (RDS Aurora) Inbound: 3306 from sg-app only References sg-app Compromise of ALB cannot reach DB directly — must traverse app layer SG references auto-update when instances scale (no IP management)
Architecture decision

PrivateLink vs VPC peering vs Transit Gateway

PrivateLink — service-level private access across accounts (one-directional, no IP overlap, per-service).

VPC peering — bidirectional VPC-to-VPC (non-transitive, no CIDR overlap).

Transit Gateway — hub-and-spoke across many VPCs and on-prem (transitive, centralized routing, supports overlapping CIDRs via route tables).

GitHub OIDC federation: keyless AWS access GitHub ActionsWorkflow triggered GitHub OIDC providerIssues JWT token JWT claimsiss: token.actions.githubusercontent.comsub: repo:org/repo:ref:refs/heads/mainaud: sts.amazonaws.com STSAssumeRoleWithWebIdentity Trust policy validatesCondition: token.actions... == issCondition: sub matches repo/branch Temp credentialsAccessKey + Secret + Token What this eliminatesNo IAM user, no static keys AWS API callsDeploy, push, manage Credentials auto-expire (default 1h, max 12h) Zero static credentials in GitHub Secrets = zero credential rotation burden
Security

Trust policy scoping

"Condition": { "StringLike": { "token.actions.githubusercontent.com:sub": "repo:SKCloudOps/*:ref:refs/heads/main" }, "StringEquals": { "token.actions.githubusercontent.com:aud": "sts.amazonaws.com" } }

Scope to org + branch + environment. Add environment claim for prod. Use sts:TagSession to carry repo/SHA into CloudTrail.

STS assume-role chain: cross-account access DevOps account (111111) Role: ci-cd-deployerTrust: GitHub OIDC + optional session policy AssumeRole Staging account (222222) Role: staging-deployTrust: arn:...ci-cd-deployer Permissions: EKS + ECR Chain hop 2 Prod account (333333) Role: prod-deployTrust: arn:...staging-deploy Permissions: EKS only Role chaining constraintsMax session: 1 hour when chaining (cannot extend with DurationSeconds)CloudTrail: each hop logged with sourceIdentity for full audit trailEffective permissions = intersection of all roles in the chain SCP hierarchy: organizational guardrails Organization rootSCP: FullAWSAccess OU: ProductionSCP: DenyNonApprovedRegions OU: SandboxSCP: DenyExpensiveServices Phrma prodAccount 333 Shared svcsAccount 444 Effective permission calculation Root SCP OU SCP Account SCP Identity policy = Effective permissions (must be allowed at EVERY level) SCPs are deny guardrails — they cannot grant permissions, only restrict

ABAC vs RBAC

RBAC (traditional)
ABAC (recommended)
Model
Role per job function
Tag principal + tag resource
Scale
N roles × M resources = N*M
1 policy covers all projects
New project
Create new role + policy
Just tag the resources
Condition
Static ARN matching
Dynamic tag matching
IAM limit
High risk (5120 char)
Low risk (single policy)
Implementation

ABAC condition keys

"Condition": { "StringEquals": { "aws:ResourceTag/Project": "${aws:PrincipalTag/Project}" } }

aws:PrincipalTag — tags on caller. aws:ResourceTag — tags on target. aws:RequestTag — enforce at creation. aws:TagKeys — prevent tag escalation.

Encryption at rest

KMS envelope encryption

CMK stored in HSMs, never leaves KMS unencrypted. GenerateDataKey returns plaintext DEK + encrypted DEK. Plaintext DEK encrypts data, then discarded. To decrypt: send encrypted DEK to KMS → get plaintext DEK → decrypt data.

Key policies control access. Automatic annual rotation (old versions retained). Grants for temporary scoped access.

SSE

S3 encryption options

SSE-S3: AWS manages keys. AES-256. Default. No audit trail. SSE-KMS: KMS CMK. CloudTrail logs every operation. $0.03/10K requests. SSE-C: You provide key per request. Rare use case.

Enforce: deny PutObject without x-amz-server-side-encryption: aws:kms header.

Credentials

Secrets Manager

KMS-encrypted. Auto-rotation via Lambda for RDS/Redshift/DocumentDB. Version staging labels (AWSCURRENT, AWSPENDING, AWSPREVIOUS) for zero-downtime rotation. Cross-account via resource policy. EKS integration via External Secrets Operator or CSI driver.

In transit

TLS in transit

ACM free public certs + auto-renewal. Private CA via ACM PCA. CloudFront: TLS 1.2/1.3 at edge. ALB: termination + re-encrypt. EKS: service mesh mTLS. Enforce aws:SecureTransport in bucket policy.

Detection, monitoring & automated response Data sources (continuous ingestion) CloudTrail VPC flow logs DNS logs S3 / CW logs Detection & compliance engines GuardDutyML threat detection ConfigCompliance rules InspectorVuln scanning MacieData discovery Security HubAggregated findings + scoring EventBridge rules Lambda remediation SNS / PagerDuty SSM automation
ML-based

GuardDuty

Analyzes CloudTrail, VPC flow logs, DNS logs via ML + threat intel. Finding types: reconnaissance, instance compromise (C&C), account compromise. EKS audit log monitoring for K8s threats. S3 protection for unusual data access.

Compliance

AWS Config

Records config changes. ~300+ managed rules. Conformance packs (PCI-DSS, CIS). Auto-remediation via SSM Automation. Cross-account aggregator for compliance dashboard.

Aggregation

Security Hub

Single pane: normalizes findings from GuardDuty, Config, Inspector, Macie, IAM Access Analyzer into ASFF. Security score per standard. Custom actions → EventBridge.

Architecture

Automated remediation pattern

GuardDuty detects compromised EC2 → EventBridge rule → Lambda → removes from all SGs → attaches forensic SG → takes EBS snapshot → sends SNS alert. Total time: under 60 seconds.