Web Security & Ethical Hacking · Lesson 17 of 23
Zero Trust Architecture — Never Trust, Always Verify
The Perimeter Model Is Dead
The classic castle-and-moat model assumed that everything inside the network is trusted and everything outside is not. You deployed a VPN, put a firewall at the edge, and considered yourself secure.
That model fails in three concrete ways today:
- Lateral movement — Once an attacker is inside (via phishing, a compromised endpoint, or a stolen VPN credential), they move freely. The 2020 SolarWinds breach propagated for months inside trusted perimeters.
- Cloud and SaaS — Your data and workloads are no longer inside a building. Azure, GitHub, Salesforce, and your CI/CD pipeline sit outside any traditional perimeter.
- Remote work — Employees connect from personal devices on untrusted networks. A VPN grants broad network access — far more than they need.
VPN is not Zero Trust. A VPN authenticates a user once, assigns them a network segment, then trusts everything they do. Zero Trust has no trusted network positions.
The Three Core Principles
Zero Trust is defined by three NIST SP 800-207 principles.
1. Verify Explicitly
Every request is authenticated and authorized using all available signals: identity, location, device health, service, workload, data classification, and anomalies. Not just at login — on every request.
2. Use Least Privilege Access
Permissions are granted for the minimum scope needed, for the minimum time needed, and revoked automatically. Just-enough access, just-in-time.
3. Assume Breach
Design as if attackers are already inside. Minimise blast radius, segment access, encrypt everything in transit (including east-west internal traffic), and log everything for detection.
Identity Is the New Perimeter
In a Zero Trust model, identity takes the role the network perimeter used to play. Every human user, service account, managed identity, and workload has an identity — and that identity is the control plane.
Traditional model: IP address inside the network implies trust. Zero Trust model: Verified identity plus device health plus contextual signals equals access decision.
Azure AD (Entra ID) is the identity provider for the Microsoft ecosystem. Key capabilities:
- Conditional Access Policies — evaluate sign-in risk, device compliance, location
- Privileged Identity Management (PIM) — just-in-time privileged role activation
- Managed Identities — service-to-service auth with no credentials stored anywhere
- Continuous Access Evaluation (CAE) — revoke tokens in near-real-time when risk changes
Microsegmentation: East-West Is the Real Threat
Traditional firewalls focus on north-south traffic (external to internal). Microsegmentation controls east-west traffic (service to service inside your network or cluster).
Without microsegmentation every pod can reach every other pod. With microsegmentation you define explicit allow rules:
- APIGateway to OrderService on port 443: ALLOWED
- APIGateway to UserService on port 443: ALLOWED
- OrderService to PaymentService on port 443: ALLOWED
- OrderService to UserService: DENIED (no business reason)
- PaymentService to OrderService: DENIED (payment does not call orders)
In Kubernetes, implement this with NetworkPolicy resources. In Azure, use Azure Firewall Premium or Network Security Groups at the subnet level.
Conditional Access Policy — Azure AD Example
A Conditional Access policy enforces Zero Trust at the identity layer. This example requires MFA and a compliant device for access to your API app registration:
{
"displayName": "Require MFA and compliant device for API access",
"state": "enabled",
"conditions": {
"users": { "includeGroups": ["api-users-group-id"] },
"applications": { "includeApplications": ["your-api-app-registration-id"] },
"signInRiskLevels": ["medium", "high"]
},
"grantControls": {
"operator": "AND",
"builtInControls": ["mfa", "compliantDevice"]
}
}Apply this via the Azure Portal, Terraform (azurerm_conditional_access_policy), or the Microsoft Graph API.
Just-in-Time Access with Azure PIM
Permanent privileged role assignments violate least privilege. Azure PIM gives you just-in-time elevation:
- Developer requests Contributor on a resource group for a 2-hour window
- PIM sends an approval request to their manager
- Manager approves — role is activated with a time limit, reason recorded in the audit log
- At expiry the role is automatically removed — no standing access remains
az rest --method POST \
--url "https://management.azure.com/providers/Microsoft.Authorization/roleAssignmentScheduleRequests/{id}?api-version=2020-10-01" \
--body '{
"properties": {
"principalId": "{userId}",
"requestType": "SelfActivate",
"scheduleInfo": {
"expiration": { "type": "AfterDuration", "duration": "PT2H" }
},
"justification": "Deploying hotfix to production"
}
}'mTLS Between Services
For service-to-service communication, mTLS (mutual TLS) means both sides present and verify certificates. This eliminates stolen-bearer-token attacks where a compromised service impersonates another.
// Program.cs — configure Kestrel with mTLS for an internal .NET service
builder.WebHost.ConfigureKestrel(options =>
{
options.Listen(IPAddress.Any, 5001, listenOptions =>
{
listenOptions.UseHttps(httpsOptions =>
{
httpsOptions.ServerCertificate = LoadCertFromKeyVault();
httpsOptions.ClientCertificateMode = ClientCertificateMode.RequireCertificate;
httpsOptions.ClientCertificateValidation = (cert, chain, errors) =>
{
return cert.Issuer == "CN=InternalCA,O=YourOrg";
};
});
});
});In Kubernetes with Istio or Linkerd, mTLS is transparent — sidecar proxies handle cert rotation via SPIFFE/SPIRE. You get mTLS without changing application code.
Zero Trust for a .NET Microservices API
Service Accounts with Minimal Permissions
// Use Azure Managed Identity — no credentials in code or config ever
builder.Services.AddAzureClients(clientBuilder =>
{
clientBuilder.UseCredential(new DefaultAzureCredential());
clientBuilder.AddSecretClient(new Uri(builder.Configuration["KeyVault:Uri"]!));
clientBuilder.AddBlobServiceClient(new Uri(builder.Configuration["Storage:Uri"]!));
});The Managed Identity for OrderService holds Key Vault Secrets User and Storage Blob Data Reader on the specific container it needs. No Owner, no Contributor, no broad subscription access.
Short-Lived Token Validation
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidIssuer = "https://login.microsoftonline.com/{tenantId}/v2.0",
ValidateAudience = true,
ValidAudience = "api://order-service",
ValidateLifetime = true,
ClockSkew = TimeSpan.FromSeconds(30),
};
});Audit Every Call
app.Use(async (context, next) =>
{
var user = context.User.Identity?.Name ?? "anonymous";
var correlationId = context.TraceIdentifier;
var resource = $"{context.Request.Method} {context.Request.Path}";
logger.LogInformation(
"ACCESS {CorrelationId} User={User} Resource={Resource} IP={IP}",
correlationId, user, resource, context.Connection.RemoteIpAddress);
await next();
logger.LogInformation(
"RESULT {CorrelationId} Status={Status}",
correlationId, context.Response.StatusCode);
});Route this log stream to Azure Monitor and Log Analytics. Build alerts on anomalous patterns — a service account calling an endpoint it has never called before is a breach signal.
Zero Trust Maturity Model
CISA defines a Zero Trust Maturity Model with three stages:
| Stage | Identity | Device | Network | Application | Data | |-------|----------|--------|---------|-------------|------| | Traditional | Passwords, on-prem IdP | Unmanaged | Flat, implicit trust | No internal authz | Unclassified | | Advanced | MFA, cloud IdP, CA policies | MDM enrolled | Microsegmented | Per-app authz | Classified at rest | | Optimal | Continuous risk scoring, passwordless | Continuous compliance | Fully encrypted east-west | Just-in-time access | Automated DLP |
Most enterprises sit between Traditional and Advanced. Reaching Advanced is achievable in 6-12 months with Azure AD P2 plus Defender for Endpoint plus Conditional Access.
What to Do This Week
- Enable MFA for all users and block legacy auth protocols in Conditional Access
- Audit service-to-service calls — any using long-lived secrets? Migrate to Managed Identities
- Turn on Azure AD Sign-in Logs and alert on impossible travel and leaked credential detections
- Review container network policies — can every pod reach every other pod? Lock it down with NetworkPolicy
- Identify standing privileged roles and migrate them to Azure PIM with approval workflows
Zero Trust is a journey, not a product you purchase. Implement it incrementally, pillar by pillar. Start with identity — because identity is the control plane for everything else.