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 policy
button, then: - Provide a name for the policy.
- Under
Assignments
, selectUsers or work load identities
then:- 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 actions
then:- Under
Include
, selectAll cloud apps
- Leave
Exclude
blank unless you have a well defined exception.
- Under
- Under
Conditions
, selectLocations
then:- 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 theExclude
list.)
- Select
- Under
Access Controls
, selectGrant
and Confirm thatBlock Access
is selected. - Set
Enable policy
toReport-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-only
tab) 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 Name
column. - The
Result
column 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-only
toOn
. - 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_2
Snapshot and share results via Turbot Pipes:
powerpipe loginpowerpipe control run azure_compliance.control.cis_v200_1_2_2 --share
SQL
This control uses a named query:
ad_manual_control