All posts

Security architecture design: turn zero trust, least privilege, and defense in depth into a system

· 12 min read

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.

PrincipleDesign questionApplication in this example
Zero trustAre 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 privilegeCan we restrict resources, operations, and duration?The fetcher can write only its assigned temporary object
Defense in depthIf 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 abuseProperty to preserveResponsible boundary
An import URL targets an internal API or metadataUser-selected destinations cannot reach internal resourcesFetching client and outbound network controls
A compromised fetcher uses its credentialsIt cannot read customer records or decrypt production filesRuntime, network, and service identity separation
Compromised administrator or operator errorLimit standing privileges and deletion of evidenceTime-limited access and separately administered audit storage

Reference design: separate fetching, inspection, and business data

Main data flows in an original design proposal; the fetcher has no customer-database access or production decryption privileges

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.

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.

IdentityExample allowed scopeExample denied actions
URL fetcherTime-limited write to its assigned temporary objectCustomer database reads, production file retrieval, KMS decryption
Inspection and conversionRead assigned quarantine input and store approved outputFull customer-database reads, IAM changes, arbitrary external traffic
Delivery serviceRetrieve and decrypt an authorized targetKey administration, changing public visibility, deployment
CI deployment identityDeploy an approved artifact to the designated environmentRoutine 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.

If application-layer envelope encryption is chosen, the full file is not sent to KMS

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 controlExpected behaviorEvidence to inspect
Connect from the fetcher to an internal test destinationReject through the user-selected fetch pathDestination records and network-enforcement outcomes
Use the fetcher's identity to read customer data or decrypt production filesReject at a network or permission boundaryDenial using the actual identity and no returned customer data
Request a production role from an unapproved CI environmentReject through trust conditionsAudit evidence without secret token values
Retrieve a private file through a public routeReject unwanted public routes and unauthorized retrievalDNS, exposure settings, and data responses
Delete audit evidence using an ordinary runtime identityReject deletion and detect collection outagesPreserved records and delivered notifications
Exercise procedures assuming KMS or SSO is unavailableUse defined defer, deny, or emergency procedures without bypassing controlsRecovery time, recoverable data, and remaining limitations
  1. Map assets and abuse paths, then close high-impact paths such as exposed databases and shared administrator keys.
  2. Separate workload identities and permissions; constrain network and storage access for fetchers and converters handling untrusted input. Verify legitimate imports and retrieval too.
  3. 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

Tips this post digs into