1.Security architecture principles: threat modeling to secure defaults
Threat modeling is the exercise of asking, for a specific system, who would attack it, how, and what they would gain — done before or during design, not after an incident. Attack surface is everything an attacker could touch: every endpoint, input field, dependency and open port, and a smaller surface is easier to defend than a larger one. Least privilege means every user, service and process gets only the access it needs to do its job, nothing more. Defense in depth means stacking multiple independent security controls so one failure does not mean total compromise. Secure defaults means the out-of-the-box configuration is the safe one, so a team that changes nothing is still reasonably protected.
Key features
- Threat modeling asks three questions for a specific system: what are we building, what can go wrong, and what will we do about it — frameworks like STRIDE (spoofing, tampering, repudiation, information disclosure, denial of service, elevation of privilege) structure the second question
- Attack surface grows with every new endpoint, third-party dependency, open port and input field — reducing it (removing an unused admin route, an unpinned dependency) is often cheaper than defending it
- Least privilege applies to humans and to services alike — a service account that only ever reads one table should not hold write access to the whole database, since a compromised credential then grants only what that credential actually needed
- Defense in depth assumes any single control can fail — a WAF, input validation, parameterized queries and least-privilege database access are four independent layers against SQL injection, not four redundant copies of the same one
- Secure defaults shift the burden from "the team must remember to configure this safely" to "the team must deliberately choose to weaken it" — a new S3 bucket that defaults to private is secure by default; one that defaults to public is not
- Network — database not reachable from the public internet
- Identity — least-privilege, per-service credential
- Application — parameterized queries, input validation
- Data — sensitive columns encrypted at rest
- Detection — audit logs alert on anomalous query patterns
Command
// Least privilege applied to a database credential
// Bad: one shared "app_user" role, superuser-adjacent
// Good: one role per service, scoped to what it touches
GRANT SELECT, INSERT ON orders TO orders_service;
GRANT SELECT ON orders TO reporting_service;
-- reporting_service can never write, even if
-- its credential leaksThreat model per feature, not once; shrink the attack surface before defending it; grant least privilege to humans and services alike; stack independent layers (defense in depth) since any one control can fail; ship secure by default so an unconfigured system is still reasonably safe.