CYART // SCHEMA · ZERO-TRUST-GATEWAY8 NODES · 7 LINKSWHAT WE DESIGNPOSTUREREQUESTALLOW?ALLOWEDACTOR · Device — agent postureACTOR01Deviceagent postureACTOR · User — browser / CLIACTOR02Userbrowser / CLIEDGE · Edge PoP — TLS, DDoS, anycastEDGE03Edge PoPTLS, DDoS, anycastSERVICE · Policy enforcement — proxy per requestSERVICE04Policy enforcementproxy per requestSERVICE · Policy decision — OPA / Cedar, 1 to 3 msSERVICE05Policy decisionOPA / Cedar, 1 to 3 msDATA · Identity — OIDC, MFA, groupsDATA06IdentityOIDC, MFA, groupsDATA · Signals — device, geo, risk scoreDATA07Signalsdevice, geo, risk scoreSTREAM · Private app — mTLS from PEP onlySTREAM08Private appmTLS from PEP only

Segmentation and zero trust

From flat networks to identity-aware access: VPC design, security groups, network policy and the per-request checks that zero trust actually means.

● Must know for interviewsFREELesson·11 min read·Intermediate → Advanced
zero trustsegmentationnetwork policy

01Why flat networks fail

✓What you will learn
  • Design network tiers that limit lateral movement
  • Explain zero trust as per-request authn + authz + device context
  • Write a default-deny network policy that does not break DNS
  • Roll segmentation out without an outage
  • Know when a VPN is the wrong answer

In a flat network, one compromised laptop or pod can reach every database. Most real breaches are not a single exploit; they are an initial foothold followed by lateral movement: harvesting credentials, scanning for open ports and hopping host to host until something valuable answers. Segmentation turns one hop into many, each one authenticated and logged.

Macro-segmentation splits the estate into large zones (VPCs, accounts, environments). Micro-segmentation controls traffic between individual workloads, ideally by identity rather than address. You want both: zones contain the blast radius of a misconfiguration, and per-workload rules contain an attacker inside a zone.

FigIdentity-aware access instead of a VPN
CYART // SCHEMA · ZERO-TRUST-GATEWAY8 NODES · 7 LINKSWHAT WE DESIGNPOSTUREREQUESTALLOW?ALLOWEDACTOR · Device — agent postureACTOR01Deviceagent postureACTOR · User — browser / CLIACTOR02Userbrowser / CLIEDGE · Edge PoP — TLS, DDoS, anycastEDGE03Edge PoPTLS, DDoS, anycastSERVICE · Policy enforcement — proxy per requestSERVICE04Policy enforcementproxy per requestSERVICE · Policy decision — OPA / Cedar, 1 to 3 msSERVICE05Policy decisionOPA / Cedar, 1 to 3 msDATA · Identity — OIDC, MFA, groupsDATA06IdentityOIDC, MFA, groupsDATA · Signals — device, geo, risk scoreDATA07Signalsdevice, geo, risk scoreSTREAM · Private app — mTLS from PEP onlySTREAM08Private appmTLS from PEP only
  • ACTOR
  • EDGE
  • SERVICE
  • DATA
  • STREAM
  • Live flow
  • Lookup / async
//Every request passes a policy enforcement point that asks a decision service: who is this, on what device, from where, with what risk, for which app. Private apps accept mTLS from the enforcement point only.

02Tiers and default deny

TierAllowed inboundExample
EdgeInternet :443CDN, WAF, load balancers
AppEdge tier only, via mesh identityAPIs, workers
DataApp tier, specific service identities, specific portsPostgres, Redis, Kafka
ManagementZero trust gateway only, MFA, session recordedBastion, k8s API, consoles

In the cloud, express tiers with security groups that reference other security groups rather than CIDR ranges: the database group allows 5432 from the app group, so new app instances are allowed automatically and nothing else is, whatever IP it lands on. In Kubernetes, NetworkPolicy does the same with labels, but only if the CNI enforces it (Calico, Cilium and the managed equivalents do).

Default deny, allow DNS, then allow one pathyaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata: { name: default-deny, namespace: payments }
spec:
  podSelector: {}
  policyTypes: [Ingress, Egress]
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata: { name: allow-dns, namespace: payments }
spec:
  podSelector: {}
  policyTypes: [Egress]
  egress:
  - to: [{ namespaceSelector: { matchLabels: { kubernetes.io/metadata.name: kube-system } }, podSelector: { matchLabels: { k8s-app: kube-dns } } }]
    ports: [{ port: 53, protocol: UDP }, { port: 53, protocol: TCP }]
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata: { name: api-to-db, namespace: payments }
spec:
  podSelector: { matchLabels: { app: postgres } }
  ingress:
  - from: [{ podSelector: { matchLabels: { app: payments-api } } }]
    ports: [{ port: 5432 }]

Policies are additive, so api-to-db opens ingress to Postgres only. Because egress is denied too, the API pods also need an egress rule to Postgres on 5432, or the connection never leaves the client side. Forgetting DNS is the classic first-day breakage: every lookup times out and it looks like the whole cluster is down.

!Egress matters as much as ingress

Data leaves through egress. Default-deny egress with an allow-list of destinations (your APIs, your package mirror) stops most exfiltration and command-and-control, and makes the rest visible in the proxy logs.

03Segmentation in the cloud

Terraform: the database accepts 5432 from the app group, nothing elsehcl
resource "aws_security_group" "db" {
  name   = "payments-db"
  vpc_id = var.vpc_id
}

resource "aws_vpc_security_group_ingress_rule" "db_from_app" {
  security_group_id            = aws_security_group.db.id
  referenced_security_group_id = aws_security_group.app.id
  ip_protocol                  = "tcp"
  from_port                    = 5432
  to_port                      = 5432
  description                  = "payments-api to postgres only"
}

Security groups are stateful (return traffic is allowed automatically) and allow-only. Network ACLs are stateless subnet-level filters that can deny, useful as a coarse backstop such as blocking a known bad range, but painful as the main control. Put data stores in private subnets with no route to an internet gateway, and reach cloud APIs through VPC endpoints so that traffic to S3 or KMS never crosses the internet and can be restricted with endpoint policies.

MistakeWhy it hurtsBetter
Security groups opened to 10.0.0.0/8Every workload in the company becomes a permitted callerReference the caller's security group or identity
Shared VPC with one big app subnetProd and test sit side by side; a test box reaches prod databasesSeparate accounts or VPCs per environment
Peering everything with everythingTransitive reach through shared services turns segments back into one networkHub and spoke through a transit gateway with route tables per segment and inspection
SSH open to the office IP rangeVPN or office compromise equals server accessNo inbound SSH; session manager or a ZT gateway with recording
Rules nobody can explainAfraid to remove them, so they accumulate foreverDescription and owner on every rule; flow logs show which rules are unused

04Segmenting by identity, not address

IP-based rules break down once workloads autoscale, share nodes and move between clusters: the address that was the API a minute ago is now a batch job. A service mesh fixes this by giving each workload an mTLS identity derived from its service account, then letting you write policy against that identity at layer 7.

Istio: only payments-api may POST ledger entriesyaml
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata: { name: ledger-callers, namespace: payments }
spec:
  selector: { matchLabels: { app: ledger } }
  action: ALLOW
  rules:
  - from: [{ source: { principals: ["cluster.local/ns/payments/sa/payments-api"] } }]
    to: [{ operation: { methods: ["POST"], paths: ["/v1/entries"] } }]

The rule names a caller identity, a method and a path. A compromised pod in the same namespace with a different service account is refused even though NetworkPolicy lets its packets through. Combine the two: NetworkPolicy as the coarse layer that still holds if the mesh sidecar is bypassed, mesh policy as the fine layer that understands requests. Turn on strict mTLS mode so plaintext traffic between meshed workloads is rejected rather than silently allowed.

05Rolling it out without an outage

  1. Map real flows first. Collect VPC flow logs or CNI flow data (Cilium Hubble, Calico flow logs) for a few weeks, including month-end jobs and backups.
  2. Draft policy from observed flows, grouped by service identity, and review it with the owning team. Anything surprising in the map is a finding in its own right.
  3. Run in audit mode where the tooling supports it (log-only rules, staged policies), and alert on would-be denials.
  4. Enforce one namespace or tier at a time, starting with the data tier where the allowed callers are fewest and best known.
  5. Keep a fast rollback and make new services ship with their policies, so the default-deny estate does not decay into allow-all exceptions.

06Zero trust, concretely

Zero trust, as NIST SP 800-207 describes it, removes the idea that network location grants trust. A policy enforcement point (an identity-aware proxy, mesh sidecar or gateway) sits in front of each resource and asks a policy decision point whether this request should proceed, using identity, device and context signals. Google's BeyondCorp is the best-known large deployment.

  • Identity on every request: user and workload, never "it came from the internal subnet".
  • Device context: managed, disk encrypted, EDR healthy, OS patched. Unknown device gets read-only or nothing.
  • Least privilege per app: access to the HR app says nothing about access to the payments console.
  • Continuous evaluation: a session that was fine at 9am is re-checked when risk changes (new geo, EDR alert).

A VPN is the wrong answer when it grants network-level access to everything behind it once connected: one phished credential then reaches every internal app. Replacing it with per-app access through a proxy also removes the internet-facing VPN appliance, a perennial target for mass exploitation.

“How to say it in the room

"Zero trust for me is three checks per request, identity, device and policy, enforced at a proxy in front of each app. The VPN goes away because network location stops being a credential. Segmentation stays, because it limits what an attacker can reach when one of those checks is fooled."

Test yourself

A developer needs production database access for an incident. Zero-trust answer?

Q1Does zero trust mean we can drop network segmentation?+

No. Identity checks can be bypassed by a stolen session or a bug; segmentation still bounds what that attacker can reach. They are layers, not alternatives.

Q2How do you handle legacy apps that cannot do modern auth?+

Put them behind an identity-aware proxy that authenticates the user and passes a signed header, and restrict the app's network so only the proxy can reach it.

Q3What breaks first when you enforce default-deny egress?+

DNS, time sync, package mirrors and cloud API endpoints. Allow them explicitly, preferably through VPC endpoints and an egress proxy that logs destinations.

Finished this one?
Tick it and it shows as done on the roadmap and the course.