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;