Control: 1.2.2 Ensure that an exclusionary Geographic Access Policy is considered
Description
Conditional Access Policies can be used to block access from geographic locations that are deemed out-of-scope for your organization or application. The scope and variables for this policy should be carefully examined and defined.
Conditional Access, when used as a deny list for the tenant or subscription, is able to prevent ingress or egress of traffic to countries that are outside of the scope of interest (e.g.: customers, suppliers) or jurisdiction of an organization. This is an effective way to prevent unnecessary and long-lasting exposure to international threats such as APTs.
Remediation
From Azure Portal
Part 1 of 2 - Create the policy and enable it in Report-only mode.
- From Azure Home open the portal menu in the top left, and select Azure Active Directory.
- Scroll down in the menu on the left, and select Security.
- Select on the left side Conditional Access.
- Click the + New policybutton, then:
- Provide a name for the policy.
- Under Assignments, selectUsers or work load identitiesthen:- Under Include, selectAll users
- Under Exclude, check Users and groups and only select emergency access accounts and service accounts (NOTE: Service accounts are excluded here because service accounts are non-interactive and cannot complete MFA)
 
- Under 
- Under Assignments, selectCloud apps or actionsthen:- Under Include, selectAll cloud apps
- Leave Excludeblank unless you have a well defined exception.
 
- Under 
- Under Conditions, selectLocationsthen:- Select Include, then add entries for locations for those that should be blocked.
- Select Exclude, then add entries for those that should be allowed (IMPORTANT: Ensure that all Trusted Locations are in theExcludelist.)
 
- Select 
- Under Access Controls, selectGrantand Confirm thatBlock Accessis selected.
- Set Enable policytoReport-only.
- Click Create.
NOTE: The policy is not yet 'live,' since Report-only is being used to audit the effect of the policy.
Part 2 of 2 - Confirm that the policy is not blocking access that should be granted, then toggle to On.
- With your policy now in report-only mode, return to the Azure Active Directory blade and click on Sign-in logs.
- Review the recent sign-in events - click an event then review the event details (specifically the Report-onlytab) to ensure:- The sign-in event you're reviewing occurred after turning on the policy in report-only mode.
- The policy name from step 5 above is listed in the Policy Namecolumn.
- The Resultcolumn for the new policy shows that the policy wasNot applied(indicating the location origin was not blocked).
 
- If the above conditions are present, navigate back to the policy name in Conditional Access and open it.
- Toggle the policy from Report-onlytoOn.
- Click Save.
From PowerShell
First, set up the conditions objects values before updating an existing conditional access policy or before creating a new one. You may need to use additional PowerShell cmdlets to retrieve specific IDs such as the Get-AzureADMSNamedLocationPolicy which outputs the Location IDs for use with conditional access policies.
$conditions = New-Object -TypeName Microsoft.Open.MSGraph.Model.ConditionalAccessConditionSet
$conditions.Applications = New-Object -TypeName Microsoft.Open.MSGraph.Model.ConditionalAccessApplicationCondition $conditions.Applications.IncludeApplications = <"All" | "Office365" | "app ID" | @("app ID 1", "app ID 2", etc...> $conditions.Applications.ExcludeApplications = <"Office365" | "app ID" | @("app ID 1", "app ID 2", etc...)>
$conditions.Users = New-Object -TypeName Microsoft.Open.MSGraph.Model.ConditionalAccessUserCondition $conditions.Users.IncludeUsers = <"All" | "None" | "GuestsOrExternalUsers" | "Specific User ID" | @("User ID 1", "User ID 2", etc.)> $conditions.Users.ExcludeUsers = <"GuestsOrExternalUsers" | "Specific User ID" | @("User ID 1", "User ID 2", etc.)>$conditions.Users.IncludeGroups = <"group ID" | "All" | @("Group ID 1", "Group ID 2", etc...)>$conditions.Users.ExcludeGroups = <"group ID" | @("Group ID 1", "Group ID 2", etc...)>$conditions.Users.IncludeRoles = <"Role ID" | "All" | @("Role ID 1", "Role ID 2", etc...)>$conditions.Users.ExcludeRoles = <"Role ID" | @("Role ID 1", "Role ID 2", etc...)>
$conditions.Locations = New-Object -TypeName Microsoft.Open.MSGraph.Model.ConditionalAccessLocationCondition $conditions.Locations.IncludeLocations = <"Location ID" | @("Location ID 1", "Location ID 2", etc...) >$conditions.Locations.ExcludeLocations = <"AllTrusted" | "Location ID" | @("Location ID 1", "Location ID 2", etc...)>
$controls = New-Object -TypeName Microsoft.Open.MSGraph.Model.ConditionalAccessGrantControls $controls._Operator = "OR"$controls.BuiltInControls = "block"
Next, update the existing conditional access policy with the condition set options configured with the previous commands.
Set-AzureADMSConditionalAccessPolicy -PolicyId <policy ID> -Conditions $conditions -GrantControls $controls
To create a new conditional access policy that complies with this best practice, run the following commands after creating the condition set above
New-AzureADMSConditionalAccessPolicy -Name "Policy Name" -State <enabled|disabled> -Conditions $conditions -GrantControls $controls
Default Value
This policy does not exist by default.
Usage
Run the control in your terminal:
powerpipe control run azure_compliance.control.cis_v200_1_2_2Snapshot and share results via Turbot Pipes:
powerpipe loginpowerpipe control run azure_compliance.control.cis_v200_1_2_2 --shareSQL
This control uses a named query:
select  'active_directory' as resource,  'info' as status,  'Manual verification required.' as reason;