Section 06

Zero Trust Architecture

Zero Trust is a security model based on the principle "never trust, always verify." It assumes that threats exist both outside and inside the network, and every access request must be authenticated, authorized, and encrypted.

The End of Perimeter Security

Traditional security assumed everything inside the network was trusted. Zero Trust recognizes that attackers breach perimetersβ€”the internal network is not safe.

Core Principles

1. Verify Explicitly

Always authenticate and authorize based on all available data points: identity, location, device health, service, data classification, anomalies.

2. Use Least Privilege Access

Limit user access with just-in-time (JIT) and just-enough-access (JEA). Risk-based adaptive policies that respond to context.

3. Assume Breach

Minimize blast radius with segmentation. Verify end-to-end encryption. Use analytics to detect threats and improve defenses.

Zero Trust Pillars

πŸ‘€

Identities

  • β€’ Strong authentication (MFA)
  • β€’ Passwordless when possible
  • β€’ Conditional access policies
  • β€’ Identity governance
πŸ’»

Devices

  • β€’ Device inventory
  • β€’ Compliance checking
  • β€’ Endpoint detection
  • β€’ Mobile device management
πŸ“±

Applications

  • β€’ Shadow IT discovery
  • β€’ In-app permissions
  • β€’ Runtime monitoring
  • β€’ API security
πŸ“Š

Data

  • β€’ Data classification
  • β€’ Encryption everywhere
  • β€’ DLP policies
  • β€’ Access tracking
πŸ—οΈ

Infrastructure

  • β€’ JIT VM access
  • β€’ Micro-segmentation
  • β€’ Threat detection
  • β€’ Config management
🌐

Networks

  • β€’ Network segmentation
  • β€’ Encrypt all traffic
  • β€’ Real-time threat protection
  • β€’ No implicit trust zones

Zero Trust Network Access (ZTNA)

ZTNA replaces VPNs with identity-aware, context-aware access to specific applications rather than entire network segments.

❌ Traditional VPN

  • β€’ Full network access after auth
  • β€’ Implicit trust of VPN users
  • β€’ Lateral movement possible
  • β€’ Performance bottlenecks
  • β€’ Binary access model

βœ“ ZTNA

  • β€’ App-specific access only
  • β€’ Continuous verification
  • β€’ No lateral movement
  • β€’ Cloud-native scaling
  • β€’ Granular policies

Policy Engine Architecture

Zero Trust Policy Engine Architecture

graph LR Subject["πŸ‘€ Subject (User / App)"] subgraph PDP["Policy Engine (PDP)"] IdP["πŸ”‘ Identity Provider (Entra ID / Okta)"] PolicyAdmin["πŸ“‹ Policy Decision Point β€’ Evaluate policy β€’ Risk score β€’ Device trust β€’ User behavior"] Threat["πŸ” Threat Intel Feeds"] DataPolicy["πŸ“Š Data Access Policy"] end PEP["πŸ›‘οΈ Policy Enforcement Point (PEP)"] Resource["πŸ–₯️ Resource (Data / App)"] Signals["πŸ“‘ Signals β€’ Identity β€’ Device health β€’ Location β€’ Behavior β€’ Data sensitivity"] Subject --> PDP Signals --> PDP PDP -->|"Allow / Deny + Context"| PEP Subject --> PEP PEP --> Resource

Implementation Steps

1

Identify Protected Surfaces

Map critical data, applications, assets, and services (DAAS).

2

Map Transaction Flows

Understand how users and apps access protected surfaces.

3

Architect Zero Trust Network

Deploy micro-perimeters around each protected surface.

4

Create Zero Trust Policies

Define who/what/when/where/why/how for access (Kipling Method).

5

Monitor and Maintain

Continuous logging, analytics, and policy refinement.

NIST SP 800-207

NIST Special Publication 800-207 defines the authoritative Zero Trust Architecture reference. It describes three deployment approaches: Enhanced Identity Governance, Micro-Segmentation, and Software Defined Perimeters (SDP). Most enterprises blend all three.

Practical: OPA Policy for Zero Trust Access

zero-trust-policy.rego
rego
package zerotrust.access

import rego.v1

default allow := false

# Require ALL conditions for access (never trust, always verify)
allow if {
    identity_verified
    device_compliant
    context_acceptable
    permission_granted
}

# Identity must be authenticated with MFA
identity_verified if {
    input.identity.authenticated == true
    input.identity.mfa_verified == true
    time.now_ns() < input.identity.token_expiry_ns
}

# Device must meet compliance baseline
device_compliant if {
    input.device.managed == true
    input.device.os_patched == true
    input.device.encryption_enabled == true
    input.device.edr_running == true
    input.device.risk_score < 50
}

# Context checks: location, time, behavior
context_acceptable if {
    not input.context.impossible_travel
    input.context.risk_score < 70
}

# RBAC + resource-level check
permission_granted if {
    required_role := data.resource_roles[input.resource.path][input.method]
    required_role == input.identity.roles[_]
}
package zerotrust.access

import rego.v1

default allow := false

# Require ALL conditions for access (never trust, always verify)
allow if {
    identity_verified
    device_compliant
    context_acceptable
    permission_granted
}

# Identity must be authenticated with MFA
identity_verified if {
    input.identity.authenticated == true
    input.identity.mfa_verified == true
    time.now_ns() < input.identity.token_expiry_ns
}

# Device must meet compliance baseline
device_compliant if {
    input.device.managed == true
    input.device.os_patched == true
    input.device.encryption_enabled == true
    input.device.edr_running == true
    input.device.risk_score < 50
}

# Context checks: location, time, behavior
context_acceptable if {
    not input.context.impossible_travel
    input.context.risk_score < 70
}

# RBAC + resource-level check
permission_granted if {
    required_role := data.resource_roles[input.resource.path][input.method]
    required_role == input.identity.roles[_]
}

Platform-Specific Zero Trust Policies

The OPA policy above shows the logic model. Here's how Zero Trust translates to real platform configurations across the three NIST 800-207 deployment approaches: identity governance (Azure/Entra), network micro-segmentation (Kubernetes), and software-defined perimeter (Cloudflare).

Azure Conditional Access (Identity-Centric)

conditional-access-policy.json
json
{
  "displayName": "Require MFA + Compliant Device for Sensitive Apps",
  "state": "enabled",
  "conditions": {
    "applications": {
      "includeApplications": ["finance-portal", "hr-admin"]
    },
    "users": {
      "includeGroups": ["all-employees"]
    },
    "signInRiskLevels": ["medium", "high"],
    "platforms": {
      "includePlatforms": ["all"]
    }
  },
  "grantControls": {
    "operator": "AND",
    "builtInControls": ["mfa", "compliantDevice"]
  },
  "sessionControls": {
    "signInFrequency": { "value": 4, "type": "hours" },
    "persistentBrowser": { "isEnabled": true, "mode": "never" }
  }
}
{
  "displayName": "Require MFA + Compliant Device for Sensitive Apps",
  "state": "enabled",
  "conditions": {
    "applications": {
      "includeApplications": ["finance-portal", "hr-admin"]
    },
    "users": {
      "includeGroups": ["all-employees"]
    },
    "signInRiskLevels": ["medium", "high"],
    "platforms": {
      "includePlatforms": ["all"]
    }
  },
  "grantControls": {
    "operator": "AND",
    "builtInControls": ["mfa", "compliantDevice"]
  },
  "sessionControls": {
    "signInFrequency": { "value": 4, "type": "hours" },
    "persistentBrowser": { "isEnabled": true, "mode": "never" }
  }
}

What This Policy Does

Requires MFA + compliant device for sensitive apps when sign-in risk is medium or high. Session lifetime is limited to 4 hours. Browser sessions are never persisted. This is the identity pillar of Zero Trust operationalized.

Kubernetes NetworkPolicy (Micro-Segmentation)

network-policies.yaml
yaml
# Zero Trust micro-segmentation: default deny ALL traffic
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-all
  namespace: production
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  - Egress
---
# Allow only API gateway -> backend on port 8080
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-api-to-backend
  namespace: production
spec:
  podSelector:
    matchLabels:
      app: backend-service
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: api-gateway
    ports:
    - port: 8080
      protocol: TCP
  egress:
  - to:    # Allow backend -> postgres only
    - podSelector:
        matchLabels:
          app: postgres
    ports:
    - port: 5432
      protocol: TCP
  - to:    # Allow DNS resolution
    ports:
    - port: 53
      protocol: UDP
# Zero Trust micro-segmentation: default deny ALL traffic
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-all
  namespace: production
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  - Egress
---
# Allow only API gateway -> backend on port 8080
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-api-to-backend
  namespace: production
spec:
  podSelector:
    matchLabels:
      app: backend-service
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: api-gateway
    ports:
    - port: 8080
      protocol: TCP
  egress:
  - to:    # Allow backend -> postgres only
    - podSelector:
        matchLabels:
          app: postgres
    ports:
    - port: 5432
      protocol: TCP
  - to:    # Allow DNS resolution
    ports:
    - port: 53
      protocol: UDP

Default Deny Is Non-Negotiable

In Zero Trust Kubernetes, the first policy is always default-deny-all. Then you explicitly allow only the traffic patterns your application requires. Every new service must come with its NetworkPolicy β€” no exceptions. Use kubectl get networkpolicy -A to audit coverage.

Cloudflare Access (Software-Defined Perimeter)

cloudflare-ztna.tf
hcl
# Cloudflare Access β€” ZTNA for internal apps (no VPN needed)
resource "cloudflare_access_application" "internal_wiki" {
  zone_id          = var.zone_id
  name             = "Internal Wiki"
  domain           = "wiki.internal.example.com"
  session_duration = "4h"
  type             = "self_hosted"
}

resource "cloudflare_access_policy" "wiki_access" {
  application_id = cloudflare_access_application.internal_wiki.id
  zone_id        = var.zone_id
  name           = "Require SSO + device posture"
  precedence     = 1
  decision       = "allow"

  include {
    group = [cloudflare_access_group.employees.id]
  }

  require {
    login_method   = [cloudflare_access_identity_provider.okta.id]
    device_posture = [
      cloudflare_device_posture_rule.disk_encryption.id,
      cloudflare_device_posture_rule.os_version.id,
    ]
  }
}

resource "cloudflare_device_posture_rule" "disk_encryption" {
  account_id = var.account_id
  name       = "Disk Encryption Required"
  type       = "disk_encryption"
  match { platform = "mac" }
  input { require_all = true }
}
# Cloudflare Access β€” ZTNA for internal apps (no VPN needed)
resource "cloudflare_access_application" "internal_wiki" {
  zone_id          = var.zone_id
  name             = "Internal Wiki"
  domain           = "wiki.internal.example.com"
  session_duration = "4h"
  type             = "self_hosted"
}

resource "cloudflare_access_policy" "wiki_access" {
  application_id = cloudflare_access_application.internal_wiki.id
  zone_id        = var.zone_id
  name           = "Require SSO + device posture"
  precedence     = 1
  decision       = "allow"

  include {
    group = [cloudflare_access_group.employees.id]
  }

  require {
    login_method   = [cloudflare_access_identity_provider.okta.id]
    device_posture = [
      cloudflare_device_posture_rule.disk_encryption.id,
      cloudflare_device_posture_rule.os_version.id,
    ]
  }
}

resource "cloudflare_device_posture_rule" "disk_encryption" {
  account_id = var.account_id
  name       = "Disk Encryption Required"
  type       = "disk_encryption"
  match { platform = "mac" }
  input { require_all = true }
}

CISA Zero Trust Maturity Model

Pillar Traditional Advanced Optimal
Identity Passwords, basic MFA Phishing-resistant MFA Continuous validation, passwordless
Devices Inventory exists Compliance enforced Real-time risk scoring, auto-remediation
Networks Macro-segmentation Micro-segmentation Encrypted everywhere, no implicit trust
Applications Some cloud integration SSO + context-aware access Per-request authz, runtime monitoring
Data Basic classification Auto-classification, DLP Granular controls per datum, full lineage

Migration Strategy: VPN to Zero Trust

Phase 1: Foundation (Months 1-3)

  • β€’ Inventory all users, devices, and applications
  • β€’ Deploy centralized identity provider with MFA
  • β€’ Map application access patterns and dependencies
  • β€’ Start with low-risk applications (e.g., SaaS apps)

Phase 2: Expand (Months 4-8)

  • β€’ Deploy ZTNA proxy for internal web apps
  • β€’ Implement device compliance checking
  • β€’ Add conditional access policies (location, risk)
  • β€’ Run VPN and ZTNA in parallel β€” migrate app by app

Phase 3: Optimize (Months 9-12)

  • β€’ Decommission VPN for migrated apps
  • β€’ Enable micro-segmentation in production
  • β€’ Deploy continuous verification and adaptive policies
  • β€’ Measure: mean time to detect (MTTD), mean time to contain (MTTC)

Zero Trust Anti-Patterns

Common Mistakes That Derail ZT Initiatives

Zero Trust migrations fail more often from organizational issues than technical ones. Recognize and avoid these patterns.

❌ "Just Buy a Product"

Zero Trust is an architecture strategy, not a product SKU. No single vendor delivers it. You need identity + device + network + app + data controls working together across platforms.

❌ Big Bang Migration

Migrating everything at once guarantees outages and organizational pushback. Start with SaaS apps (lowest risk, fastest ROI), then internal web, then legacy. Run VPN in parallel during transition.

❌ Ignoring User Experience

If ZT access is slower or harder than VPN, users will find workarounds. SSO + passwordless auth should make ZT feel easier, not harder. Measure login friction and session interruptions.

❌ Default-Deny Without Baselining First

Enabling strict deny policies before mapping traffic patterns causes legitimate blocks and incident tickets. Deploy in log-only/audit mode first, build a baseline for 2-4 weeks, then enforce.

❌ Treating Legacy Apps as Hopeless

Legacy apps without modern auth can still be wrapped with ZTNA proxies (Cloudflare Access, Zscaler Private Access). You don't need to rewrite β€” front them with identity-aware gateways.

Zero Trust Tools & Platforms

Identity Providers

Okta, Azure AD, Google Workspace, Ping Identity

ZTNA Solutions

Zscaler, Cloudflare Access, Palo Alto Prisma, Akamai EAA

Micro-Segmentation

Illumio, VMware NSX, Guardicore, Cisco Tetration

Policy Engines

Open Policy Agent (OPA), Azure Policy, Styra DAS

Framework Alignment

NIST SP 800-207: Zero Trust Architecture reference standard
NIST CSF 2.0: PR.AC (Access Control), PR.DS (Data Security), DE.CM (Continuous Monitoring)
CISA: Zero Trust Maturity Model v2.0 (5 pillars: Identity, Devices, Networks, Applications, Data)
CIS Controls v8.1: 6 (Access Control), 12 (Network), 13 (Monitoring)
Related: Security Frameworks β†’ | Reference Architectures β†’
🎯

Zero Trust Architecture Labs

Hands-on exercises to implement and validate Zero Trust controls across identity, network, and access layers.

πŸ”§
Kubernetes Micro-Segmentation Lab Custom Lab medium
Deploy a multi-service app in Kubernetes (frontend, API, database)Apply default-deny NetworkPolicies to all namespacesAdd explicit allow policies for required traffic flows onlyVerify that unauthorized pod-to-pod traffic is blocked (use curl from test pod)Monitor denied traffic with Cilium or Calico flow logs
πŸ”§
VPN-to-ZTNA Migration Simulation Custom Lab hard
Deploy Cloudflare Access (or similar) for an internal web appConfigure SSO integration with your identity providerAdd device posture checks (disk encryption, OS version)Run parallel access: VPN users vs. ZTNA users for 1 weekCompare access logs, latency, and user experience metricsDocument migration runbook with rollback procedures
πŸ”§
Azure Conditional Access Policy Design Custom Lab medium
Audit existing Entra ID conditional access policiesCreate risk-based policies requiring MFA for medium/high risk sign-insAdd device compliance requirements for sensitive applicationsTest with What-If tool before enabling in enforcement modeConfigure sign-in frequency and persistent browser controls