Skip to main content
Conditional access policies are the foundation of a zero-trust security model, allowing you to enforce access controls based on real-time conditions.

Resources

Conditional Access Policy

Resource: microsoft365_graph_beta_identity_and_access_conditional_access_policyCreate and manage conditional access policies for Entra ID.

Basic Policy Example

resource "microsoft365_graph_beta_identity_and_access_conditional_access_policy" "require_mfa" {
  display_name = "Require MFA for All Users"
  state        = "enabled"
  
  conditions = {
    client_app_types = ["all"]
    
    users = {
      include_users = ["All"]
      exclude_groups = [
        microsoft365_graph_beta_groups_group.breakglass.id
      ]
    }
    
    applications = {
      include_applications = ["All"]
    }
  }
  
  grant_controls = {
    operator          = "OR"
    built_in_controls = ["mfa"]
  }
}

Policy States

StateDescriptionUse Case
enabledPolicy is active and enforcedProduction policies
disabledPolicy exists but not enforcedTemporarily disabled
enabledForReportingButNotEnforcedReport-only modeTesting new policies

User Conditions

users = {
  include_users = ["All"]
  exclude_groups = [
    microsoft365_graph_beta_groups_group.breakglass.id
  ]
}

Application Conditions

applications = {
  include_applications = ["All"]
}

Platform Conditions

conditions = {
  platforms = {
    include_platforms = ["windows", "macOS"]
    exclude_platforms = ["iOS", "android"]
  }
}
Available platforms:
  • windows
  • macOS
  • iOS
  • android
  • linux
  • all

Location Conditions

conditions = {
  locations = {
    include_locations = ["All"]
    exclude_locations = [
      "AllTrusted",
      microsoft365_graph_beta_identity_and_access_named_location.corporate_hq.id
    ]
  }
}

Device Conditions

# Device filter
conditions = {
  devices = {
    device_filter = {
      mode = "exclude"
      rule = "device.isCompliant -eq True -or device.trustType -eq \"ServerAD\""
    }
  }
}

Risk-Based Conditions

conditions = {
  sign_in_risk_levels = ["high", "medium"]
  user_risk_levels    = ["high"]
}
Risk levels:
  • low
  • medium
  • high
  • hidden
  • none

Grant Controls

Block Access

grant_controls = {
  operator          = "OR"
  built_in_controls = ["block"]
}

Require MFA

grant_controls = {
  operator          = "OR"
  built_in_controls = ["mfa"]
}

Require Compliant Device

grant_controls = {
  operator          = "OR"
  built_in_controls = ["compliantDevice"]
}

Require Hybrid Azure AD Join

grant_controls = {
  operator          = "OR"
  built_in_controls = ["domainJoinedDevice"]
}

Multiple Requirements (AND)

grant_controls = {
  operator          = "AND"
  built_in_controls = ["mfa", "compliantDevice"]
}

Authentication Strength

grant_controls = {
  operator = "OR"
  authentication_strength = {
    id = microsoft365_graph_beta_identity_and_access_authentication_strength_policy.phishing_resistant.id
  }
}

Require App Protection Policy

grant_controls = {
  operator          = "OR"
  built_in_controls = ["compliantApplication"]
}

Session Controls

Sign-in Frequency

session_controls = {
  sign_in_frequency = {
    value               = 4
    type                = "hours"
    authentication_type = "primaryAndSecondaryAuthentication"
    frequency_interval  = "timeBased"
    is_enabled          = true
  }
}

Sign-in Every Time

session_controls = {
  sign_in_frequency = {
    authentication_type = "primaryAndSecondaryAuthentication"
    frequency_interval  = "everyTime"
    is_enabled          = true
  }
}

Persistent Browser Session

session_controls = {
  persistent_browser = {
    mode       = "never"  # or "always"
    is_enabled = true
  }
}

Application Enforced Restrictions

session_controls = {
  application_enforced_restrictions = {
    is_enabled = true
  }
}

Common Policy Scenarios

Block Legacy Authentication

resource "microsoft365_graph_beta_identity_and_access_conditional_access_policy" "block_legacy_auth" {
  display_name = "Block Legacy Authentication"
  state        = "enabled"
  
  conditions = {
    client_app_types = ["exchangeActiveSync", "other"]
    
    users = {
      include_users = ["All"]
      exclude_groups = [
        microsoft365_graph_beta_groups_group.breakglass.id
      ]
    }
    
    applications = {
      include_applications = ["All"]
    }
  }
  
  grant_controls = {
    operator          = "OR"
    built_in_controls = ["block"]
  }
}

Require MFA for Admins

resource "microsoft365_graph_beta_identity_and_access_conditional_access_policy" "admin_mfa" {
  display_name = "Require MFA for Administrators"
  state        = "enabled"
  
  conditions = {
    client_app_types = ["all"]
    
    users = {
      include_roles = [
        data.microsoft365_graph_beta_identity_and_access_role_definitions.global_admin.items[0].id,
        data.microsoft365_graph_beta_identity_and_access_role_definitions.security_admin.items[0].id
      ]
      exclude_groups = [
        microsoft365_graph_beta_groups_group.breakglass.id
      ]
    }
    
    applications = {
      include_applications = ["All"]
    }
  }
  
  grant_controls = {
    operator = "OR"
    authentication_strength = {
      id = "00000000-0000-0000-0000-000000000004"  # Phishing-resistant MFA
    }
  }
}

Block Untrusted Locations

resource "microsoft365_graph_beta_identity_and_access_conditional_access_policy" "block_untrusted" {
  display_name = "Block Access from Untrusted Locations"
  state        = "enabled"
  
  conditions = {
    client_app_types = ["all"]
    
    users = {
      include_users = ["All"]
      exclude_groups = [
        microsoft365_graph_beta_groups_group.breakglass.id
      ]
    }
    
    applications = {
      include_applications = ["All"]
    }
    
    locations = {
      include_locations = ["All"]
      exclude_locations = [
        "AllTrusted",
        microsoft365_graph_beta_identity_and_access_named_location.vpn.id
      ]
    }
  }
  
  grant_controls = {
    operator          = "OR"
    built_in_controls = ["mfa", "compliantDevice"]
  }
}

Require Compliant Device for Office 365

resource "microsoft365_graph_beta_identity_and_access_conditional_access_policy" "o365_compliant" {
  display_name = "Require Compliant Device for Office 365"
  state        = "enabled"
  
  conditions = {
    client_app_types = ["browser", "mobileAppsAndDesktopClients"]
    
    users = {
      include_users = ["All"]
      exclude_groups = [
        microsoft365_graph_beta_groups_group.breakglass.id
      ]
    }
    
    applications = {
      include_applications = ["Office365"]
    }
    
    platforms = {
      include_platforms = ["windows", "macOS"]
    }
  }
  
  grant_controls = {
    operator          = "OR"
    built_in_controls = ["compliantDevice", "domainJoinedDevice"]
  }
}

Import Syntax

terraform import microsoft365_graph_beta_identity_and_access_conditional_access_policy.policy <policy-id>

Best Practices

Always exclude break-glass accounts from all conditional access policies to prevent lockout scenarios.
Use state = "enabledForReportingButNotEnforced" to test policies before enforcement.
Combine multiple controls for defense in depth (MFA + compliant device + trusted location).
Name policies clearly to indicate their purpose and scope (e.g., “CAD001-O365: Require Compliant Device”).
Use descriptions to explain why the policy exists and what it protects.
Regularly review sign-in logs to identify blocked users and policy impact.

Build docs developers (and LLMs) love