Home / Deep Dive / Zero Trust Network Architecture: Azure AD + Conditional Access + Intune + Defender
Deep Dive

Zero Trust Network Architecture: Azure AD + Conditional Access + Intune + Defender

Implement a comprehensive Zero Trust security architecture using Microsoft Entra ID, Conditional Access policies, Intune device compliance, and Microsoft Defender XDR for end-to-end identity, device, and network protection.

What you will learn

Practical execution with concise explanations, real implementation patterns, and production-ready recommendations.

Introduction: Why Zero Trust Is No Longer Optional

Introduction: Why Zero Trust Is No Longer Optional

The traditional perimeter-based security model is dead. With remote work, BYOD, cloud applications, and sophisticated threat actors, organizations must adopt a "never trust, always verify" approach. This deep dive implements a complete Zero Trust architecture using Microsoft's security stack — from identity verification through Entra ID, to device compliance with Intune, to threat detection with Defender XDR. Every access request is continuously evaluated against identity, device health, location, and risk signals.

Prerequisites

  • Microsoft 365 E5 or E3 + Security Add-on
  • Azure AD Premium P2 (Microsoft Entra ID P2)
  • Microsoft Intune licenses
  • Microsoft Defender for Endpoint Plan 2
  • Azure subscription for Log Analytics and Sentinel
  • Global Administrator or Security Administrator role

Phase 1: Identity Foundation with Microsoft Entra ID

Phase 1: Identity Foundation with Microsoft Entra ID

Configuring Authentication Strength Policies

# Connect to Microsoft Graph
Connect-MgGraph -Scopes "Policy.ReadWrite.ConditionalAccess", "Policy.Read.All"

# Create custom authentication strength for privileged access
$authStrength = @{
    displayName = "Privileged Access - Phishing Resistant"
    description = "Requires phishing-resistant MFA for admin operations"
    allowedCombinations = @(
        "fido2",
        "windowsHelloForBusiness",
        "x509CertificateMultiFactor"
    )
    requirementsSatisfied = "mfa"
}

New-MgPolicyAuthenticationStrengthPolicy -BodyParameter $authStrength

# Configure Entra ID Protection risk policies
$signInRiskPolicy = @{
    displayName = "High Risk Sign-In - Block"
    state = "enabled"
    conditions = @{
        signInRiskLevels = @("high")
        applications = @{ includeApplications = @("All") }
        users = @{ includeUsers = @("All"); excludeUsers = @("breakglass@contoso.com") }
    }
    grantControls = @{
        operator = "OR"
        builtInControls = @("block")
    }
}

Expected output:

Welcome to Microsoft Graph!

Terminal output for Connect-MgGraph

Privileged Identity Management (PIM) Configuration

# Configure PIM for Global Admin role
$roleDefinitionId = (Get-MgRoleManagementDirectoryRoleDefinition -Filter "displayName eq 'Global Administrator'").Id

# Set eligible assignment policy (max 4 hours, require justification + approval)
$pimPolicy = @{
    rules = @(
        @{
            "@odata.type" = "#microsoft.graph.unifiedRoleManagementPolicyExpirationRule"
            id = "Expiration_EndUser_Assignment"
            isExpirationRequired = $true
            maximumDuration = "PT4H"
            target = @{ caller = "EndUser"; operations = @("All"); level = "Assignment" }
        },
        @{
            "@odata.type" = "#microsoft.graph.unifiedRoleManagementPolicyApprovalRule"
            id = "Approval_EndUser_Assignment"
            setting = @{
                isApprovalRequired = $true
                approvalStages = @(@{
                    approvalStageTimeOutInDays = 1
                    isApproverJustificationRequired = $true
                    primaryApprovers = @(@{
                        "@odata.type" = "#microsoft.graph.groupMembers"
                        groupId = "security-admins-group-id"
                    })
                })
            }
        },
        @{
            "@odata.type" = "#microsoft.graph.unifiedRoleManagementPolicyNotificationRule"
            id = "Notification_Admin_EndUser_Assignment"
            notificationType = "Email"
            recipientType = "Admin"
            notificationLevel = "Critical"
            isDefaultRecipientsEnabled = $true
        }
    )
}

Phase 2: Conditional Access Policies

Implementing Adaptive Access Controls

{
  "policies": [
    {
      "displayName": "CA001 - Require MFA for all users",
      "state": "enabled",
      "conditions": {
        "users": {
          "includeUsers": ["All"],
          "excludeUsers": ["breakglass-account-id"]
        },
        "applications": { "includeApplications": ["All"] },
        "clientAppTypes": ["browser", "mobileAppsAndDesktopClients"]
      },
      "grantControls": {
        "operator": "OR",
        "builtInControls": ["mfa"],
        "authenticationStrength": { "id": "phishing-resistant-strength-id" }
      }
    },
    {
      "displayName": "CA002 - Require compliant device for Office 365",
      "state": "enabled",
      "conditions": {
        "users": { "includeUsers": ["All"] },
        "applications": { "includeApplications": ["Office365"] },
        "platforms": { "includePlatforms": ["android", "iOS", "windows", "macOS"] }
      },
      "grantControls": {
        "operator": "AND",
        "builtInControls": ["compliantDevice", "mfa"]
      },
      "sessionControls": {
        "signInFrequency": {
          "value": 12,
          "type": "hours",
          "authenticationType": "primaryAndSecondaryAuthentication"
        },
        "persistentBrowser": { "mode": "never", "isEnabled": true }
      }
    },
    {
      "displayName": "CA003 - Block legacy authentication",
      "state": "enabled",
      "conditions": {
        "users": { "includeUsers": ["All"] },
        "applications": { "includeApplications": ["All"] },
        "clientAppTypes": ["exchangeActiveSync", "other"]
      },
      "grantControls": {
        "operator": "OR",
        "builtInControls": ["block"]
      }
    },
    {
      "displayName": "CA004 - Require compliant network for admin portals",
      "state": "enabled",
      "conditions": {
        "users": {
          "includeRoles": [
            "Global Administrator",
            "Security Administrator",
            "Exchange Administrator"
          ]
        },
        "applications": {
          "includeApplications": [
            "Microsoft Admin Portals"
          ]
        },
        "locations": {
          "includeLocations": ["All"],
          "excludeLocations": ["trusted-corporate-locations"]
        }
      },
      "grantControls": {
        "operator": "OR",
        "builtInControls": ["block"]
      }
    }
  ]
}

Phase 3: Device Compliance with Intune

Phase 3: Device Compliance with Intune

Windows Compliance Policy

{
  "@odata.type": "#microsoft.graph.windows10CompliancePolicy",
  "displayName": "Windows - Corporate Compliance",
  "scheduledActionsForRule": [
    {
      "ruleName": "PasswordRequired",
      "scheduledActionConfigurations": [
        {
          "actionType": "block",
          "gracePeriodHours": 24,
          "notificationTemplateId": "compliance-warning-template"
        },
        {
          "actionType": "retire",
          "gracePeriodHours": 720,
          "notificationTemplateId": "compliance-retire-template"
        }
      ]
    }
  ],
  "passwordRequired": true,
  "passwordMinimumLength": 14,
  "passwordRequiredType": "alphanumeric",
  "passwordExpirationDays": 90,
  "osMinimumVersion": "10.0.22621",
  "secureBootEnabled": true,
  "bitLockerEnabled": true,
  "tpmRequired": true,
  "antivirusRequired": true,
  "antiSpywareRequired": true,
  "defenderEnabled": true,
  "defenderVersion": "4.18.2301",
  "firewallEnabled": true,
  "codeIntegrityEnabled": true,
  "storageRequireEncryption": true,
  "deviceThreatProtectionEnabled": true,
  "deviceThreatProtectionRequiredSecurityLevel": "secured",
  "advancedThreatProtectionRequiredSecurityLevel": "secured"
}

Configuration Profile for Security Hardening

# Create Intune configuration profile via Graph API
$securityBaseline = @{
    "@odata.type" = "#microsoft.graph.windows10EndpointProtectionConfiguration"
    displayName = "Zero Trust - Endpoint Hardening"
    firewallBlockAllIncoming = $true
    firewallProfileDomain = @{
        firewallEnabled = "allowed"
        inboundConnectionsBlocked = $true
        outboundConnectionsRequired = $true
        stealthModeBlocked = $false
    }
    applicationGuardEnabled = $true
    applicationGuardAllowPrintToLocalPrinters = $false
    applicationGuardAllowPersistence = $false
    bitLockerEnableStorageCardEncryptionOnMobile = $true
    bitLockerEncryptDevice = $true
    bitLockerSystemDrivePolicy = @{
        encryptionMethod = "xtsAes256"
        startupAuthenticationRequired = $true
        startupAuthenticationTpmUsage = "required"
        startupAuthenticationTpmPinUsage = "required"
        recoveryOptions = @{
            enableRecoveryInformationSaveToStore = $true
            recoveryKeyUsage = "required"
            hideRecoveryOptions = $false
        }
    }
    defenderSecurityCenterBlockExploitProtectionOverride = $true
    defenderAdobeReaderLaunchChildProcess = "enable"
    defenderOfficeAppsLaunchChildProcess = "enable"
    defenderOfficeMacroCodeAllowWin32Imports = "block"
    defenderScriptObfuscatedMacroCode = "block"
    defenderScriptDownloadedPayloadExecution = "block"
}

Phase 4: Microsoft Defender XDR Integration

Configuring Advanced Hunting Queries

// Detect impossible travel - user signs in from two geographically distant locations
let impossibleTravelThreshold = 500; // km
IdentityLogonEvents
| where Timestamp > ago(24h)
| where ActionType == "LogonSuccess"
| project Timestamp, AccountUpn, IPAddress, City = tostring(Location.City), 
    Latitude = todouble(Location.Latitude), Longitude = todouble(Location.Longitude)
| order by AccountUpn, Timestamp asc
| serialize
| extend PrevTimestamp = prev(Timestamp, 1), PrevLat = prev(Latitude, 1), 
    PrevLon = prev(Longitude, 1), PrevUser = prev(AccountUpn, 1)
| where AccountUpn == PrevUser
| extend TimeDiffMinutes = datetime_diff('minute', Timestamp, PrevTimestamp)
| extend DistanceKm = geo_distance_2points(Longitude, Latitude, PrevLon, PrevLat) / 1000
| where DistanceKm > impossibleTravelThreshold and TimeDiffMinutes < 120
| project Timestamp, AccountUpn, DistanceKm, TimeDiffMinutes, 
    RequiredSpeedKmh = DistanceKm / (TimeDiffMinutes / 60.0)

// Detect credential stuffing patterns
IdentityLogonEvents
| where Timestamp > ago(1h)
| where ActionType == "LogonFailed"
| summarize FailedAttempts = count(), DistinctAccounts = dcount(AccountUpn), 
    Accounts = make_set(AccountUpn, 10) by IPAddress, bin(Timestamp, 5m)
| where FailedAttempts > 20 and DistinctAccounts > 5
| order by FailedAttempts desc

// Detect suspicious mailbox rules (BEC indicator)
CloudAppEvents
| where Timestamp > ago(7d)
| where ActionType == "New-InboxRule"
| extend RuleName = tostring(RawEventData.Parameters[0].Value),
    ForwardTo = tostring(RawEventData.Parameters[?(@.Name == "ForwardTo")].Value),
    DeleteMessage = tostring(RawEventData.Parameters[?(@.Name == "DeleteMessage")].Value)
| where ForwardTo != "" or DeleteMessage == "True"
| project Timestamp, AccountUpn = AccountObjectId, RuleName, ForwardTo, DeleteMessage

Automated Investigation and Response

{
  "automationRules": [
    {
      "name": "Auto-contain compromised device",
      "trigger": "alertCreated",
      "conditions": [
        {
          "property": "alertSeverity",
          "operator": "equals",
          "value": "high"
        },
        {
          "property": "alertCategory",
          "operator": "in",
          "value": ["Malware", "Ransomware", "CredentialAccess"]
        }
      ],
      "actions": [
        {
          "type": "isolateDevice",
          "comment": "Auto-isolated due to high-severity threat detection"
        },
        {
          "type": "disableUser",
          "comment": "Account disabled pending investigation"
        },
        {
          "type": "collectInvestigationPackage"
        },
        {
          "type": "assignToAnalyst",
          "analystGroup": "Tier2-SOC"
        }
      ]
    }
  ]
}

Phase 5: Network Segmentation with Azure Private Link

Securing Application Access

// Private endpoint for Key Vault
resource keyVaultPrivateEndpoint 'Microsoft.Network/privateEndpoints@2023-09-01' = {
  name: 'pe-keyvault-zerotrust'
  location: resourceGroup().location
  properties: {
    subnet: {
      id: privateEndpointSubnet.id
    }
    privateLinkServiceConnections: [
      {
        name: 'keyvault-connection'
        properties: {
          privateLinkServiceId: keyVault.id
          groupIds: ['vault']
        }
      }
    ]
  }
}

// Network Security Group with zero-trust rules
resource nsgZeroTrust 'Microsoft.Network/networkSecurityGroups@2023-09-01' = {
  name: 'nsg-zerotrust-workloads'
  location: resourceGroup().location
  properties: {
    securityRules: [
      {
        name: 'DenyAllInbound'
        properties: {
          priority: 4096
          direction: 'Inbound'
          access: 'Deny'
          protocol: '*'
          sourceAddressPrefix: '*'
          destinationAddressPrefix: '*'
          sourcePortRange: '*'
          destinationPortRange: '*'
        }
      }
      {
        name: 'AllowAppGatewayInbound'
        properties: {
          priority: 100
          direction: 'Inbound'
          access: 'Allow'
          protocol: 'Tcp'
          sourceAddressPrefix: 'GatewayManager'
          destinationAddressPrefix: '*'
          sourcePortRange: '*'
          destinationPortRange: '443'
        }
      }
      {
        name: 'AllowAzureLoadBalancer'
        properties: {
          priority: 110
          direction: 'Inbound'
          access: 'Allow'
          protocol: '*'
          sourceAddressPrefix: 'AzureLoadBalancer'
          destinationAddressPrefix: '*'
          sourcePortRange: '*'
          destinationPortRange: '*'
        }
      }
    ]
  }
}

Phase 6: Microsoft Sentinel SIEM Integration

Centralized Security Monitoring

// Zero Trust health score dashboard
let identityScore = toscalar(
    SigninLogs | where TimeGenerated > ago(24h) 
    | summarize MFARate = 1.0 * countif(AuthenticationRequirement == "multiFactorAuthentication") / count()
);
let deviceScore = toscalar(
    IntuneDeviceComplianceOrg | where TimeGenerated > ago(24h) 
    | summarize ComplianceRate = 1.0 * countif(ComplianceState == "compliant") / count()
);
let networkScore = toscalar(
    AzureNetworkAnalytics_CL | where TimeGenerated > ago(24h) 
    | summarize BlockedRate = 1.0 * countif(FlowStatus_s == "D") / count()
);
print IdentityScore = round(identityScore * 100, 1),
    DeviceScore = round(deviceScore * 100, 1),
    NetworkScore = round((1 - networkScore) * 100, 1),
    OverallZeroTrustScore = round((identityScore + deviceScore + (1 - networkScore)) / 3 * 100, 1)

Zero Trust Maturity Assessment

Pillar Level 1 (Traditional) Level 2 (Advanced) Level 3 (Optimal)
Identity Password + SMS MFA FIDO2 + Risk-based CA Passwordless + Continuous evaluation
Devices Antivirus only Compliance policies Real-time risk assessment
Network VPN perimeter Micro-segmentation Identity-aware proxy
Apps On-prem only Cloud w/ SSO CASB + App protection
Data No classification Sensitivity labels Auto-classification + DLP
Monitoring Basic logs SIEM correlation AI-driven threat hunting

Architecture Decision and Tradeoffs

When designing integrated solutions solutions with Azure + Power Platform, consider these key architectural trade-offs:

Approach Best For Tradeoff
Managed / platform service Rapid delivery, reduced ops burden Less customisation, potential vendor lock-in
Custom / self-hosted Full control, advanced tuning Higher operational overhead and cost

Recommendation: Start with the managed approach for most workloads and move to custom only when specific requirements demand it.

Validation and Versioning

  • Last validated: April 2026
  • Validate examples against your tenant, region, and SKU constraints before production rollout.
  • Keep module, CLI, and SDK versions pinned in automation pipelines and review quarterly.

Security and Governance Considerations

  • Apply least-privilege access using RBAC roles and just-in-time elevation for admin tasks.
  • Store secrets in managed secret stores and avoid embedding credentials in scripts or source files.
  • Enable audit logging, data protection policies, and periodic access reviews for regulated workloads.

Cost and Performance Notes

  • Define budgets and alerts, then monitor usage and cost trends continuously after go-live.
  • Baseline performance with synthetic and real-user checks before and after major changes.
  • Scale resources with measured thresholds and revisit sizing after usage pattern changes.

Official Microsoft References

  • https://learn.microsoft.com/azure/architecture/
  • https://learn.microsoft.com/azure/well-architected/
  • https://learn.microsoft.com/power-platform/guidance/

Public Examples from Official Sources

  • These examples are sourced from official public Microsoft documentation and sample repositories.
  • Documentation examples: https://learn.microsoft.com/azure/well-architected/
  • Sample repositories: https://github.com/Azure/ArchitectureCenter
  • Prefer adapting these examples to your tenant, subscriptions, and governance requirements before production use.

Key Takeaways

  • Zero Trust is a journey, not a destination — start with identity and expand systematically
  • Conditional Access policies are the policy engine of Zero Trust in Microsoft's ecosystem
  • Device compliance combined with Conditional Access ensures only healthy devices access resources
  • Microsoft Defender XDR provides cross-workload detection and automated response
  • Network segmentation with Private Link eliminates public endpoint exposure
  • Continuous monitoring through Sentinel ties all pillars together for unified security posture

Further Reading

Discussion