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
| State | Description | Use Case |
|---|
enabled | Policy is active and enforced | Production policies |
disabled | Policy exists but not enforced | Temporarily disabled |
enabledForReportingButNotEnforced | Report-only mode | Testing new policies |
User Conditions
users = {
include_users = ["All"]
exclude_groups = [
microsoft365_graph_beta_groups_group.breakglass.id
]
}
Application Conditions
applications = {
include_applications = ["All"]
}
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.
Test in report-only mode first
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.