What you'll learn: By the end of this lesson you will be able to state what zero trust means in the words of NIST SP 800-207, name its seven tenets and its three logical components (policy engine, policy administrator, policy enforcement point), describe how Google's BeyondCorp papers decide access from device and user instead of network location, apply least privilege to a person, a service and a network path, write a per-request decision that denies by default, and plan for the failure that zero trust adds: the decision service going down.
A hospital has a front desk where every visitor signs in and gets a sticker. In an old-fashioned hospital the sticker is enough: wear it and every ward door opens. In a careful one, each ward door checks again: is this person expected on this ward, today? Does the pharmacy open only for pharmacists? Nobody is treated as a suspect. The building just stops treating "got past the lobby" as proof of anything.
That is the shift from a trusted network to zero trust. Security for Distributed Systems already says to give every actor the minimum access it needs, and ShopStream Stage 10 gives zero trust a short section. This lesson goes to the source documents and spends most of its time on what is hard: deciding access per request, keeping privileges small over time, and surviving the decision point's own failures. The lessons on role-based and attribute-based access control and on secrets management are planned and have no page yet.
Verified against NIST SP 800-207 (August 2020), the two Google BeyondCorp articles in ;login:, the AWS IAM security best practices page and the Kubernetes NetworkPolicy documentation, on 2026-11-08.
The core idea
Zero trust is not a product or a network layout. It is the practice of making every access decision from evidence about the request, at the moment of the request, with the smallest permission that does the job. NIST's operative definition says zero trust provides concepts "designed to minimize uncertainty in enforcing accurate, least privilege per-request access decisions in information systems and services in the face of a network viewed as compromised". Least privilege is the goal; per-request evidence is the mechanism; "network location is not evidence" is the premise.
Three examples run through the lesson: a minimal example (a Java decision function that denies by default), a realistic example (ShopStream's support console and its internal services) and a failure example (the policy decision point becoming unavailable).
What NIST says
NIST SP 800-207, "Zero Trust Architecture", was published in August 2020 as a response to networks that are no longer one perimeter: remote workers, cloud services and devices outside the walls. Its seven tenets, paraphrased:
| # | Tenet | For a backend |
|---|---|---|
| 1 | All data sources and computing services are resources | Queues and caches need rules too |
| 2 | All communication is secured regardless of network location | Internal calls are authenticated; inside the cluster is not trust |
| 3 | Access is granted per session, with least privilege | A token for one resource does not open another |
| 4 | Access is decided by dynamic policy over identity, application and device state, plus behavioural and environmental attributes | Rules can use more than a role |
| 5 | The enterprise monitors the posture of all owned and associated assets | Unpatched or unmanaged assets are treated differently |
| 6 | Authentication and authorisation are dynamic and strictly enforced before access | Re-evaluate during a session |
| 7 | The enterprise collects as much information as possible and uses it to improve policy | Telemetry feeds policy |
Two caveats from the document are easy to miss. NIST says these tenets are the ideal goal and that "not all tenets may be fully implemented in their purest form". And it says they apply to work done within an organisation or with partners, and not to anonymous public or consumer-facing business processes. A shopper browsing ShopStream is not inside a zero trust enterprise; zero trust governs the staff plane and the service plane behind the shopper.
The logical components
NIST splits the decision into three pieces. The policy engine (PE) makes the ultimate decision to grant, deny or revoke access, using enterprise policy and outside inputs (for example a continuous diagnostics and mitigation system and threat intelligence) as input to a trust algorithm. The policy administrator (PA) establishes or shuts down the communication path between subject and resource, and generates any session credential. The policy enforcement point (PEP) enables, monitors and eventually terminates the connection. The PE and PA together are the policy decision point. The paper puts their communication on a separate control plane from the application data on the data plane.
Figure 1. The three logical components and where they sit. How to read this: data flows along the bottom row. The enforcement point asks the administrator, which asks the engine; the engine decides from policy plus posture and threat inputs, and the answer returns along the same path.
NIST also describes how a trust algorithm can vary. Criteria-based algorithms require every configured criterion to hold; score-based ones compute a confidence value from weighted inputs and compare it to a threshold, and may reduce access (read but not write) instead of denying. Singular algorithms judge each request alone, which is fast but can miss an attacker who stays within a user's normal role; contextual ones consider recent history, at the cost of the engine keeping state.
What Google published: BeyondCorp
Google's two ;login: articles describe one real deployment. The 2014 article (Ward and Beyer) states the problem plainly: a perimeter breach gives an attacker easy access to a privileged intranet, and Google's experience was that faith in the internal network is misplaced. It says access "depends solely on device and user credentials, regardless of a user's network location", with all access "fully authenticated, fully authorized, and fully encrypted based upon device state and user credentials".
The parts it describes:
- A device inventory database and managed devices. A device certificate, issued only to a device present and correct in the inventory, identifies the device but "does not single-handedly grant access privileges": it is a key into information about the device.
- A user and group database tied to HR processes, and single sign-on that validates primary and second-factor credentials and issues short-lived tokens.
- An Internet-facing access proxy in front of every enterprise application, and an access control engine that authorises each request using the user, groups, device certificate, inventory data and an inferred level of trust.
- An unprivileged network for devices in Google buildings, looking like an external one, so local and remote access are equal.
The 2016 article (Osborn, McWilliams, Beyer, Saltonstall) adds trust tiers. Each resource has a minimum tier; a Trust Inferer continuously analyses device state and assigns each device a maximum tier; the access control engine returns a binary decision from the access policy, the inferer's output, the resource and real-time credentials. Its example: a device missing a critical security patch may only reach remediation services, and a known lost device can be denied everything.
Figure 2. The 2014 article's request flow, condensed. How to read this: two credentials arrive at the proxy, one for the device and one for the person. Neither alone grants access. The engine decides on every request, and a failed check means the request is denied.
The migration story matters as much as the design. The 2014 article describes a phased move: qualify each application, analyse traffic, and run a simulator on devices first in logging mode (ineligible traffic is captured but allowed) and then in enforcement mode (captured and dropped). A device moved forward only when more than 99.9 percent of its traffic over a contiguous 30 days was eligible, and enforcement needed more than 99.99 percent. Observe, then enforce: copy that pattern.
Least privilege, concretely
Least privilege has four dials: who (a separate identity per person and per workload), what (specific actions on specific resources, not wildcards), where and when (conditions such as network, device or time), and how long (credentials that expire).
The AWS IAM best-practices page, one provider's statement of the idea, advises: grant only the permissions required for a task (actions on specific resources under specific conditions); start broad while exploring and narrow as the use case matures; generate a fine-grained policy from access activity logged in CloudTrail; use last-accessed information to remove unused permissions; have workloads use temporary credentials through roles, not long-lived keys; and cap delegates with permissions boundaries. Service control policies and resource control policies grant nothing themselves; they only set guardrails.
For the network path, the Kubernetes documentation states that pods are non-isolated by default: all inbound and outbound connections are allowed. A pod becomes isolated for a direction only when a NetworkPolicy selects it for that direction; policies are additive, so the allowed set is the union of what applicable policies allow; and a policy has no effect unless the cluster's network plugin enforces it. Default deny plus named flows is how the "inside is trusted" assumption is removed on the data plane. The API gateway and service mesh lesson covers the workload-identity side.
Minimal example: a decision that denies by default
This is the smallest useful policy decision point: a criteria-based, singular evaluation (NIST's terms) that looks up the device tier, compares it with the resource's minimum tier, checks group membership, and denies on any missing fact.
static String decide(Request r) {
Integer tier = DEVICE_TIER.get(r.deviceId());
if (tier == null) return "DENY unknown device";
if (tier < r.resource().minTier()) return "DENY device tier " + tier + " < required " + r.resource().minTier();
boolean inGroup = r.groups().stream().anyMatch(r.resource().allowedGroups()::contains);
if (!inGroup) return "DENY user not in an allowed group";
return "ALLOW " + r.action() + " on " + r.resource().name();
}
With a refund console that needs tier 3 and group support-leads, an order lookup that needs tier 1 and either support group, and two devices (laptop-17 at tier 3, laptop-22 at tier 1), this prints on JDK 26.0.1:
asha laptop-17 refund-console -> ALLOW refund on refund-console
asha laptop-22 refund-console -> DENY device tier 1 < required 3
ben laptop-17 refund-console -> DENY user not in an allowed group
ben laptop-22 order-lookup -> ALLOW view on order-lookup
ben laptop-99 order-lookup -> DENY unknown device
Row 2 is the point: the same person is allowed on one device and denied on another. Row 5 is the other: an unknown device is not "tier 0", it is a denial. The data (tiers, groups) is invented for the demo.
Trade-offs
| Choice | Gain | Cost | Wrong when |
|---|---|---|---|
| Per-request decisions | A stolen credential or device stops working when evidence changes | A decision on the hot path, and a service that must stay up | The resource is low value and the latency budget tiny |
| Score-based, contextual trust | Graded, adaptive access | State, tuning, hard-to-explain denials | You must explain every denial |
| Default-deny network policy | Removes lateral reach | Every legitimate flow must be named | You do not know your flows yet (observe first) |
| Short-lived credentials | Small blast radius | Rotation; outages if issuance fails | Offline jobs that cannot renew |
In practice: refunds, a support console and a ledger
This is the realistic example. It is an educational scenario on ShopStream and describes no real company.
This is a realistic scenario, not a case history.
The situation
ShopStream support staff issue refunds from an internal console. Staff reach it over a company VPN, and once connected the console and every internal service accept their requests. The payments design posts refunds to the ledger, and the Notifications service shares a database login with Payments "for convenience" (an illustrative flaw). A review asks what a stolen VPN laptop or a compromised Notifications pod could do.
Starting architecture
Figure 3. What "inside is trusted" allows. How to read this: the red dashed edge is access nobody intended. Notifications can reach the ledger because the network permits it and the database login is shared.
Options considered
| Option | What changes | Cost | Risk |
|---|---|---|---|
| A. Tighten roles on the VPN | Narrower roles in the console | Days | A stolen laptop on the VPN still reaches everything the role allows |
| B. Identity-aware access plus per-service identity | Console behind a proxy that checks user, group and device tier per request; each service its own identity and database login; default-deny network policy with named flows | A quarter of part-time work (illustrative) | A policy mistake can lock out support or break a flow |
| C. Full zero trust rebuild | B plus continuous scoring, contextual evaluation, micro-segmentation everywhere | Long; platform-team capacity | High operational load before the basics are in |
The decision
Option B, staged. Refund rights need the support-leads group and a managed device at the highest tier (as in the minimal example); order lookup needs a lower tier. Payments gets its own database login with insert and select on ledger tables only, since the ledger is append-only; Notifications gets no ledger access and no network flow to it. Credentials are short-lived. Contextual scoring is deferred, with a written trigger (for example, abuse inside an allowed role). Every allow and deny goes to the audit stream.
Rollout and verification
- Run the proxy in logging mode first, as BeyondCorp's simulator did: record what would be denied and fix the legitimate flows it finds.
- Generate each service's network allow-list from observed traffic, review it, then enforce.
- Enforce for a pilot group, then all of support.
- Test that Notifications cannot connect to the ledger database, that tier-1 devices cannot reach refunds, and that an unknown device is denied.
- Revoke the shared database login only after every service has its own.
The 2 a.m. failure
The proxy's policy decision service cannot be reached after a bad deploy. Every request is denied, including a support agent's refund for a customer who was charged twice.
Figure 4. The failure zero trust adds. How to read this: the decision point is now on the path of every request. Without a plan, its outage is everyone's outage. The plan treats resources by sensitivity.
NIST names this risk: because resources cannot connect without the policy components' approval, disruption of the enforcement point or the PE and PA "can adversely impact enterprise operations". It recommends replicating them or hosting them in a properly secured cloud environment, which "mitigates the risk but does not eliminate it", and warns that an administrator with configuration access to the policy engine can disrupt operations by mistake, so configuration changes must be logged and audited.
First three checks: the decision service health endpoint, the last deploy to its policy bundle, and whether denials rose for every resource or only some. Mitigation: roll back the policy deploy; use the break-glass path for the double-charge refund (named people, time-limited, every use audited, which the OWASP logging guidance lists among higher-risk functions to log). Longer term: validate a policy in logging mode before enforcing it, and canary policy changes like code.
Architect's notes
- Ask the credential question. "If this one credential leaks, what exactly does it open, and for how long?"
- Observe, then enforce, for policies and network rules alike.
- Decide the fail mode per resource class before the first outage.
- Count privileges never used. Last-accessed data is a to-do list.
- Name the non-goals. Zero trust does not replace authorisation inside the application, and it does not govern anonymous shoppers.
Common mistakes
- Buying zero trust. It is a way of deciding access; a product does not make a flat network with shared logins safe.
- Trusting the network for "just internal" calls. Tenet 2: location alone does not imply trust.
- Identity as the only input. A valid user on an unknown device is a different risk from the same user on a managed one.
- No fail mode. The decision point becomes a single point of failure by design.
- Permissions that only grow, and no audit trail for policy changes or break-glass use.
Key takeaways
- NIST defines zero trust around least-privilege, per-request decisions in the face of a network viewed as compromised: seven tenets, an ideal rather than a product.
- The decision splits into a policy engine, a policy administrator and an enforcement point, with a trust algorithm that is criteria or score based, singular or contextual.
- BeyondCorp decides on device and user credentials, not network location, through an access proxy and an engine that decides every request, with trust tiers per resource.
- Least privilege has four dials: who, what, where and when, how long. Measure usage and remove what is unused. Default deny applies to networks too.
- The new risk is the decision point itself: replicate it, set a fail mode by sensitivity, audit break-glass use.
Practice exercises
Exercise 1 (30 minutes): For ShopStream's Orders service, write one concrete control per NIST tenet. Mark any you would defer, and why.
Exercise 2 (2 hours): Extend decide with a score-based variant (device tier, user risk and time of day as weighted inputs; a middle score allows read but not write). Write six tests and say which of NIST's trust-algorithm types each version is.
Exercise 3 (half a day): Draw ShopStream's checkout service-to-service flows. For each service write the default-deny allow-list, database privileges, credential lifetime, and the fail mode of the policy decision point.
Related reading
Official documentation
- NIST SP 800-207: Zero Trust Architecture - the definition, tenets, components, trust algorithm variants and threats (sections 2, 3 and 5).
- BeyondCorp: A New Approach to Enterprise Security (;login:, December 2014) - the model, components and the migration approach.
- BeyondCorp: Design to Deployment at Google (;login:, Spring 2016) - trust tiers, the Trust Inferer and the device inventory service.
- AWS IAM: Security best practices - least privilege, temporary credentials, access-activity-based policies.
- Kubernetes: Network Policies - default non-isolation, additive rules, plugin requirement.