Security-First Design
Threat modeling with STRIDE, defense in depth, zero trust principles, secrets management, and supply chain security.
Security-First Design
Threat modeling with STRIDE, defense in depth, zero trust principles, secrets management, and supply chain security.
What you'll learn
- Security is an architecture concern — it cannot be bolted on after the fact. Design decisions made without security create structural vulnerabilities tools cannot fix.
- STRIDE threat modeling: Spoofing, Tampering, Repudiation, Information Disclosure, Denial of Service, Elevation of Privilege — apply systematically to every component.
- Defense in depth: security controls at every layer (network, identity, application, data, detection) — compromise of one layer does not mean full system compromise.
- Never hardcode secrets. Use IAM roles for AWS service access (no keys at all). Use AWS Secrets Manager or Vault for third-party API keys and database passwords.
- Least privilege: every identity (user, service, Lambda function) should have only the exact permissions it needs for its specific job — nothing more.
Lesson outline
Security is an architecture problem, not a product problem
The most common misconception in software security: that you can add security at the end. "We will do the security audit before release." "We will enable WAF when we are in production." "We will rotate secrets after launch."
Security that is added after the fact has gaps — design decisions made without security in mind create structural vulnerabilities that tools cannot patch. A WAF cannot fix an IDOR (Insecure Direct Object Reference) bug in your API. An audit cannot undo the fact that your service runs with admin database permissions.
Security-first design
Security is designed into the architecture at every layer — not bolted on afterward. It asks: what could go wrong? Who could misuse this? What is the blast radius if this component is compromised? These questions are asked in design reviews, not in security audits three months later.
Threat modeling with STRIDE
Threat modeling is the practice of systematically identifying what could go wrong with a system before it is built. STRIDE is the most widely-used framework.
| Threat | What it means | Example | Mitigation |
|---|---|---|---|
| Spoofing | Attacker pretends to be another user or service | Forged JWTs, session fixation, IP spoofing | Strong authentication, signed tokens, certificate pinning |
| Tampering | Attacker modifies data in transit or at rest | HTTP parameter manipulation, SQL injection, MITM | HTTPS everywhere, parameterized queries, input validation, checksums |
| Repudiation | Attacker denies performing an action | "I never transferred that money" | Immutable audit logs with user, timestamp, and action — CloudTrail, WORM storage |
| Information Disclosure | Sensitive data exposed to unauthorized parties | Stack traces in API errors, S3 bucket ACL misconfiguration, verbose logs | Least privilege, encrypt at rest, sanitize error messages, no credentials in logs |
| Denial of Service | Attacker makes service unavailable | DDoS, resource exhaustion via large payloads, regex DoS | Rate limiting, input size limits, WAF, DDoS protection (CloudFront/Shield) |
| Elevation of Privilege | Attacker gains more access than intended | IDOR bugs, JWT algorithm confusion, path traversal | Authorization checks on every request, principle of least privilege, RBAC |
How to run a threat modeling session
01
Draw a data flow diagram (DFD): every component, every data store, every external entity, every data flow with trust boundaries.
02
For each component and data flow, apply STRIDE: which of the six threats apply here?
03
For each threat identified, assess likelihood (1–5) × impact (1–5) = risk score.
04
For high-risk threats (score ≥ 12), define a mitigation and assign it as a work item.
05
Document assumptions. "We assume the internal network is trusted" is a decision — not a fact. Make it explicit.
Draw a data flow diagram (DFD): every component, every data store, every external entity, every data flow with trust boundaries.
For each component and data flow, apply STRIDE: which of the six threats apply here?
For each threat identified, assess likelihood (1–5) × impact (1–5) = risk score.
For high-risk threats (score ≥ 12), define a mitigation and assign it as a work item.
Document assumptions. "We assume the internal network is trusted" is a decision — not a fact. Make it explicit.
Defense in depth
Defense in depth means having multiple independent security controls at every layer. A single control failing does not mean the attacker wins — they still must defeat every other control.
Security layers in a cloud architecture
- Network layer — VPC with private subnets, security groups (allow-list only), NACLs, WAF on the edge, no direct internet access to databases or internal services.
- Identity & access layer — IAM least privilege, MFA for all human access, OIDC for service-to-service, no long-lived access keys (use role assumption and temporary credentials via STS).
- Application layer — Input validation, parameterized queries, output encoding, CSRF tokens, Content Security Policy, secure cookie flags (HttpOnly, Secure, SameSite).
- Data layer — Encryption at rest (KMS-managed keys), encryption in transit (TLS 1.2+), field-level encryption for PII, data minimization (do not store what you do not need).
- Detection layer — CloudTrail (API calls), VPC Flow Logs (network traffic), GuardDuty (threat detection), Security Hub (compliance posture), access log alerting for unusual patterns.
The attacker's cost model
Defense in depth works by making the cost of a successful attack prohibitively high. Even if an attacker bypasses the WAF, they still need to break the application-layer auth. Even if they compromise an application server, the database is in a private subnet with no direct internet route, encrypted at rest, and the app only has SELECT permission on specific tables. Each layer adds cost to the attack.
A developer hardcodes an AWS access key in a Lambda function environment variable to access an S3 bucket. Which security problem does this create?
Secrets management
Secrets (API keys, database passwords, certificates, OAuth tokens) need to be stored securely, rotated regularly, and accessed with minimal blast radius.
| Method | Security level | Problem |
|---|---|---|
| Hardcoded in source code | ❌ None | Checked into git forever — every developer and their laptop has it |
| Environment variables baked into image | ❌ Poor | In image layers, in CI logs, in kubectl describe pod output |
| Environment variables injected at runtime (unencrypted) | ⚠️ Partial | Visible in process list, container env dumps, CloudWatch Logs |
| AWS Secrets Manager / HashiCorp Vault | ✅ Good | Encrypted at rest, access-controlled by IAM, automatic rotation, full audit trail |
| AWS Parameter Store (SecureString with KMS) | ✅ Good | Cheaper than Secrets Manager for static secrets; no auto-rotation |
The IAM role pattern eliminates most secrets
Most "secrets" in cloud environments are credentials to access other AWS services (RDS, S3, DynamoDB). IAM roles eliminate these entirely — the Lambda function or EC2 instance assumes a role and gets temporary credentials automatically. No keys to store, rotate, or leak. Only use Secrets Manager for third-party API keys and database passwords.
How this might come up in interviews
Security-conscious companies and any senior engineering interview. Often comes up as a follow-up when discussing architecture: "How would you secure this system?"
Common questions:
- How do you approach security in system design?
- What is threat modeling and have you done it?
- What is defense in depth?
- How do you manage secrets in a cloud application?
- What is the principle of least privilege?
Key takeaways
- Security is an architecture concern — it cannot be bolted on after the fact. Design decisions made without security create structural vulnerabilities tools cannot fix.
- STRIDE threat modeling: Spoofing, Tampering, Repudiation, Information Disclosure, Denial of Service, Elevation of Privilege — apply systematically to every component.
- Defense in depth: security controls at every layer (network, identity, application, data, detection) — compromise of one layer does not mean full system compromise.
- Never hardcode secrets. Use IAM roles for AWS service access (no keys at all). Use AWS Secrets Manager or Vault for third-party API keys and database passwords.
- Least privilege: every identity (user, service, Lambda function) should have only the exact permissions it needs for its specific job — nothing more.
Before you move on: can you answer these?
What does "defense in depth" mean, and why does it matter?
Multiple independent security controls at every layer so that no single failure compromises the entire system. An attacker must defeat every control — network, identity, application, data, and detection — not just one.
Ready to see how this works in the cloud?
Switch to Career Paths for structured paths (e.g. Developer, DevOps) and provider-specific lessons.
View role-based pathsSign in to track your progress and mark lessons complete.
Discussion
Questions? Discuss in the community or start a thread below.
Join DiscordIn-app Q&A
Sign in to start or join a thread.