Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhance AAD Provider and Rego Code to automate checks for policy MS.AAD.3.3v1 #1014

Merged
merged 24 commits into from
Apr 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
611a4fb
Update provider json for auth method config
ssatyapal123 Feb 27, 2024
504393c
Added new json for MS auth feature settings
ssatyapal123 Feb 28, 2024
7e9935a
Combined authentication method calls into one json object
ssatyapal123 Mar 1, 2024
51f108c
Updates to JSON for aad 3.4 and 3.5
ssatyapal123 Mar 4, 2024
b5e7fee
updates to aad 3.3 rego
ssatyapal123 Mar 5, 2024
f0e9f83
Include all auth method configs in json export
ssatyapal123 Mar 6, 2024
18e446b
Updates to aad 3.3 to check msauth settings
ssatyapal123 Mar 14, 2024
fbcfc89
Updates to unit tests for aad 3.4
ssatyapal123 Mar 20, 2024
e2cea82
Update AADConfig.rego 3.3v1 status check
ssatyapal123 Mar 20, 2024
9fc2e00
fix N/A criticality for 3.5 and adjust unit and functional tests for …
tkol2022 Mar 25, 2024
d8e67bb
changed JSON structure for 3.4, 3.5 because it had redundant objects …
tkol2022 Mar 26, 2024
0407204
fix run unit test
Sloane4 Mar 26, 2024
761e41c
revised 3.3 unit tests
tkol2022 Mar 27, 2024
ecaab6b
update 3.3 code & added unit tests
Sloane4 Apr 2, 2024
9cc717d
refactored names and added comments to 3.3 policy
tkol2022 Apr 11, 2024
5f4368f
refactored 3.4 to reduce redundant code and bad variable naming
tkol2022 Apr 11, 2024
85d352b
streamlined code for 3.5 to reduce redundancy and returned ActualValu…
tkol2022 Apr 11, 2024
7b9ec1f
renamed MFAPolicies to PhishingResistantMFAPolicies for accuracy
tkol2022 Apr 12, 2024
4a22282
initial version 3.3 functional test wip
tkol2022 Apr 15, 2024
bb03685
added functional test cases
tkol2022 Apr 15, 2024
0978633
removed NotCheckedDetails import since linter complained
tkol2022 Apr 15, 2024
4ee500c
made AuthenticationPolicyMigrationIsComplete shorter due to linter co…
tkol2022 Apr 15, 2024
103adc2
changed AuthenticationPolicyMigrationIsComplete from boolean assignme…
tkol2022 Apr 15, 2024
2c57498
removed redundant call to Get-MgBetaPolicyAuthenticationMethodPolicy …
tkol2022 Apr 16, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 22 additions & 4 deletions PowerShell/ScubaGear/Modules/Providers/ExportAADProvider.psm1
tkol2022 marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -107,10 +107,25 @@ function Export-AADProvider {
# 5.3, 5.4
$DirectorySettings = ConvertTo-Json -Depth 10 @($Tracker.TryCommand("Get-MgBetaDirectorySetting"))

# Read the properties and relationships of an authentication method policy
$AuthenticationMethodPolicy = ConvertTo-Json @($Tracker.TryCommand("Get-MgBetaPolicyAuthenticationMethodPolicy")) -Depth 5
##### This block of code below supports 3.3, 3.4, 3.5
$AuthenticationMethodPolicyRootObject = $Tracker.TryCommand("Get-MgBetaPolicyAuthenticationMethodPolicy")

# 6.1
$AuthenticationMethodFeatureSettings = @($AuthenticationMethodPolicyRootObject.AuthenticationMethodConfigurations | Where-Object { $_.Id})

# Exclude the AuthenticationMethodConfigurations so we do not duplicate it in the JSON
$AuthenticationMethodPolicy = $AuthenticationMethodPolicyRootObject | ForEach-Object {
$_ | Select-Object * -ExcludeProperty AuthenticationMethodConfigurations
}

$AuthenticationMethodObjects = @{
authentication_method_policy = $AuthenticationMethodPolicy
authentication_method_feature_settings = $AuthenticationMethodFeatureSettings
}

$AuthenticationMethod = ConvertTo-Json -Depth 10 @($AuthenticationMethodObjects)
##### End block

# 6.1
$DomainSettings = ConvertTo-Json @($Tracker.TryCommand("Get-MgBetaDomain"))

$SuccessfulCommands = ConvertTo-Json @($Tracker.GetSuccessfulCommands())
Expand All @@ -125,7 +140,7 @@ function Export-AADProvider {
"privileged_roles": $PrivilegedRoles,
"service_plans": $ServicePlans,
"directory_settings": $DirectorySettings,
"authentication_method": $AuthenticationMethodPolicy,
"authentication_method": $AuthenticationMethod,
"domain_settings": $DomainSettings,
"license_information": $LicenseInfo,
"total_user_count": $UserCount,
Expand All @@ -136,6 +151,9 @@ function Export-AADProvider {
$json
}

#"authentication_method_policy": $AuthenticationMethodPolicy,
#"authentication_method_configuration": $AuthenticationMethodConfiguration,
#"authentication_method_feature_settings": $AuthenticationMethodFeatureSettings,
function Get-AADTenantDetail {
<#
.Description
Expand Down
135 changes: 93 additions & 42 deletions PowerShell/ScubaGear/Rego/AADConfig.rego
tkol2022 marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@
# If policy matches basic conditions, special conditions,
# all exclusions are intentional, & none but acceptable MFA
# are allowed, save the policy name
MFAPolicies contains CAPolicy.DisplayName if {
PhishingResistantMFAPolicies contains CAPolicy.DisplayName if {
some CAPolicy in input.conditional_access_policies

"All" in CAPolicy.Conditions.Users.IncludeUsers
Expand All @@ -197,23 +197,23 @@
"PolicyId": "MS.AAD.3.1v1",
"Criticality": "Shall",
"Commandlet": ["Get-MgBetaIdentityConditionalAccessPolicy"],
"ActualValue": MFAPolicies,
"ReportDetails": concat(". ", [ReportFullDetailsArray(MFAPolicies, DescriptionString), CAPLINK]),
"ActualValue": PhishingResistantMFAPolicies,
"ReportDetails": concat(". ", [ReportFullDetailsArray(PhishingResistantMFAPolicies, DescriptionString), CAPLINK]),
"RequirementMet": Status
} if {
DescriptionString := "conditional access policy(s) found that meet(s) all requirements"
Status := count(MFAPolicies) > 0
Status := count(PhishingResistantMFAPolicies) > 0
}
#--

#
# MS.AAD.3.2v1
#--

# Save all policy names if MFAPolicies exist
# Save all policy names if PhishingResistantMFAPolicies exist
AlternativeMFA contains CAPolicy.DisplayName if {
some CAPolicy in input.conditional_access_policies
Count(MFAPolicies) > 0
Count(PhishingResistantMFAPolicies) > 0
}

# If policy matches basic conditions, special conditions,
Expand Down Expand Up @@ -248,75 +248,126 @@
# MS.AAD.3.3v1
#--

# At this time we are unable to test for X because of NEW POLICY
# If we have acceptable MFA then policy passes otherwise MS Authenticator need to be
# enabled to pass. However, we can not currently check if MS Authenticator enabled
tests contains {
"PolicyId": "MS.AAD.3.3v1",
"Criticality": "Shall",
"Commandlet": ["Get-MgBetaIdentityConditionalAccessPolicy"],
"ActualValue": MFAPolicies,
"ReportDetails": concat(". ", [ReportFullDetailsArray(MFAPolicies, DescriptionString), CAPLINK]),
"RequirementMet": Status
} if {
DescriptionString := "conditional access policy(s) found that meet(s) all requirements"
Status := count(MFAPolicies) > 0
count(MFAPolicies) > 0
# Returns the MS Authenticator configuration settings
MSAuth := auth_setting if {
some auth_method in input.authentication_method
some auth_setting in auth_method.authentication_method_feature_settings

auth_setting.Id == "MicrosoftAuthenticator"
}

# Returns true if MS Authenticator is enabled, false if it is not
default MSAuthEnabled := false
MSAuthEnabled := true if {
MSAuth.State == "enabled"
}

# Returns true if MS Authenticator is configured per the baseline, false if it is not
default MSAuthProperlyConfigured := false
MSAuthProperlyConfigured := true if {
MSAuth.State == "enabled"

# Make sure that MS Auth shows the app name and geographic location
Settings := MSAuth.AdditionalProperties.featureSettings
Settings.displayAppInformationRequiredState.state == "enabled"
Settings.displayLocationInformationRequiredState.state == "enabled"

# Make sure that the configuration applies to all users
some target in MSAuth.AdditionalProperties.includeTargets
target.id == "all_users"
}

default AAD_3_3_Not_Applicable := false
# Returns true no matter what if phishing-resistant MFA is being enforced
AAD_3_3_Not_Applicable := true if {
count(PhishingResistantMFAPolicies) > 0
}

# Returns true if phishing-resistant MFA is not being enforced but MS Auth is disabled
AAD_3_3_Not_Applicable := true if {
count(PhishingResistantMFAPolicies) == 0
MSAuthEnabled == false
}

# First test is for N/A case
tests contains {
"PolicyId": PolicyId,
"Criticality": "Shall/Not-Implemented",
"Commandlet": [],
"Commandlet": ["Get-MgBetaPolicyAuthenticationMethodPolicy"],
"ActualValue": [],
"ReportDetails": NotCheckedDetails(PolicyId),
"ReportDetails": CheckedSkippedDetails(PolicyId, Reason),
"RequirementMet": false
} if {
PolicyId := "MS.AAD.3.3v1"
count(MFAPolicies) == 0
# regal ignore:line-length
Reason := "This policy is only applicable if phishing-resistant MFA is not enforced and MS Authenticator is enabled. See %v for more info"
AAD_3_3_Not_Applicable == true
}

# If policy is not N/A then we check that the configuration matches the baseline
tests contains {
"PolicyId": "MS.AAD.3.3v1",
"Criticality": "Shall",
"Commandlet": ["Get-MgBetaPolicyAuthenticationMethodPolicy"],
"ActualValue": MSAuth,
"ReportDetails": ReportDetailsBoolean(Status),
"RequirementMet": Status
} if {
AAD_3_3_Not_Applicable == false

Status := MSAuthProperlyConfigured == true
}
#--

#
# MS.AAD.3.4v1
#--

PolicyMigrationIsComplete := Status if {
some Policy in input.authentication_method
Status := Policy.PolicyMigrationState == "migrationComplete"
# Returns the auth policy migration state object
AuthenticationPolicyMigrationState := PolicyMigrationState if {
some Setting in input.authentication_method
PolicyMigrationState := Setting.authentication_method_policy.PolicyMigrationState
}

# At this time we are unable to test for X because of NEW POLICY
# Returns true if the tenant has completed their authpolicy migration
default AuthenticationPolicyMigrationIsComplete := false
AuthenticationPolicyMigrationIsComplete if AuthenticationPolicyMigrationState == "migrationComplete"

tests contains {
"PolicyId": "MS.AAD.3.4v1",
"Criticality": "Shall",
"Commandlet": ["Get-MgBetaPolicyAuthenticationMethodPolicy"],
"ActualValue": [Policy.PolicyMigrationState],
"ActualValue": [AuthenticationPolicyMigrationState],
"ReportDetails": ReportDetailsBoolean(Status),
"RequirementMet": Status
} if {
some Policy in input.authentication_method
Status := Policy.PolicyMigrationState == "migrationComplete"
Status := AuthenticationPolicyMigrationIsComplete
}
#--

#
# MS.AAD.3.5v1
#--

GoodAuthenticationMethodConfigurations contains {
# Returns all the config states for the methods Sms, Voice, Email
LowSecurityAuthMethods contains {
"Id": Configuration.Id,
"State": Configuration.State
} if {
some Item in input.authentication_method
some Configuration in Item.AuthenticationMethodConfigurations
some Setting in input.authentication_method
some Configuration in Setting.authentication_method_feature_settings
Configuration.Id in ["Sms", "Voice", "Email"]
Configuration.State == "disabled"
}

# Returns true only when all the low security auth methods are disabled per the policy
default LowSecurityAuthMethodsDisabled := false
LowSecurityAuthMethodsDisabled := true if {
every Config in LowSecurityAuthMethods { Config.State == "disabled" }
}

# First test is for N/A case
tests contains {
"PolicyId": PolicyId,
"Criticality": "Shall",
"Criticality": "Shall/Not-Implemented",
"Commandlet": ["Get-MgBetaPolicyAuthenticationMethodPolicy"],
"ActualValue": [],
"ReportDetails": CheckedSkippedDetails("MS.AAD.3.4v1", Reason),
Expand All @@ -325,21 +376,21 @@
PolicyId := "MS.AAD.3.5v1"
# regal ignore:line-length
Reason := "This policy is only applicable if the tenant has their Manage Migration feature set to Migration Complete. See %v for more info"
PolicyMigrationIsComplete != true
AuthenticationPolicyMigrationIsComplete != true
}

# If policy is not N/A then we check that the configuration matches the baseline
tests contains {
"PolicyId": "MS.AAD.3.5v1",
"Criticality": "Shall",
"Commandlet": ["Get-MgBetaPolicyAuthenticationMethodPolicy"],
"ActualValue": [],
"ActualValue": [LowSecurityAuthMethods],
"ReportDetails": ReportDetailsString(Status, ErrorMessage),
"RequirementMet": Status
} if {
ErrorMessage := "Sms, Voice, and Email authentication must be disabled."
PolicyMigrationIsComplete == true
Conditions := [PolicyMigrationIsComplete == true, count(GoodAuthenticationMethodConfigurations) == 3]
Status := count(FilterArray(Conditions, false)) == 0
AuthenticationPolicyMigrationIsComplete == true
Status := LowSecurityAuthMethodsDisabled
}
#--

Expand Down Expand Up @@ -523,12 +574,12 @@
# Return the Id if non-compliant user consent policies
BadDefaultGrantPolicies contains Policy.Id if {
some Policy in input.authorization_policies
"ManagePermissionGrantsForSelf.microsoft-user-default-legacy" in Policy.PermissionGrantPolicyIdsAssignedToDefaultUserRole

Check warning on line 577 in PowerShell/ScubaGear/Rego/AADConfig.rego

View workflow job for this annotation

GitHub Actions / Unit / OPA Unit Tests

Line too long. To learn more, see: https://docs.styra.com/regal/rules/style/line-length
}

BadDefaultGrantPolicies contains Policy.Id if {
some Policy in input.authorization_policies
"ManagePermissionGrantsForSelf.microsoft-user-default-low" in Policy.PermissionGrantPolicyIdsAssignedToDefaultUserRole

Check warning on line 582 in PowerShell/ScubaGear/Rego/AADConfig.rego

View workflow job for this annotation

GitHub Actions / Unit / OPA Unit Tests

Line too long. To learn more, see: https://docs.styra.com/regal/rules/style/line-length
}

# Return all policy Ids
Expand Down Expand Up @@ -990,7 +1041,7 @@
"ReportDetails": ReportDetailsArrayLicenseWarning(GlobalAdminsWithoutActivationAlert, DescriptionString),
"RequirementMet": Status
} if {
DescriptionString := "role(s) or group(s) without notification e-mail configured for Global Administrator activations found"

Check warning on line 1044 in PowerShell/ScubaGear/Rego/AADConfig.rego

View workflow job for this annotation

GitHub Actions / Unit / OPA Unit Tests

Line too long. To learn more, see: https://docs.styra.com/regal/rules/style/line-length
Conditions := [
count(Aad2P2Licenses) > 0,
count(GlobalAdminsWithoutActivationAlert) == 0
Expand Down Expand Up @@ -1148,4 +1199,4 @@
"ReportDetails": NotCheckedDetails("MS.AAD.8.3v1"),
"RequirementMet": false
}
#--
#--
Loading