Based on the great work of Kenneth van Surksum and his conditional access demystification whitepaper, where he has created a spreadsheet with a recommended set of conditional access policies, this Terraform module creates these policies - with some small changes and additions. This version is based on version 1.4 of his recommended policies.
Thanks for your contribution to the community, Kenneth!
You can find this module on Terraform Registry: https://registry.terraform.io/modules/robertbrandso/recommended-conditional-access-policies
When running this as with a service principal the following API permissions are needed:
API permission | Description |
---|---|
Policy.ReadWrite.ConditionalAccess |
Needed to read and create the conditional access policies. |
Policy.Read.All |
Needed to read and create the conditional access policies. |
Group.ReadWrite.All |
Needed to create the Azure AD groups used for exclusion. |
User.Read.All |
Needed to get information about object ID of user accounts when providing UPN. |
Application.Read.All |
Needed to include applications in certain policies. |
Configuration | Required/Optional | Details |
---|---|---|
group_name_prefix |
Required | Prefix for Azure AD group names to be used for exclude groups. Group name will be <prefix>-CA-Exclude-<policy sequence number> . |
emergency_access_upn |
Required | User principal name of your emergency access account which will be excluded from all policies. |
supported_device_platforms |
Required | Specify a list of supported device platforms. Possible values are: android , iOS , linux , macOS , windows , windowsPhone . |
trusted_locations |
Optional | List of IP address ranges in IPv4 CIDR format (e.g. 1.2.3.4/32) or any allowable IPv6 format from IETF RFC596 to be marked as trusted location(s). |
reporting_only_for_all_policies |
Optional | Overrides each policies state and sets it to report only mode. |
privileged_role_ids |
Optional | To define your own list of roles to include, specify the role IDs in this variable. Role IDs can be found in the Microsoft docs - Azure AD built-in roles. Check out the list below to see the default roles. |
The following policies can be created through this module:
Category | Sequence number | Name | Must explicity be enabled | Extra configuration needed | Optional configuration available |
---|---|---|---|---|---|
Prerequisite | CAP001 | CAP001-All: Block Legacy Authentication for All users when OtherClients-v1.0 | No | No | No |
Prerequisite | CAP002 | CAP002-O365: Grant Exchange ActiveSync Clients for All users when Approved App-v1.0 | No | No | No |
User | CAU001 | CAU001-All: Grant Require MFA for guests when Browser and Modern Auth Clients-v1.0 | No | No | No |
User | CAU002 | CAU002-All: Grant Require MFA for All users when Browser and Modern Auth Clients-v1.0 | No | No | No |
User | CAU003 | CAU003-Selected: Block unapproved apps for guests when Browser and Modern Auth Clients-v1.0 | No | Define cau003_included_application_ids with application IDs to include. |
No |
User | CAU004 | CAU004-Selected: Session route through MDCA for All users when Browser on Non-Compliant-v1.2 | No | Define cau004_included_application_ids with application IDs to include. |
No |
User | CAU005 | CAU005-Selected: Session route through MDCA for All users when Browser on Compliant-v1.1 | No | Define cau005_included_application_ids with application IDs to include. |
No |
User | CAU006 | CAU006-All: Grant Require MFA for High Risk Sign-in for All Users when Browser and Modern Auth Clients-v1.0 | No | No | No |
User | CAU007 | CAU007-All: Grant Require MFA and Password reset for High Risk Users for All Users when All clients-v1.0 | No | No | No |
User | CAU008 | CAU008-All: Grant Require MFA for Admins when Browser and Modern Auth Clients-v1.0 | No | No | Define your own list of privileged roles in privileged_role_ids . See below for details about the default roles included. |
User | CAU009 | CAU009-AzureManagement: Grant Require MFA for Azure Management for All Users when Browser and Modern Auth Clients-v1.0 | No | No | No |
User | CAU010 | CAU010-All: Grant Require ToU for All Users when Browser and Modern Auth Clients-v1.1 | No | cau010_terms_of_use_ids |
Because of a known issue, Intune enrollment must be excluded from the terms of use policy. If your tenant are not using Intune, the service principals for Intune and Intune enrollment may not exist in the tenant. That is why we can't exclude the applications by default, and only the ones who is using Intune should set cau010_exclude_intune_enrollment to true . See under tips and tricks for details. |
User | CAU011 | CAU011-All: Block access for All users except licensed when Browser and Modern Auth Clients-v1.0 | Yes, set cau011_create to true |
Define cau011_license_group_object_ids with Azure AD group IDs to include. |
No |
Device | CAD001 | CAD001-O365: Grant macOS access for All users when Modern Auth Clients and Compliant-v1.1 | No | No | No |
Device | CAD002 | CAD002-O365: Grant Windows access for All users when Modern Auth Clients and Compliant-v1.1 | No | No | No |
Device | CAD003 | CAD003-O365: Grant iOS and Android access for All users when Modern Auth Clients and ApprovedApp or Compliant-v1.1 | No | No | No |
Device | CAD004 | CAD004-O365: Grant Require MFA for All users when Browser and Non-Compliant-v1.2 | No | No | No |
Device | CAD005 | CAD005-O365: Block access for unsupported device platforms for All users when Modern Auth Clients (and Browser)-v1.1 | No | Define supported_device_platforms with your supported device platforms. See below for details. |
Set cad005_enable_for_browser to true to also enable the policy for browsers. |
Device | CAD006 | CAD006-O365: Session block download on unmanaged device for All users when Browser and Modern App Clients and Non-Compliant-v1.6 | No | No | No |
Device | CAD007 | CAD007-O365: Session set Sign-in Frequency for Apps for All users when Modern Auth Clients and Non-Compliant-v1.3 | No | No | Defaults to 7 days, but can be configured in cad007_sign_in_frequency_in_days . |
Device | CAD008 | CAD008-All: Session set Sign-in Frequency for All users when Browser and Non-Compliant-v1.1 | No | No | Defaults to 1 day, but can be configured in cad008_sign_in_frequency_in_days . |
Device | CAD009 | CAD009-All: Session disable browser persistence for All users when Browser and Non-Compliant-v1.3 | No | No | No |
Device | CAD010 | CAD010-All: Require MFA for device join or registration when All clients-v1.0 | No | No | No |
Device | CAD011 | CAD011-O365: Grant Linux access for All users when Modern Auth Clients and Compliant-v1.0 | No | No | No |
Device | CAD012 | CAD012-All: Grant access for Admin users when Browser and Modern Auth Clients and Compliant-v1.0 | No | No | No |
Device | CAD013 | CAD013-Selected: Grant access for All users when Browser and Modern Auth Clients and Compliant-v1.0 | No | Define cad013_included_application_ids with application IDs to include. |
No |
Location | CAL001 | CAL001-All: Block specified locations for All users when Browser and Modern Auth Clients-v1.1 | No | Define cal001_blocked_location_ids with location IDs to be blocked. See below under Tips and tricks for details. |
No |
Location | CAL002 | CAL002-All: Require MFA registration from trusted locations only for All users when Browser and Modern Auth Clients-v1.2 | No | Define CIDR in trusted_locations . See below for details. |
No |
Location | CAL003 | CAL003:All: Block Access for Specified Service Accounts except from Provided Trusted Locations when Browser and Modern Auth Clients-v1.0 | No | Define CIDR in trusted_locations . See below for details. Define cal003_included_user_upns with user principal names of user that should be included. |
No |
Location | CAL004 | CAL004-All: Block access for Admins from non-trusted locations when Browser and Modern Auth Clients-v1.0 | No | Define CIDR in trusted_locations . See below for details. |
Define your own list of privileged roles in privileged_role_ids . See below for details about the default roles included. |
Location | CAL005 | CAL005-Selected: Grant access for All users on less-trusted locations when Browser and Modern Auth Clients and Compliant-v1.0 | No | Define cal005_less_trusted_location_ids with less-trusted location IDs to be included in policy. See below under Tips and tricks for details. This policy will then require compliant device, Azure AD Hybrid joined device or a approved client app from these locations. |
No |
The following changes are done compared to the recommended policies mentioned in the introduction:
Policy | Description |
---|---|
CAU002 | Excluded the Directory Synchronization Accounts role. |
CAU002 | Version 1.1 of the policy in the Excel sheet uses Require authentication strength. This is not supported in Terraform resource azuread_conditional_access_policy (GitHub issue). CAU002 created using regular "require MFA" like in version 1.0 of the policy. |
CAU006 | Fixed name of the policy, so it follows the naming standard. |
CAU007 | Fixed name of the policy, so it follows the naming standard. |
CAU008 | Added more AAD roles to the list included_roles . See below for details about the default roles included. |
CAU008 | Version 1.1 of the policy in the Excel sheet uses Require authentication strength. This is not supported in Terraform resource azuread_conditional_access_policy (GitHub issue). CAU008 created using regular "require MFA" like in version 1.0 of the policy. |
CAU009 | Version 1.1 of the policy in the Excel sheet uses Require authentication strength. This is not supported in Terraform resource azuread_conditional_access_policy (GitHub issue). CAU009 created using regular "require MFA" like in version 1.0 of the policy. |
CAU012 | Policy not created because CAL002 is the same. |
CAD004 | Version 1.3 of the policy in the Excel sheet uses Require authentication strength. This is not supported in Terraform resource azuread_conditional_access_policy (GitHub issue). CAD004 created using regular "require MFA" like in version 1.2 of the policy. |
CAD010 | client_app_types needs to bet set to all when included_user_actions = ["urn:user:registerdevice"] is set. |
CAD012 | Added more AAD roles to the list included_roles . See below for details about the default roles included. |
CAL004 | Added more AAD roles to the list included_roles . See below for details about the default roles included. |
The following privileged roles are set as default in the module:
- User Administrator
- SharePoint Administrator
- Security Administrator
- Password Administrator
- Helpdesk Administrator
- Global Administrator
- Exchange Administrator
- Conditional Access Administrator
- Billing Administrator
- Authentication Administrator
- Authentication Policy Administrator
- Azure DevOps Administrator
- Azure Information Protection Administrator
- Cloud App Security Administrator
- Cloud Application Administrator
- Cloud Device Administrator
- Domain Name Administrator
- Groups Administrator
- Intune Administrator
- Office Apps Administrator
- Privileged Authentication Administrator
- Privileged Role Administrator
- Skype for Business Administrator
- Teams Administrator
- Teams Communications Administrator
- Yammer Administrator
- Windows Update Deployment Administrator
In CAU010 you point to a Terms of Use ID in cau010_terms_of_use_ids
. The first thing you have to do is to create the terms of use.
I haven't found an easy way to find the ID of the terms of use in the Azure Portal, but one way to find the ID is to query the Graph API at GET /identityGovernance/termsOfUse/agreements
. Check the following links for details:
- Microsoft Graph Docs: Terms of use - List agreements
- Graph Explorer: GET /identityGovernance/termsOfUse/agreements
Create blocked locations with the azuread_named_location
resource in your root module, and use the ID in cal001_blocked_location_ids
and/or cal005_less_trusted_location_ids
.
If you need your own organization specific conditional access policies, you can create them in your root module with the conditional_access_policy
resource. In this way you can manage all your conditional access policies through Terraform.
Because of a known issue, Intune enrollment must be excluded from the terms of use policy.
If your tenant are not using Intune, the service principals for Intune and Intune enrollment may not exist in the tenant. That is why we can't exclude the applications by default, and only the ones who is using Intune should set cau010_exclude_intune_enrollment
to true
.
If you're missing the service principals for Intune and Intune enrollment, you may add them using the following PowerShell commands:
New-MgServicePrincipal -AppId 0000000a-0000-0000-c000-000000000000 # Microsoft Intune
New-MgServicePrincipal -AppId d4ebce55-015a-49b5-a083-c84d1797ae8c # Microsoft Intune Enrollment
Example with minimal configuration:
# ------
# BASICS
# ------
provider "azuread" {}
# -----------------------------------
# MODULE: CONDITIONAL ACCESS POLICIES
# -----------------------------------
module "default_conditional_access_policies" {
source = "robertbrandso/recommended-conditional-access-policies/azuread"
version = "1.4.1"
group_name_prefix = "Access-Contoso"
emergency_access_upn = "[email protected]"
supported_device_platforms = ["android", "iOS", "linux", "macOS", "windows"]
}
Example with more configuration:
# ------
# BASICS
# ------
provider "azuread" {}
# ---------------
# NAMED LOCATIONS
# ---------------
resource "azuread_named_location" "north_korea" {
display_name = "North Korea"
country {
countries_and_regions = ["KP"]
}
}
# -----------------------------------
# MODULE: CONDITIONAL ACCESS POLICIES
# -----------------------------------
module "default_conditional_access_policies" {
source = "robertbrandso/recommended-conditional-access-policies/azuread"
version = "1.4.1"
# Common configuration
group_name_prefix = "Access-Contoso"
emergency_access_upn = "[email protected]"
supported_device_platforms = ["android", "iOS", "linux", "macOS", "windows"]
reporting_only_for_all_policies = true
trusted_locations = [
"1.2.3.4/32", # Oslo office
"4.3.2.1/32" # Stockholm office
]
# Custom settings for user policies
cau004_included_application_ids = ["eafb53d0-2c31-45ca-91ed-0a262e9e64ec"] # Contoso ERP app
cau005_included_application_ids = ["eafb53d0-2c31-45ca-91ed-0a262e9e64ec"] # Contoso ERP app
cau010_terms_of_use_ids = ["4c4d2ee8-bcbd-469f-b850-1843912a16eb"] # Contoso Terms of use
cau010_exclude_intune_enrollment = true
# Custom settings for device policies
cad005_enable_for_browser = true
# Custom settings for location policies
cal001_blocked_location_ids = [azuread_named_location.north_korea.id]
cal003_included_user_upns = [
"[email protected]",
"[email protected]"
]
}