Back to blog
Security & Complianceadvanced

Zero Trust Architecture — Never Trust, Always Verify

The perimeter is dead. Learn how Zero Trust replaces VPN-based security with identity-driven, microsegmented, continuously verified access for modern .NET microservices on Azure.

LearnixoApril 15, 20266 min read
SecurityZero TrustAzure ADmTLSMicrosegmentationConditional AccessAzure PIM.NET
Share:𝕏

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:

  1. 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.
  2. 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.
  3. 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:

JSON
{
  "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:

  1. Developer requests Contributor on a resource group for a 2-hour window
  2. PIM sends an approval request to their manager
  3. Manager approves — role is activated with a time limit, reason recorded in the audit log
  4. At expiry the role is automatically removed — no standing access remains
Bash
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.

C#
// 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

C#
// 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

C#
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

C#
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

  1. Enable MFA for all users and block legacy auth protocols in Conditional Access
  2. Audit service-to-service calls — any using long-lived secrets? Migrate to Managed Identities
  3. Turn on Azure AD Sign-in Logs and alert on impossible travel and leaked credential detections
  4. Review container network policies — can every pod reach every other pod? Lock it down with NetworkPolicy
  5. 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.

Enjoyed this article?

Explore the Security & Compliance learning path for more.

Found this helpful?

Share:𝕏

Leave a comment

Have a question, correction, or just found this helpful? Leave a note below.