Security architecture design: turn zero trust, least privilege, and defense in depth into a system
What should you design beyond a WAF and private subnets? Follow a SaaS that imports files from external URLs to connect trust boundaries, network paths, workload identities, KMS, privileged access, and audit logging with containment and verification.
What is security architecture? Distinguish three principles
A WAF, firewall, and encryption do not necessarily stop the same compromise path. Security architecture starts with protected data and business operations, connecting access decisions, allowed actions, evidence, and containment. Explain why each boundary exists, rather than merely naming its components.
| Principle | Design question | Application in this example |
|---|---|---|
| Zero trust | Are we allowing access just because it comes from our network or VPC? | Internal APIs also verify the caller's service identity and target permissions |
| Least privilege | Can we restrict resources, operations, and duration? | The fetcher can write only its assigned temporary object |
| Defense in depth | If one control fails, does a different boundary stop the next step? | Combine URL checks, destination restrictions, database permission separation, and auditing |
The public abstract of NIST SP 800-207 describes avoiding implicit trust based solely on network location or ownership, with authentication and authorization before resource access. This does not mean abandoning network segmentation. Likewise, inspecting input with a WAF and deciding whether someone may read an invoice are distinct controls.
Choose protected assets and an initial compromise point
Threat modeling follows the path from input to resources, beyond checking whether a URL looks safe. Server-side request forgery, or SSRF, makes a server contact unintended destinations. If crafted remote content compromises a processor, colocating customer-database access and decryption privileges lets the compromise spread.
| Assumed abuse | Property to preserve | Responsible boundary |
|---|---|---|
| An import URL targets an internal API or metadata | User-selected destinations cannot reach internal resources | Fetching client and outbound network controls |
| A compromised fetcher uses its credentials | It cannot read customer records or decrypt production files | Runtime, network, and service identity separation |
| Compromised administrator or operator error | Limit standing privileges and deletion of evidence | Time-limited access and separately administered audit storage |
Reference design: separate fetching, inspection, and business data
User → public entry (TLS, WAF, request limits) → business API (authentication, authorization) → Business API → customer database / import controller (verified request metadata) → Import controller → isolated URL fetcher → quarantine storage → Quarantine storage → inspection and conversion → private production file storage → Authorizing delivery service → retrieve and decrypt permitted production files → Boundary audit events → storage ordinary runtime roles cannot delete → on-call notifications
The controller sends a URL and temporary write destination over a protected control channel. Restrict that authority to the job's temporary object, without listing, reading, or changing storage visibility. Fetched files remain quarantined until format, size, malicious-content, and other required checks succeed, then move into production storage.
Inspection and conversion also handle untrusted bytes; they are not an infallible barrier. Bound execution time, memory, and expanded size. Normally deny external egress and allow access only to required inputs and outputs. An import-success message alone must not publish an artifact: verify its relationship to the request, inspection result, and access policy.
Network design: constrain both public ingress and outbound egress
Limit the business API's public entry and let only required application paths reach the database. Distinguish the fetcher's fixed control and storage paths from its user-selected URL path. The latter must not reach internal APIs, loopback, link-local addresses, metadata services, or other internal resources. Separate subnets alone do not reject traffic.
- Limit fetches to registered partner hosts over HTTPS and validate URLs with a maintained parser. Disable automatic redirects.
- Check resolved IPv4 and IPv6 addresses against the actual connection destination to resist DNS changes. Preserve TLS hostname verification and bound fetch duration and received bytes.
- Enforce egress so direct connections or alternative proxies cannot bypass it. Allow only required network destinations, and do not let user-selected URLs reuse exceptions for fixed storage endpoints.
When using private endpoints, verify DNS, routing, public exposure, and IAM together. For example, creating an Azure Storage Private Endpoint does not automatically block connections to its public endpoint. Providing a private route and closing an unnecessary public route are separate configuration tasks.
Least privilege: give each workload role its own identity
Sharing administrator keys across the API, fetcher, inspector, delivery service, and CI lets a fetcher compromise reach deployment or key administration. A workload identity identifies a processing component. Restrict its resources, actions, and conditions, including whether it can assume a stronger role. User-level business authorization remains separate from authenticating a service identity.
| Identity | Example allowed scope | Example denied actions |
|---|---|---|
| URL fetcher | Time-limited write to its assigned temporary object | Customer database reads, production file retrieval, KMS decryption |
| Inspection and conversion | Read assigned quarantine input and store approved output | Full customer-database reads, IAM changes, arbitrary external traffic |
| Delivery service | Retrieve and decrypt an authorized target | Key administration, changing public visibility, deployment |
| CI deployment identity | Deploy an approved artifact to the designated environment | Routine customer-file reads, audit-log deletion |
Use roles or equivalent facilities for temporary runtime credentials. For CI federation, constrain OIDC issuer, audience, repository, environment, and other applicable trust conditions. Credentials exchanged through services such as AWS STS have their own session expiration. Do not equate expiration of the original OIDC token or completion of the CI job with revocation of cloud credentials.
Encryption: separate data access from key administration
Encryption at rest matters, but a compromised component with read permission can still obtain plaintext when the storage read API decrypts automatically. Ask separately who can retrieve ciphertext, who can decrypt, and who can change the key policy.
Generate a data encryption key (DEK) using a cryptographic library → Apply authenticated encryption to the file with the DEK → Wrap the DEK with a key encryption key (KEK) in KMS → Store ciphertext, wrapped DEK, and required encryption metadata → Only permitted readers unwrap the DEK and decrypt
Use managed-storage encryption when it satisfies the requirements. Additional application-layer encryption should use maintained cryptographic libraries and key management rather than custom cryptography. Account for KMS round trips, quotas, outages, plaintext-key caches, and backup restoration. A key administrator without direct decryption permission still needs controls such as approval if they can grant themselves that permission.
Administration: design standing privileges and emergency access
Changing production configuration is more powerful than ordinary file access. Use attributable individual identities through SSO and MFA, with scoped, time-limited elevation when needed. Microsoft Entra PIM is one product example supporting time-bound and approval-based activation, MFA, and notifications. Check the chosen product's capabilities and coverage when implementing these controls.
Prepare emergency access for identity-provider outages, with assigned owners for protected storage, use notifications, and periodic tests. Separately verify whether SSO disablement terminates each service's existing sessions and API keys. Emergency access must not become a routine shared administrator account.
Audit and detection: keep compromised workloads from erasing evidence
Record rejected fetches, role changes, key use, important file retrievals, and audit-configuration changes with actor, target, operation, outcome, and time. Deny ordinary runtime identities permission to delete evidence or reconfigure collection. Use a separate administrative boundary, such as another account, where appropriate. Keep secrets and file contents out of audit records.
In AWS CloudTrail, operations such as S3 GetObject are data events, which trails and event data stores do not record by default. Management logs alone do not establish coverage of customer-file reads. Configure the required resources and check collection scope, retention, and cost.
First verify collection of a test-file read. Then generate activity meeting the configured detection condition, such as a bulk-read rule, and follow it through notification to an on-call investigation. Injecting a sample alert can check delivery, but does not test actual event collection and detection logic end to end. Detect collection outages too.
Rollout and verification: test attempts to cross each boundary
| Test in an environment you control | Expected behavior | Evidence to inspect |
|---|---|---|
| Connect from the fetcher to an internal test destination | Reject through the user-selected fetch path | Destination records and network-enforcement outcomes |
| Use the fetcher's identity to read customer data or decrypt production files | Reject at a network or permission boundary | Denial using the actual identity and no returned customer data |
| Request a production role from an unapproved CI environment | Reject through trust conditions | Audit evidence without secret token values |
| Retrieve a private file through a public route | Reject unwanted public routes and unauthorized retrieval | DNS, exposure settings, and data responses |
| Delete audit evidence using an ordinary runtime identity | Reject deletion and detect collection outages | Preserved records and delivered notifications |
| Exercise procedures assuming KMS or SSO is unavailable | Use defined defer, deny, or emergency procedures without bypassing controls | Recovery time, recoverable data, and remaining limitations |
- Map assets and abuse paths, then close high-impact paths such as exposed databases and shared administrator keys.
- Separate workload identities and permissions; constrain network and storage access for fetchers and converters handling untrusted input. Verify legitimate imports and retrieval too.
- Establish key, administrator, and audit boundaries, and make ownership, containment, and recovery tests repeatable.
More boundaries mean more identities, policies, DNS, and monitoring to maintain. A small team can use managed identity, key, storage, and logging features while keeping the architecture as simple as its protection requirements allow. When a new feature adds communication or administration paths, update diagrams, permission tables, and verification together.
Primary sources for checking design decisions
- NIST SP 800-207 — Zero Trust Architecture (publication abstract)
- OWASP — Threat Modeling Cheat Sheet
- OWASP — Server Side Request Forgery Prevention Cheat Sheet
- Microsoft Learn — Use private endpoints for Azure Storage
- AWS IAM — Security best practices
- AWS STS — AssumeRoleWithWebIdentity: session duration
- Google Cloud KMS — Envelope encryption
- Microsoft Entra — What is Privileged Identity Management?
- AWS CloudTrail — Logging data events
Tips this post digs into
- Map protected data and trust boundaries before building (threat modeling)
- A feature that makes your server fetch URLs is a door into your internal network
- Limit credential lifetime and permissions to reduce exposure after leakage
- Encrypt data with a data key, and have the KMS only wrap that key
- Design administrator access from granting through removal
- Test that audit logging detects the operations you need to see