diff --git a/PowerShell/ScubaGear/Modules/Providers/ExportAADProvider.psm1 b/PowerShell/ScubaGear/Modules/Providers/ExportAADProvider.psm1 index e42f408a1..86d61b614 100644 --- a/PowerShell/ScubaGear/Modules/Providers/ExportAADProvider.psm1 +++ b/PowerShell/ScubaGear/Modules/Providers/ExportAADProvider.psm1 @@ -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()) @@ -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, @@ -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 diff --git a/PowerShell/ScubaGear/Rego/AADConfig.rego b/PowerShell/ScubaGear/Rego/AADConfig.rego index 4bab4bf16..c633cda2f 100644 --- a/PowerShell/ScubaGear/Rego/AADConfig.rego +++ b/PowerShell/ScubaGear/Rego/AADConfig.rego @@ -178,7 +178,7 @@ tests contains { # 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 @@ -197,12 +197,12 @@ tests contains { "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 } #-- @@ -210,10 +210,10 @@ tests contains { # 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, @@ -248,55 +248,99 @@ tests contains { # 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 } #-- @@ -304,19 +348,26 @@ tests contains { # 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), @@ -325,21 +376,21 @@ tests contains { 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 } #-- @@ -1148,4 +1199,4 @@ tests contains { "ReportDetails": NotCheckedDetails("MS.AAD.8.3v1"), "RequirementMet": false } -#-- \ No newline at end of file +#-- diff --git a/PowerShell/ScubaGear/Testing/Unit/Rego/AAD/AADConfig_03_test.rego b/PowerShell/ScubaGear/Testing/Unit/Rego/AAD/AADConfig_03_test.rego index 83569a90c..d81af2c8b 100644 --- a/PowerShell/ScubaGear/Testing/Unit/Rego/AAD/AADConfig_03_test.rego +++ b/PowerShell/ScubaGear/Testing/Unit/Rego/AAD/AADConfig_03_test.rego @@ -1,7 +1,6 @@ package aad_test import rego.v1 import data.aad -import data.utils.report.NotCheckedDetails import data.utils.report.CheckedSkippedDetails import data.utils.key.TestResult import data.utils.key.TestResultContains @@ -1584,7 +1583,7 @@ test_State_Incorrect_V1 if { # # Policy MS.AAD.3.3v1 #-- -test_3_1_passes_and_satisfies_3_3 if{ +test_PhishingMFAEnforced_MicrosoftAuthEnabled_NotApplicable if { Output := aad.tests with input as { "conditional_access_policies": [ { @@ -1614,130 +1613,385 @@ test_3_1_passes_and_satisfies_3_3 if{ } }, "State": "enabled", - "DisplayName": "Test Policy" + "DisplayName": "Phishing Resistant MFA Enforced" + } + ], + "authentication_method": [ + { + "authentication_method_feature_settings": [ + { + "Id": "MicrosoftAuthenticator", + "State": "enabled" + }, + { + "Id": "Email", + "State": "enabled" + } + ] } ] } - ReportDetailStr := concat("", [ - "1 conditional access policy(s) found that meet(s) all requirements:", - "
Test Policy. View all CA policies." - ]) - - TestResult("MS.AAD.3.3v1", Output, ReportDetailStr, true) == true -} - -test_NotImplemented_Correct_V2 if { PolicyId := "MS.AAD.3.3v1" - - Output := aad.tests with input as { } - - ReportDetailStr := NotCheckedDetails(PolicyId) - TestResult(PolicyId, Output, ReportDetailStr, false) == true + ReportDetailStr := "This policy is only applicable if phishing-resistant MFA is not enforced and MS Authenticator is enabled. See %v for more info" + TestResult(PolicyId, Output, CheckedSkippedDetails(PolicyId, ReportDetailStr), false) == true } -#-- -# -# Policy MS.AAD.3.4v1 -#-- -test_Migrated_Correct if { +test_PhishingMFAEnforced_MicrosoftAuthDisabled_NotApplicable if { Output := aad.tests with input as { + "conditional_access_policies": [ + { + "Conditions": { + "Applications": { + "IncludeApplications": [ + "All" + ], + "ExcludeApplications": [] + }, + "Users": { + "IncludeUsers": [ + "All" + ], + "ExcludeUsers": [], + "ExcludeGroups": [], + "ExcludeRoles": [] + } + }, + "GrantControls": { + "AuthenticationStrength": { + "AllowedCombinations": [ + "windowsHelloForBusiness", + "fido2", + "x509CertificateMultiFactor" + ] + } + }, + "State": "enabled", + "DisplayName": "Phishing Resistant MFA Enforced" + } + ], "authentication_method": [ { - "PolicyMigrationState": "migrationComplete" + "authentication_method_feature_settings": [ + { + "Id": "MicrosoftAuthenticator", + "State": "disabled" + }, + { + "Id": "Email", + "State": "enabled" + } + ] } ] } - TestResult("MS.AAD.3.4v1", Output, PASS, true) == true + PolicyId := "MS.AAD.3.3v1" + ReportDetailStr := "This policy is only applicable if phishing-resistant MFA is not enforced and MS Authenticator is enabled. See %v for more info" + TestResult(PolicyId, Output, CheckedSkippedDetails(PolicyId, ReportDetailStr), false) == true } -test_Migrated_Incorrect if { +test_PhishingMFANotEnforced_MicrosoftAuthDisabled_NotApplicable if { Output := aad.tests with input as { + "conditional_access_policies": [ + { + "Conditions": { + "Applications": { + "IncludeApplications": [ + "All" + ], + "ExcludeApplications": [] + }, + "Users": { + "IncludeUsers": [ + "All" + ], + "ExcludeUsers": [], + "ExcludeGroups": [], + "ExcludeRoles": [] + } + }, + "GrantControls": { + "BuiltInControls": [ + "mfa" + ] + }, + "State": "enabled", + "DisplayName": "Vanilla MFA Enforced - not phishing-resistant" + } + ], "authentication_method": [ { - "PolicyMigrationState": "preMigration" + "authentication_method_feature_settings": [ + { + "Id": "MicrosoftAuthenticator", + "State": "disabled" + }, + { + "Id": "Email", + "State": "enabled" + } + ] } ] } - TestResult("MS.AAD.3.4v1", Output, FAIL, false) == true + PolicyId := "MS.AAD.3.3v1" + ReportDetailStr := "This policy is only applicable if phishing-resistant MFA is not enforced and MS Authenticator is enabled. See %v for more info" + TestResult(PolicyId, Output, CheckedSkippedDetails(PolicyId, ReportDetailStr), false) == true } -#-- - -# -# Policy MS.AAD.3.5v1 -#-- -test_NotImplemented_Incorrect_Sms if { +test_PhishingMFANotEnforced_MicrosoftAuthEnabled_Correct if { Output := aad.tests with input as { - "authentication_method": [ + "conditional_access_policies": [ { - "PolicyMigrationState": "migrationComplete", - "AuthenticationMethodConfigurations": [ - { - "Id": "Sms", - "State": "enabled" + "Conditions": { + "Applications": { + "IncludeApplications": [ + "All" + ], + "ExcludeApplications": [] }, + "Users": { + "IncludeUsers": [ + "All" + ], + "ExcludeUsers": [], + "ExcludeGroups": [], + "ExcludeRoles": [] + } + }, + "GrantControls": { + "BuiltInControls": [ + "mfa" + ] + }, + "State": "enabled", + "DisplayName": "Vanilla MFA Enforced - not phishing-resistant" + } + ], + "authentication_method": [ + { + "authentication_method_feature_settings": [ { - "Id": "Voice", - "State": "disabled" + "ExcludeTargets": [ + + ], + "Id": "MicrosoftAuthenticator", + "State": "enabled", + "AdditionalProperties": { + "@odata.type": "#microsoft.graph.microsoftAuthenticatorAuthenticationMethodConfiguration", + "isSoftwareOathEnabled": false, + "featureSettings": { + "displayAppInformationRequiredState": { + "state": "enabled", + "includeTarget": { + "targetType": "group", + "id": "all_users" + }, + "excludeTarget": { + "targetType": "group", + "id": "00000000-0000-0000-0000-000000000000" + } + }, + "displayLocationInformationRequiredState": { + "state": "enabled", + "includeTarget": { + "targetType": "group", + "id": "all_users" + }, + "excludeTarget": { + "targetType": "group", + "id": "00000000-0000-0000-0000-000000000000" + } + } + }, + "includeTargets@odata.context": "https://graph.microsoft.com/beta/$metadata#policies/authenticationMethodsPolicy/authenticationMethodConfigurations(\u0027MicrosoftAuthenticator\u0027)/microsoft.graph.microsoftAuthenticatorAuthenticationMethodConfiguration/includeTargets", + "includeTargets": [ + { + "targetType": "group", + "id": "all_users", + "isRegistrationRequired": false, + "authenticationMode": "any" + } + ] + } }, { "Id": "Email", - "State": "disabled" + "State": "enabled" } ] } ] } - ReportDetails := "Sms, Voice, and Email authentication must be disabled." - TestResult("MS.AAD.3.5v1", Output, ReportDetails, false) == true + TestResult("MS.AAD.3.3v1", Output, PASS, true) == true } -test_NotImplemented_Incorrect_Voice if { - +test_PhishingMFANotEnforced_MicrosoftAuthEnabled_AppnameDisabled_Incorrect if { Output := aad.tests with input as { - "authentication_method": [ + "conditional_access_policies": [ { - "PolicyMigrationState": "migrationComplete", - "AuthenticationMethodConfigurations": [ - { - "Id": "Sms", - "State": "disabled" + "Conditions": { + "Applications": { + "IncludeApplications": [ + "All" + ], + "ExcludeApplications": [] }, + "Users": { + "IncludeUsers": [ + "All" + ], + "ExcludeUsers": [], + "ExcludeGroups": [], + "ExcludeRoles": [] + } + }, + "GrantControls": { + "BuiltInControls": [ + "mfa" + ] + }, + "State": "enabled", + "DisplayName": "Vanilla MFA Enforced - not phishing-resistant" + } + ], + "authentication_method": [ + { + "authentication_method_feature_settings": [ { - "Id": "Voice", - "State": "enabled" + "ExcludeTargets": [ + + ], + "Id": "MicrosoftAuthenticator", + "State": "enabled", + "AdditionalProperties": { + "@odata.type": "#microsoft.graph.microsoftAuthenticatorAuthenticationMethodConfiguration", + "isSoftwareOathEnabled": false, + "featureSettings": { + "displayAppInformationRequiredState": { + "state": "disabled", + "includeTarget": { + "targetType": "group", + "id": "all_users" + }, + "excludeTarget": { + "targetType": "group", + "id": "00000000-0000-0000-0000-000000000000" + } + }, + "displayLocationInformationRequiredState": { + "state": "enabled", + "includeTarget": { + "targetType": "group", + "id": "all_users" + }, + "excludeTarget": { + "targetType": "group", + "id": "00000000-0000-0000-0000-000000000000" + } + } + }, + "includeTargets@odata.context": "https://graph.microsoft.com/beta/$metadata#policies/authenticationMethodsPolicy/authenticationMethodConfigurations(\u0027MicrosoftAuthenticator\u0027)/microsoft.graph.microsoftAuthenticatorAuthenticationMethodConfiguration/includeTargets", + "includeTargets": [ + { + "targetType": "group", + "id": "all_users", + "isRegistrationRequired": false, + "authenticationMode": "any" + } + ] + } }, { "Id": "Email", - "State": "disabled" + "State": "enabled" } ] } ] } - ReportDetails := "Sms, Voice, and Email authentication must be disabled." - TestResult("MS.AAD.3.5v1", Output, ReportDetails, false) == true + TestResult("MS.AAD.3.3v1", Output, FAIL, false) == true } -test_NotImplemented_Incorrect_Email if { - +test_PhishingMFANotEnforced_MicrosoftAuthEnabled_GeolocationDisabled_Incorrect if { Output := aad.tests with input as { - "authentication_method": [ + "conditional_access_policies": [ { - "PolicyMigrationState": "migrationComplete", - "AuthenticationMethodConfigurations": [ - { - "Id": "Sms", - "State": "disabled" + "Conditions": { + "Applications": { + "IncludeApplications": [ + "All" + ], + "ExcludeApplications": [] }, + "Users": { + "IncludeUsers": [ + "All" + ], + "ExcludeUsers": [], + "ExcludeGroups": [], + "ExcludeRoles": [] + } + }, + "GrantControls": { + "BuiltInControls": [ + "mfa" + ] + }, + "State": "enabled", + "DisplayName": "Vanilla MFA Enforced - not phishing-resistant" + } + ], + "authentication_method": [ + { + "authentication_method_feature_settings": [ { - "Id": "Voice", - "State": "disabled" + "ExcludeTargets": [ + + ], + "Id": "MicrosoftAuthenticator", + "State": "enabled", + "AdditionalProperties": { + "@odata.type": "#microsoft.graph.microsoftAuthenticatorAuthenticationMethodConfiguration", + "isSoftwareOathEnabled": false, + "featureSettings": { + "displayAppInformationRequiredState": { + "state": "enabled", + "includeTarget": { + "targetType": "group", + "id": "all_users" + }, + "excludeTarget": { + "targetType": "group", + "id": "00000000-0000-0000-0000-000000000000" + } + }, + "displayLocationInformationRequiredState": { + "state": "disabled", + "includeTarget": { + "targetType": "group", + "id": "all_users" + }, + "excludeTarget": { + "targetType": "group", + "id": "00000000-0000-0000-0000-000000000000" + } + } + }, + "includeTargets@odata.context": "https://graph.microsoft.com/beta/$metadata#policies/authenticationMethodsPolicy/authenticationMethodConfigurations(\u0027MicrosoftAuthenticator\u0027)/microsoft.graph.microsoftAuthenticatorAuthenticationMethodConfiguration/includeTargets", + "includeTargets": [ + { + "targetType": "group", + "id": "all_users", + "isRegistrationRequired": false, + "authenticationMode": "any" + } + ] + } }, { "Id": "Email", @@ -1748,59 +2002,446 @@ test_NotImplemented_Incorrect_Email if { ] } - ReportDetails := "Sms, Voice, and Email authentication must be disabled." - TestResult("MS.AAD.3.5v1", Output, ReportDetails, false) == true + TestResult("MS.AAD.3.3v1", Output, FAIL, false) == true } -test_NotImplemented_Incorrect_Migration if { - +test_PhishingMFANotEnforced_MicrosoftAuthEnabled_AppNameDisabled_GeolocationDisabled_Incorrect if { Output := aad.tests with input as { + "conditional_access_policies": [ + { + "Conditions": { + "Applications": { + "IncludeApplications": [ + "All" + ], + "ExcludeApplications": [] + }, + "Users": { + "IncludeUsers": [ + "All" + ], + "ExcludeUsers": [], + "ExcludeGroups": [], + "ExcludeRoles": [] + } + }, + "GrantControls": { + "BuiltInControls": [ + "mfa" + ] + }, + "State": "enabled", + "DisplayName": "Vanilla MFA Enforced - not phishing-resistant" + } + ], "authentication_method": [ { - "PolicyMigrationState": "preMigration", - "AuthenticationMethodConfigurations": [ + "authentication_method_feature_settings": [ + { + "ExcludeTargets": [ + + ], + "Id": "MicrosoftAuthenticator", + "State": "enabled", + "AdditionalProperties": { + "@odata.type": "#microsoft.graph.microsoftAuthenticatorAuthenticationMethodConfiguration", + "isSoftwareOathEnabled": false, + "featureSettings": { + "displayAppInformationRequiredState": { + "state": "disabled", + "includeTarget": { + "targetType": "group", + "id": "all_users" + }, + "excludeTarget": { + "targetType": "group", + "id": "00000000-0000-0000-0000-000000000000" + } + }, + "displayLocationInformationRequiredState": { + "state": "disabled", + "includeTarget": { + "targetType": "group", + "id": "all_users" + }, + "excludeTarget": { + "targetType": "group", + "id": "00000000-0000-0000-0000-000000000000" + } + } + }, + "includeTargets@odata.context": "https://graph.microsoft.com/beta/$metadata#policies/authenticationMethodsPolicy/authenticationMethodConfigurations(\u0027MicrosoftAuthenticator\u0027)/microsoft.graph.microsoftAuthenticatorAuthenticationMethodConfiguration/includeTargets", + "includeTargets": [ + { + "targetType": "group", + "id": "all_users", + "isRegistrationRequired": false, + "authenticationMode": "any" + } + ] + } + }, { - "Id": "Sms", + "Id": "Email", "State": "enabled" + } + ] + } + ] + } + + TestResult("MS.AAD.3.3v1", Output, FAIL, false) == true +} + +test_PhishingMFANotEnforced_MicrosoftAuthEnabled_includeTargetsNotAll_Incorrect if { + Output := aad.tests with input as { + "conditional_access_policies": [ + { + "Conditions": { + "Applications": { + "IncludeApplications": [ + "All" + ], + "ExcludeApplications": [] }, + "Users": { + "IncludeUsers": [ + "All" + ], + "ExcludeUsers": [], + "ExcludeGroups": [], + "ExcludeRoles": [] + } + }, + "GrantControls": { + "BuiltInControls": [ + "mfa" + ] + }, + "State": "enabled", + "DisplayName": "Vanilla MFA Enforced - not phishing-resistant" + } + ], + "authentication_method": [ + { + "authentication_method_feature_settings": [ { - "Id": "Voice", - "State": "disabled" + "ExcludeTargets": [ + + ], + "Id": "MicrosoftAuthenticator", + "State": "enabled", + "AdditionalProperties": { + "@odata.type": "#microsoft.graph.microsoftAuthenticatorAuthenticationMethodConfiguration", + "isSoftwareOathEnabled": false, + "featureSettings": { + "displayAppInformationRequiredState": { + "state": "enabled", + "includeTarget": { + "targetType": "group", + "id": "all_users" + }, + "excludeTarget": { + "targetType": "group", + "id": "00000000-0000-0000-0000-000000000000" + } + }, + "displayLocationInformationRequiredState": { + "state": "enabled", + "includeTarget": { + "targetType": "group", + "id": "all_users" + }, + "excludeTarget": { + "targetType": "group", + "id": "00000000-0000-0000-0000-000000000000" + } + } + }, + "includeTargets@odata.context": "https://graph.microsoft.com/beta/$metadata#policies/authenticationMethodsPolicy/authenticationMethodConfigurations(\u0027MicrosoftAuthenticator\u0027)/microsoft.graph.microsoftAuthenticatorAuthenticationMethodConfiguration/includeTargets", + "includeTargets": [ + { + "targetType": "group", + "id": "not_all_users", + "isRegistrationRequired": false, + "authenticationMode": "any" + } + ] + } }, { "Id": "Email", - "State": "disabled" + "State": "enabled" } ] } ] } + TestResult("MS.AAD.3.3v1", Output, FAIL, false) == true +} + +#-- + +# +# Policy MS.AAD.3.4v1 +#-- +test_PolicyMigrationState_Correct if { + Output := aad.tests with input as { + "authentication_method": [ + { + "authentication_method_policy": { + "PolicyMigrationState": "migrationComplete" + } + } + ] + } + + TestResult("MS.AAD.3.4v1", Output, PASS, true) == true +} + +test_PolicyMigrationState_preMigration_Incorrect if { + Output := aad.tests with input as { + "authentication_method": [ + { + "authentication_method_policy": { + "PolicyMigrationState": "preMigration" + } + } + ] + } + + TestResult("MS.AAD.3.4v1", Output, FAIL, false) == true +} + +test_PolicyMigrationState_migrationInProgress_Incorrect if { + Output := aad.tests with input as { + "authentication_method": [ + { + "authentication_method_policy": { + "PolicyMigrationState": "migrationInProgress" + } + } + ] + } + + TestResult("MS.AAD.3.4v1", Output, FAIL, false) == true +} +#-- + +# +# Policy MS.AAD.3.5v1 +#-- +test_LowSecurityAuthMethods_SmsEnabled_Incorrect if { + + Output := aad.tests with input as { + "authentication_method": [ + { + "authentication_method_feature_settings": [ + { + "Id": "Sms", + "State": "enabled" + }, + { + "Id": "Voice", + "State": "disabled" + }, + { + "Id": "Email", + "State": "disabled" + } + ], + + "authentication_method_policy": { + "PolicyMigrationState": "migrationComplete" + } + } + ] + } + + ReportDetails := "Sms, Voice, and Email authentication must be disabled." + TestResult("MS.AAD.3.5v1", Output, ReportDetails, false) == true +} + +test_LowSecurityAuthMethods_VoiceEnabled_Incorrect if { + + Output := aad.tests with input as { + "authentication_method": [ + { + "authentication_method_feature_settings": [ + { + "Id": "Sms", + "State": "disabled" + }, + { + "Id": "Voice", + "State": "enabled" + }, + { + "Id": "Email", + "State": "disabled" + } + ], + + "authentication_method_policy": { + "PolicyMigrationState": "migrationComplete" + } + } + ] + } + + ReportDetails := "Sms, Voice, and Email authentication must be disabled." + TestResult("MS.AAD.3.5v1", Output, ReportDetails, false) == true +} + +test_LowSecurityAuthMethods_EmailEnabled_Incorrect if { + + Output := aad.tests with input as { + "authentication_method": [ + { + "authentication_method_feature_settings": [ + { + "Id": "Sms", + "State": "disabled" + }, + { + "Id": "Voice", + "State": "disabled" + }, + { + "Id": "Email", + "State": "enabled" + } + ], + + "authentication_method_policy": { + "PolicyMigrationState": "migrationComplete" + } + } + ] + } + + ReportDetails := "Sms, Voice, and Email authentication must be disabled." + TestResult("MS.AAD.3.5v1", Output, ReportDetails, false) == true +} + +test_LowSecurityAuthMethods_TwoMethodsEnabled_Incorrect if { + + Output := aad.tests with input as { + "authentication_method": [ + { + "authentication_method_feature_settings": [ + { + "Id": "Sms", + "State": "enabled" + }, + { + "Id": "Voice", + "State": "enabled" + }, + { + "Id": "Email", + "State": "disabled" + } + ], + + "authentication_method_policy": { + "PolicyMigrationState": "migrationComplete" + } + } + ] + } + + ReportDetails := "Sms, Voice, and Email authentication must be disabled." + TestResult("MS.AAD.3.5v1", Output, ReportDetails, false) == true +} + +test_LowSecurityAuthMethods_AllMethodsEnabled_Incorrect if { + + Output := aad.tests with input as { + "authentication_method": [ + { + "authentication_method_feature_settings": [ + { + "Id": "Sms", + "State": "enabled" + }, + { + "Id": "Voice", + "State": "enabled" + }, + { + "Id": "Email", + "State": "enabled" + } + ], + + "authentication_method_policy": { + "PolicyMigrationState": "migrationComplete" + } + } + ] + } + + ReportDetails := "Sms, Voice, and Email authentication must be disabled." + TestResult("MS.AAD.3.5v1", Output, ReportDetails, false) == true +} + +test_LowSecurityAuthMethods_PreMigration_NotImplemented if { + + Output := aad.tests with input as { + "authentication_method": [ + { + "authentication_method_feature_settings": [ + { + "Id": "Sms", + "State": "enabled" + }, + { + "Id": "Voice", + "State": "disabled" + }, + { + "Id": "Email", + "State": "disabled" + } + ], + + "authentication_method_policy": { + "PolicyMigrationState": "preMigration" + } + } + ] + } + # 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" TestResult("MS.AAD.3.5v1", Output, CheckedSkippedDetails("MS.AAD.3.4v1", Reason), false) == true } -test_NotImplemented_Correct_V4 if { +test_LowSecurityAuthMethods_MigrationComplete_Correct if { Output := aad.tests with input as { "authentication_method": [ { - "PolicyMigrationState": "migrationComplete", - "AuthenticationMethodConfigurations": [ - { - "Id": "Sms", - "State": "disabled" - }, - { - "Id": "Voice", - "State": "disabled" - }, - { - "Id": "Email", - "State": "disabled" - } - ] + "authentication_method_feature_settings": [ + { + "Id": "Sms", + "State": "disabled" + }, + { + "Id": "Voice", + "State": "disabled" + }, + { + "Id": "Email", + "State": "disabled" + } + ], + + "authentication_method_policy": { + "PolicyMigrationState": "migrationComplete" + } } ] } diff --git a/Testing/Functional/Products/Products.Tests.ps1 b/Testing/Functional/Products/Products.Tests.ps1 index 5629a2f5e..b96edfd69 100644 --- a/Testing/Functional/Products/Products.Tests.ps1 +++ b/Testing/Functional/Products/Products.Tests.ps1 @@ -284,10 +284,6 @@ Describe "Policy Checks for "{ $Details = $PolicyResultObj.ReportDetails $Details | Should -Not -BeNullOrEmpty -Because "expect details, $Details" - if ($IsNotChecked){ - $Details | Should -Match 'This product does not currently have the capability to check compliance for this policy.+' - } - if ($IsCustomImplementation){ $Details | Should -Match 'A custom product can be used to fulfill this policy requirement.+' } @@ -360,8 +356,7 @@ Describe "Policy Checks for "{ $RowData[4].text | Should -Match 'A custom product can be used to fulfill this policy requirement.+' } elseif ($IsNotChecked){ - $RowData[2].text | Should -BeLikeExactly "N/A" -Because "custom policies should not have results. [$Msg]" - $RowData[4].text | Should -Match 'This product does not currently have the capability to check compliance for this policy.+' + $RowData[2].text | Should -BeLikeExactly "N/A" -Because "policies that are not checked should be N/A. [$Msg]" } elseif ($true -eq $ExpectedResult) { $RowData[2].text | Should -BeLikeExactly "Pass" -Because "expected policy to pass. [$Msg]" diff --git a/Testing/Functional/Products/TestPlans/aad.testplan.yaml b/Testing/Functional/Products/TestPlans/aad.testplan.yaml index 61f2ebe36..524a70a7b 100644 --- a/Testing/Functional/Products/TestPlans/aad.testplan.yaml +++ b/Testing/Functional/Products/TestPlans/aad.testplan.yaml @@ -198,13 +198,102 @@ TestPlan: ExpectedResult: true - PolicyId: MS.AAD.3.3v1 - TestDriver: RunScuba + TestDriver: RunCached Tests: - - TestDescription: MS.AAD.3.3v1 Not Checked - Preconditions: [] + - TestDescription: MS.AAD.3.3v1 Not-applicable case - PhishingMFA Enforced MS Auth Enabled + Preconditions: + - Command: UpdateCachedConditionalAccessPolicyByName + Splat: + displayName: Automated Test 1 - DO NOT MODIFY + updates: + State: enabled + Conditions: + Users: + IncludeUsers: ["All"] + ExcludeUsers: [] + IncludeGroups: [] + ExcludeGroups: [] + IncludeRoles: [] + ExcludeRoles: [] + Applications: + IncludeApplications: ["All"] + ExcludeApplications: [] + GrantControls.AuthenticationStrength.AllowedCombinations: + - "windowsHelloForBusiness" + - "fido2" + - "x509CertificateMultiFactor" + - Command: UpdateProviderExport + Splat: + updates: + authentication_method[0].authentication_method_feature_settings: + - Id: MicrosoftAuthenticator + State: enabled + AdditionalProperties: + featureSettings: + displayAppInformationRequiredState: + state: disabled + displayLocationInformationRequiredState: + state: disabled + includeTargets: + - id: "all_users" Postconditions: [] IsNotChecked: true ExpectedResult: false + - TestDescription: MS.AAD.3.3v1 Not-applicable case - PhishingMFA Not Enforced MS Auth Disabled + Preconditions: + - Command: UpdateProviderExport + Splat: + updates: + authentication_method[0].authentication_method_feature_settings: + - Id: MicrosoftAuthenticator + State: disabled + AdditionalProperties: + featureSettings: + displayAppInformationRequiredState: + state: disabled + displayLocationInformationRequiredState: + state: disabled + includeTargets: + - id: "all_users" + Postconditions: [] + IsNotChecked: true + ExpectedResult: false + - TestDescription: MS.AAD.3.3v1 Non-Compliant case - MS Auth App name and Geolocation disabled + Preconditions: + - Command: UpdateProviderExport + Splat: + updates: + authentication_method[0].authentication_method_feature_settings: + - Id: MicrosoftAuthenticator + State: enabled + AdditionalProperties: + featureSettings: + displayAppInformationRequiredState: + state: disabled + displayLocationInformationRequiredState: + state: disabled + includeTargets: + - id: "all_users" + Postconditions: [] + ExpectedResult: false + - TestDescription: MS.AAD.3.3v1 Compliant case - MS Auth Configured Correctly + Preconditions: + - Command: UpdateProviderExport + Splat: + updates: + authentication_method[0].authentication_method_feature_settings: + - Id: MicrosoftAuthenticator + State: enabled + AdditionalProperties: + featureSettings: + displayAppInformationRequiredState: + state: enabled + displayLocationInformationRequiredState: + state: enabled + includeTargets: + - id: "all_users" + Postconditions: [] + ExpectedResult: true - PolicyId: MS.AAD.3.4v1 TestDriver: RunCached @@ -214,7 +303,7 @@ TestPlan: - Command: UpdateProviderExport Splat: updates: - authentication_method[0].PolicyMigrationState: preMigration + authentication_method[0].authentication_method_policy.PolicyMigrationState: preMigration Postconditions: [] ExpectedResult: false - TestDescription: MS.AAD.3.4v1 Compliant case - Migration complete @@ -222,28 +311,36 @@ TestPlan: - Command: UpdateProviderExport Splat: updates: - authentication_method[0].PolicyMigrationState: migrationComplete + authentication_method[0].authentication_method_policy.PolicyMigrationState: migrationComplete Postconditions: [] ExpectedResult: true - PolicyId: MS.AAD.3.5v1 TestDriver: RunCached Tests: - - TestDescription: MS.AAD.3.5v1 Non-compliant case - preMigration + - TestDescription: MS.AAD.3.5v1 Not-applicable case - preMigration but auth methods disabled Preconditions: - Command: UpdateProviderExport Splat: updates: - authentication_method[0].PolicyMigrationState: preMigration + authentication_method[0].authentication_method_policy.PolicyMigrationState: preMigration + authentication_method[0].authentication_method_feature_settings: + - Id: Sms + State: disabled + - Id: Voice + State: disabled + - Id: Email + State: disabled Postconditions: [] + IsNotChecked: true ExpectedResult: false - TestDescription: MS.AAD.3.5v1 Non-compliant case - Sms enabled Preconditions: - Command: UpdateProviderExport Splat: updates: - authentication_method[0].PolicyMigrationState: migrationComplete - authentication_method[0].AuthenticationMethodConfigurations: + authentication_method[0].authentication_method_policy.PolicyMigrationState: migrationComplete + authentication_method[0].authentication_method_feature_settings: - Id: Sms State: enabled - Id: Voice @@ -257,8 +354,8 @@ TestPlan: - Command: UpdateProviderExport Splat: updates: - authentication_method[0].PolicyMigrationState: migrationComplete - authentication_method[0].AuthenticationMethodConfigurations: + authentication_method[0].authentication_method_policy.PolicyMigrationState: migrationComplete + authentication_method[0].authentication_method_feature_settings: - Id: Sms State: disabled - Id: Voice @@ -272,8 +369,8 @@ TestPlan: - Command: UpdateProviderExport Splat: updates: - authentication_method[0].PolicyMigrationState: migrationComplete - authentication_method[0].AuthenticationMethodConfigurations: + authentication_method[0].authentication_method_policy.PolicyMigrationState: migrationComplete + authentication_method[0].authentication_method_feature_settings: - Id: Sms State: disabled - Id: Voice @@ -287,8 +384,8 @@ TestPlan: - Command: UpdateProviderExport Splat: updates: - authentication_method[0].PolicyMigrationState: migrationComplete - authentication_method[0].AuthenticationMethodConfigurations: + authentication_method[0].authentication_method_policy.PolicyMigrationState: migrationComplete + authentication_method[0].authentication_method_feature_settings: - Id: Sms State: disabled - Id: Voice diff --git a/Testing/RunUnitTests.ps1 b/Testing/RunUnitTests.ps1 index 6c38a1a88..a1cd4e0f5 100644 --- a/Testing/RunUnitTests.ps1 +++ b/Testing/RunUnitTests.ps1 @@ -194,7 +194,7 @@ function Invoke-TestName { if ($Match){ Write-Output "`nTesting $Test" - ..\opa_windows_amd64.exe test $RegoPolicyPath .\$($Filename.Fullname) -r $Test $Flag + & $OPAExe test $RegoPolicyPath .\$($Filename.Fullname) -r $Test $Flag } else{ Write-Warning "`nNOT FOUND: $Test in $Filename"