mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-03-22 03:08:23 +00:00
feat(m365): add entra_require_mfa_for_management_api security check (#10150)
Co-authored-by: Andoni Alonso <14891798+andoniaf@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
6d9ef78df1
commit
db1db7d366
@@ -32,6 +32,7 @@ All notable changes to the **Prowler SDK** are documented in this file.
|
||||
- Registry scan mode for `image` provider: enumerate and scan all images from OCI standard, Docker Hub, and ECR [(#9985)](https://github.com/prowler-cloud/prowler/pull/9985)
|
||||
- Add file descriptor limits (`ulimits`) to Docker Compose worker services to prevent `Too many open files` errors [(#10107)](https://github.com/prowler-cloud/prowler/pull/10107)
|
||||
- CIS 6.0 for the AWS provider [(#10127)](https://github.com/prowler-cloud/prowler/pull/10127)
|
||||
- `entra_require_mfa_for_management_api` check for m365 provider [(#10150)](https://github.com/prowler-cloud/prowler/pull/10150)
|
||||
- OpenStack provider multiple regions support [(#10135)](https://github.com/prowler-cloud/prowler/pull/10135)
|
||||
|
||||
### 🔄 Changed
|
||||
|
||||
@@ -74,7 +74,7 @@
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"entra_conditional_access_policy_require_mfa_for_management_api",
|
||||
"entra_require_mfa_for_management_api",
|
||||
"entra_policy_guest_invite_only_for_admin_roles",
|
||||
"iam_custom_role_has_permissions_to_administer_resource_locks",
|
||||
"iam_role_user_access_admin_restricted",
|
||||
@@ -94,7 +94,7 @@
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"entra_conditional_access_policy_require_mfa_for_management_api",
|
||||
"entra_require_mfa_for_management_api",
|
||||
"entra_policy_default_users_cannot_create_security_groups",
|
||||
"iam_custom_role_has_permissions_to_administer_resource_locks",
|
||||
"iam_role_user_access_admin_restricted",
|
||||
@@ -286,7 +286,7 @@
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"entra_conditional_access_policy_require_mfa_for_management_api",
|
||||
"entra_require_mfa_for_management_api",
|
||||
"entra_policy_default_users_cannot_create_security_groups",
|
||||
"entra_policy_guest_invite_only_for_admin_roles",
|
||||
"entra_policy_user_consent_for_verified_apps",
|
||||
@@ -709,7 +709,7 @@
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"entra_conditional_access_policy_require_mfa_for_management_api",
|
||||
"entra_require_mfa_for_management_api",
|
||||
"entra_policy_guest_users_access_restrictions",
|
||||
"entra_user_with_vm_access_has_mfa",
|
||||
"iam_custom_role_has_permissions_to_administer_resource_locks",
|
||||
@@ -2122,7 +2122,7 @@
|
||||
"monitor_alert_delete_public_ip_address_rule",
|
||||
"aks_clusters_public_access_disabled",
|
||||
"app_function_access_keys_configured",
|
||||
"entra_conditional_access_policy_require_mfa_for_management_api",
|
||||
"entra_require_mfa_for_management_api",
|
||||
"entra_policy_guest_users_access_restrictions",
|
||||
"entra_user_with_vm_access_has_mfa",
|
||||
"iam_role_user_access_admin_restricted",
|
||||
@@ -3497,7 +3497,7 @@
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"entra_conditional_access_policy_require_mfa_for_management_api",
|
||||
"entra_require_mfa_for_management_api",
|
||||
"entra_user_with_vm_access_has_mfa",
|
||||
"iam_custom_role_has_permissions_to_administer_resource_locks",
|
||||
"iam_role_user_access_admin_restricted",
|
||||
@@ -4522,7 +4522,7 @@
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"entra_conditional_access_policy_require_mfa_for_management_api",
|
||||
"entra_require_mfa_for_management_api",
|
||||
"entra_policy_guest_invite_only_for_admin_roles",
|
||||
"entra_policy_guest_users_access_restrictions",
|
||||
"entra_user_with_vm_access_has_mfa",
|
||||
@@ -4894,7 +4894,7 @@
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"entra_conditional_access_policy_require_mfa_for_management_api",
|
||||
"entra_require_mfa_for_management_api",
|
||||
"entra_policy_guest_users_access_restrictions",
|
||||
"entra_user_with_vm_access_has_mfa",
|
||||
"iam_custom_role_has_permissions_to_administer_resource_locks",
|
||||
@@ -4917,7 +4917,7 @@
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"entra_conditional_access_policy_require_mfa_for_management_api",
|
||||
"entra_require_mfa_for_management_api",
|
||||
"entra_policy_guest_users_access_restrictions",
|
||||
"entra_user_with_vm_access_has_mfa",
|
||||
"iam_custom_role_has_permissions_to_administer_resource_locks",
|
||||
@@ -5053,7 +5053,7 @@
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"entra_conditional_access_policy_require_mfa_for_management_api",
|
||||
"entra_require_mfa_for_management_api",
|
||||
"entra_privileged_user_has_mfa",
|
||||
"entra_user_with_vm_access_has_mfa"
|
||||
]
|
||||
@@ -5298,7 +5298,7 @@
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"entra_conditional_access_policy_require_mfa_for_management_api",
|
||||
"entra_require_mfa_for_management_api",
|
||||
"entra_privileged_user_has_mfa",
|
||||
"entra_user_with_vm_access_has_mfa",
|
||||
"iam_role_user_access_admin_restricted",
|
||||
@@ -5346,7 +5346,7 @@
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"entra_conditional_access_policy_require_mfa_for_management_api",
|
||||
"entra_require_mfa_for_management_api",
|
||||
"entra_policy_guest_users_access_restrictions",
|
||||
"entra_policy_user_consent_for_verified_apps",
|
||||
"entra_user_with_vm_access_has_mfa",
|
||||
@@ -5429,7 +5429,7 @@
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"entra_conditional_access_policy_require_mfa_for_management_api",
|
||||
"entra_require_mfa_for_management_api",
|
||||
"entra_user_with_vm_access_has_mfa"
|
||||
]
|
||||
},
|
||||
@@ -5518,7 +5518,7 @@
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"entra_conditional_access_policy_require_mfa_for_management_api",
|
||||
"entra_require_mfa_for_management_api",
|
||||
"entra_non_privileged_user_has_mfa",
|
||||
"entra_user_with_vm_access_has_mfa"
|
||||
]
|
||||
@@ -5557,7 +5557,7 @@
|
||||
"app_function_not_publicly_accessible",
|
||||
"containerregistry_not_publicly_accessible",
|
||||
"containerregistry_uses_private_link",
|
||||
"entra_conditional_access_policy_require_mfa_for_management_api",
|
||||
"entra_require_mfa_for_management_api",
|
||||
"entra_policy_guest_users_access_restrictions",
|
||||
"entra_user_with_vm_access_has_mfa",
|
||||
"iam_role_user_access_admin_restricted",
|
||||
@@ -5598,7 +5598,7 @@
|
||||
"app_function_not_publicly_accessible",
|
||||
"containerregistry_not_publicly_accessible",
|
||||
"containerregistry_uses_private_link",
|
||||
"entra_conditional_access_policy_require_mfa_for_management_api",
|
||||
"entra_require_mfa_for_management_api",
|
||||
"entra_policy_guest_users_access_restrictions",
|
||||
"entra_user_with_vm_access_has_mfa",
|
||||
"iam_role_user_access_admin_restricted",
|
||||
@@ -9010,7 +9010,7 @@
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"entra_conditional_access_policy_require_mfa_for_management_api",
|
||||
"entra_require_mfa_for_management_api",
|
||||
"entra_non_privileged_user_has_mfa",
|
||||
"entra_privileged_user_has_mfa",
|
||||
"entra_user_with_vm_access_has_mfa"
|
||||
@@ -9029,7 +9029,7 @@
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"entra_conditional_access_policy_require_mfa_for_management_api",
|
||||
"entra_require_mfa_for_management_api",
|
||||
"entra_privileged_user_has_mfa"
|
||||
]
|
||||
},
|
||||
@@ -9240,7 +9240,7 @@
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"entra_conditional_access_policy_require_mfa_for_management_api",
|
||||
"entra_require_mfa_for_management_api",
|
||||
"entra_policy_guest_invite_only_for_admin_roles",
|
||||
"entra_policy_guest_users_access_restrictions",
|
||||
"iam_custom_role_has_permissions_to_administer_resource_locks",
|
||||
|
||||
@@ -1414,7 +1414,7 @@
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"entra_conditional_access_policy_require_mfa_for_management_api",
|
||||
"entra_require_mfa_for_management_api",
|
||||
"entra_global_admin_in_less_than_five_users",
|
||||
"entra_privileged_user_has_mfa",
|
||||
"iam_role_user_access_admin_restricted",
|
||||
@@ -5135,7 +5135,7 @@
|
||||
"Checks": [
|
||||
"entra_non_privileged_user_has_mfa",
|
||||
"entra_privileged_user_has_mfa",
|
||||
"entra_conditional_access_policy_require_mfa_for_management_api",
|
||||
"entra_require_mfa_for_management_api",
|
||||
"entra_security_defaults_enabled",
|
||||
"entra_user_with_vm_access_has_mfa"
|
||||
]
|
||||
@@ -5201,7 +5201,7 @@
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"entra_conditional_access_policy_require_mfa_for_management_api",
|
||||
"entra_require_mfa_for_management_api",
|
||||
"entra_non_privileged_user_has_mfa",
|
||||
"entra_privileged_user_has_mfa",
|
||||
"entra_security_defaults_enabled"
|
||||
@@ -5266,7 +5266,7 @@
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"entra_conditional_access_policy_require_mfa_for_management_api",
|
||||
"entra_require_mfa_for_management_api",
|
||||
"entra_non_privileged_user_has_mfa",
|
||||
"entra_privileged_user_has_mfa",
|
||||
"entra_security_defaults_enabled"
|
||||
@@ -5331,7 +5331,7 @@
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"entra_conditional_access_policy_require_mfa_for_management_api",
|
||||
"entra_require_mfa_for_management_api",
|
||||
"entra_non_privileged_user_has_mfa",
|
||||
"entra_privileged_user_has_mfa",
|
||||
"entra_user_with_vm_access_has_mfa"
|
||||
@@ -5411,7 +5411,7 @@
|
||||
"keyvault_rbac_enabled",
|
||||
"keyvault_private_endpoints",
|
||||
"keyvault_access_only_through_private_endpoints",
|
||||
"entra_conditional_access_policy_require_mfa_for_management_api",
|
||||
"entra_require_mfa_for_management_api",
|
||||
"entra_global_admin_in_less_than_five_users",
|
||||
"entra_non_privileged_user_has_mfa",
|
||||
"entra_security_defaults_enabled",
|
||||
@@ -5506,7 +5506,7 @@
|
||||
"aks_clusters_public_access_disabled",
|
||||
"app_function_not_publicly_accessible",
|
||||
"entra_global_admin_in_less_than_five_users",
|
||||
"entra_conditional_access_policy_require_mfa_for_management_api",
|
||||
"entra_require_mfa_for_management_api",
|
||||
"entra_non_privileged_user_has_mfa",
|
||||
"entra_privileged_user_has_mfa",
|
||||
"entra_trusted_named_locations_exists",
|
||||
@@ -5571,7 +5571,7 @@
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"entra_conditional_access_policy_require_mfa_for_management_api",
|
||||
"entra_require_mfa_for_management_api",
|
||||
"entra_global_admin_in_less_than_five_users",
|
||||
"entra_non_privileged_user_has_mfa",
|
||||
"iam_role_user_access_admin_restricted",
|
||||
@@ -5681,7 +5681,7 @@
|
||||
"network_ssh_internet_access_restricted",
|
||||
"network_udp_internet_access_restricted",
|
||||
"vm_jit_access_enabled",
|
||||
"entra_conditional_access_policy_require_mfa_for_management_api",
|
||||
"entra_require_mfa_for_management_api",
|
||||
"entra_global_admin_in_less_than_five_users",
|
||||
"entra_non_privileged_user_has_mfa",
|
||||
"entra_privileged_user_has_mfa",
|
||||
@@ -5845,7 +5845,7 @@
|
||||
"entra_global_admin_in_less_than_five_users",
|
||||
"entra_non_privileged_user_has_mfa",
|
||||
"entra_privileged_user_has_mfa",
|
||||
"entra_conditional_access_policy_require_mfa_for_management_api",
|
||||
"entra_require_mfa_for_management_api",
|
||||
"keyvault_rbac_enabled",
|
||||
"vm_jit_access_enabled",
|
||||
"vm_linux_enforce_ssh_authentication"
|
||||
|
||||
@@ -688,7 +688,7 @@
|
||||
"Id": "1.2.6",
|
||||
"Description": "Ensure Multifactor Authentication is Required for Windows Azure Service Management API",
|
||||
"Checks": [
|
||||
"entra_conditional_access_policy_require_mfa_for_management_api"
|
||||
"entra_require_mfa_for_management_api"
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
|
||||
@@ -729,7 +729,7 @@
|
||||
"Id": "2.2.7",
|
||||
"Description": "Ensure Multi-factor Authentication is Required for Windows Azure Service Management API",
|
||||
"Checks": [
|
||||
"entra_conditional_access_policy_require_mfa_for_management_api"
|
||||
"entra_require_mfa_for_management_api"
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
|
||||
@@ -1013,7 +1013,7 @@
|
||||
"Id": "6.2.6",
|
||||
"Description": "Ensure that multifactor authentication is required for Windows Azure Service Management API",
|
||||
"Checks": [
|
||||
"entra_conditional_access_policy_require_mfa_for_management_api"
|
||||
"entra_require_mfa_for_management_api"
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
|
||||
@@ -449,7 +449,7 @@
|
||||
"Id": "5.2.6",
|
||||
"Description": "Ensure that multifactor authentication is required for Windows Azure Service Management API",
|
||||
"Checks": [
|
||||
"entra_conditional_access_policy_require_mfa_for_management_api"
|
||||
"entra_require_mfa_for_management_api"
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
|
||||
@@ -3703,7 +3703,7 @@
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"entra_conditional_access_policy_require_mfa_for_management_api",
|
||||
"entra_require_mfa_for_management_api",
|
||||
"entra_global_admin_in_less_than_five_users",
|
||||
"entra_user_with_vm_access_has_mfa",
|
||||
"iam_role_user_access_admin_restricted",
|
||||
@@ -3921,7 +3921,7 @@
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"entra_conditional_access_policy_require_mfa_for_management_api",
|
||||
"entra_require_mfa_for_management_api",
|
||||
"entra_non_privileged_user_has_mfa",
|
||||
"entra_privileged_user_has_mfa",
|
||||
"entra_security_defaults_enabled",
|
||||
|
||||
@@ -279,7 +279,7 @@
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"entra_conditional_access_policy_require_mfa_for_management_api"
|
||||
"entra_require_mfa_for_management_api"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -329,7 +329,7 @@
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"entra_conditional_access_policy_require_mfa_for_management_api"
|
||||
"entra_require_mfa_for_management_api"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -484,7 +484,7 @@
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"entra_conditional_access_policy_require_mfa_for_management_api"
|
||||
"entra_require_mfa_for_management_api"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -89,7 +89,7 @@
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"entra_conditional_access_policy_require_mfa_for_management_api",
|
||||
"entra_require_mfa_for_management_api",
|
||||
"entra_global_admin_in_less_than_five_users",
|
||||
"entra_non_privileged_user_has_mfa",
|
||||
"entra_policy_default_users_cannot_create_security_groups",
|
||||
|
||||
@@ -142,7 +142,7 @@
|
||||
"entra_privileged_user_has_mfa",
|
||||
"entra_non_privileged_user_has_mfa",
|
||||
"entra_security_defaults_enabled",
|
||||
"entra_conditional_access_policy_require_mfa_for_management_api",
|
||||
"entra_require_mfa_for_management_api",
|
||||
"entra_user_with_vm_access_has_mfa",
|
||||
"network_flow_log_captured_sent",
|
||||
"app_http_logs_enabled"
|
||||
@@ -730,7 +730,7 @@
|
||||
"entra_security_defaults_enabled",
|
||||
"entra_privileged_user_has_mfa",
|
||||
"entra_non_privileged_user_has_mfa",
|
||||
"entra_conditional_access_policy_require_mfa_for_management_api",
|
||||
"entra_require_mfa_for_management_api",
|
||||
"entra_user_with_vm_access_has_mfa",
|
||||
"entra_trusted_named_locations_exists",
|
||||
"sqlserver_azuread_administrator_enabled",
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"entra_conditional_access_policy_require_mfa_for_management_api",
|
||||
"entra_require_mfa_for_management_api",
|
||||
"entra_global_admin_in_less_than_five_users",
|
||||
"entra_non_privileged_user_has_mfa",
|
||||
"entra_policy_default_users_cannot_create_security_groups",
|
||||
@@ -307,7 +307,7 @@
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"entra_conditional_access_policy_require_mfa_for_management_api",
|
||||
"entra_require_mfa_for_management_api",
|
||||
"entra_non_privileged_user_has_mfa",
|
||||
"entra_privileged_user_has_mfa",
|
||||
"entra_user_with_vm_access_has_mfa"
|
||||
|
||||
@@ -212,7 +212,7 @@
|
||||
"Description": "Adversaries may obtain and abuse credentials of existing accounts as a means of gaining Initial Access, Persistence, Privilege Escalation, or Defense Evasion. Compromised credentials may be used to bypass access controls placed on various resources on systems within the network and may even be used for persistent access to remote systems and externally available services, such as VPNs, Outlook Web Access, network devices, and remote desktop.[1] Compromised credentials may also grant an adversary increased privilege to specific systems or access to restricted areas of the network. Adversaries may choose not to use malware or tools in conjunction with the legitimate access those credentials provide to make it harder to detect their presence.",
|
||||
"TechniqueURL": "https://attack.mitre.org/techniques/T1078/",
|
||||
"Checks": [
|
||||
"entra_conditional_access_policy_require_mfa_for_management_api",
|
||||
"entra_require_mfa_for_management_api",
|
||||
"entra_global_admin_in_less_than_five_users",
|
||||
"entra_non_privileged_user_has_mfa",
|
||||
"entra_policy_default_users_cannot_create_security_groups",
|
||||
@@ -489,7 +489,7 @@
|
||||
"Description": "Adversaries may manipulate accounts to maintain access to victim systems. Account manipulation may consist of any action that preserves adversary access to a compromised account, such as modifying credentials or permission groups. These actions could also include account activity designed to subvert security policies, such as performing iterative password updates to bypass password duration policies and preserve the life of compromised credentials.",
|
||||
"TechniqueURL": "https://attack.mitre.org/techniques/T1098/",
|
||||
"Checks": [
|
||||
"entra_conditional_access_policy_require_mfa_for_management_api",
|
||||
"entra_require_mfa_for_management_api",
|
||||
"entra_global_admin_in_less_than_five_users",
|
||||
"entra_non_privileged_user_has_mfa",
|
||||
"entra_policy_default_users_cannot_create_security_groups",
|
||||
@@ -804,7 +804,7 @@
|
||||
"Description": "Adversaries may modify authentication mechanisms and processes to access user credentials or enable otherwise unwarranted access to accounts. The authentication process is handled by mechanisms, such as the Local Security Authentication Server (LSASS) process and the Security Accounts Manager (SAM) on Windows, pluggable authentication modules (PAM) on Unix-based systems, and authorization plugins on MacOS systems, responsible for gathering, storing, and validating credentials. By modifying an authentication process, an adversary may be able to authenticate to a service or system without using Valid Accounts.",
|
||||
"TechniqueURL": "https://attack.mitre.org/techniques/T1556/",
|
||||
"Checks": [
|
||||
"entra_conditional_access_policy_require_mfa_for_management_api",
|
||||
"entra_require_mfa_for_management_api",
|
||||
"entra_global_admin_in_less_than_five_users",
|
||||
"entra_non_privileged_user_has_mfa",
|
||||
"entra_privileged_user_has_mfa",
|
||||
@@ -1279,7 +1279,7 @@
|
||||
"Description": "Adversaries may sniff network traffic to capture information about an environment, including authentication material passed over the network. Network sniffing refers to using the network interface on a system to monitor or capture information sent over a wired or wireless connection. An adversary may place a network interface into promiscuous mode to passively access data in transit over the network, or use span ports to capture a larger amount of data.",
|
||||
"TechniqueURL": "https://attack.mitre.org/techniques/T1040/",
|
||||
"Checks": [
|
||||
"entra_conditional_access_policy_require_mfa_for_management_api",
|
||||
"entra_require_mfa_for_management_api",
|
||||
"entra_global_admin_in_less_than_five_users",
|
||||
"entra_non_privileged_user_has_mfa",
|
||||
"entra_policy_default_users_cannot_create_security_groups",
|
||||
|
||||
@@ -1603,7 +1603,7 @@
|
||||
"Id": "11.3.2.a",
|
||||
"Description": "establish strong identification, authentication such as multi-factor authentication, and authorisation procedures for privileged accounts and system administration accounts;",
|
||||
"Checks": [
|
||||
"entra_conditional_access_policy_require_mfa_for_management_api",
|
||||
"entra_require_mfa_for_management_api",
|
||||
"entra_non_privileged_user_has_mfa",
|
||||
"entra_privileged_user_has_mfa",
|
||||
"entra_user_with_vm_access_has_mfa"
|
||||
@@ -1692,7 +1692,7 @@
|
||||
"Checks": [
|
||||
"entra_trusted_named_locations_exists",
|
||||
"entra_user_with_vm_access_has_mfa",
|
||||
"entra_conditional_access_policy_require_mfa_for_management_api",
|
||||
"entra_require_mfa_for_management_api",
|
||||
"entra_privileged_user_has_mfa"
|
||||
],
|
||||
"Attributes": [
|
||||
@@ -1762,7 +1762,7 @@
|
||||
"Id": "11.6.2.a",
|
||||
"Description": "ensure the strength of authentication is appropriate to the classification of the asset to be accessed;",
|
||||
"Checks": [
|
||||
"entra_conditional_access_policy_require_mfa_for_management_api",
|
||||
"entra_require_mfa_for_management_api",
|
||||
"entra_non_privileged_user_has_mfa",
|
||||
"entra_privileged_user_has_mfa",
|
||||
"entra_user_with_vm_access_has_mfa"
|
||||
@@ -1794,7 +1794,7 @@
|
||||
"Id": "11.7.2",
|
||||
"Description": "The relevant entities shall ensure that the strength of authentication is appropriate for the classification of the asset to be accessed.",
|
||||
"Checks": [
|
||||
"entra_conditional_access_policy_require_mfa_for_management_api",
|
||||
"entra_require_mfa_for_management_api",
|
||||
"entra_non_privileged_user_has_mfa",
|
||||
"entra_privileged_user_has_mfa",
|
||||
"entra_user_with_vm_access_has_mfa"
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
"Id": "1.1.3",
|
||||
"Description": "Ensure Multi-factor Authentication is Required for Windows Azure Service Management API",
|
||||
"Checks": [
|
||||
"entra_conditional_access_policy_require_mfa_for_management_api"
|
||||
"entra_require_mfa_for_management_api"
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
|
||||
@@ -160,7 +160,7 @@
|
||||
"entra_policy_restricts_user_consent_for_apps",
|
||||
"entra_user_with_vm_access_has_mfa",
|
||||
"entra_security_defaults_enabled",
|
||||
"entra_conditional_access_policy_require_mfa_for_management_api",
|
||||
"entra_require_mfa_for_management_api",
|
||||
"entra_trusted_named_locations_exists",
|
||||
"sqlserver_azuread_administrator_enabled",
|
||||
"postgresql_flexible_server_entra_id_authentication_enabled",
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"entra_conditional_access_policy_require_mfa_for_management_api",
|
||||
"entra_require_mfa_for_management_api",
|
||||
"entra_global_admin_in_less_than_five_users",
|
||||
"entra_non_privileged_user_has_mfa",
|
||||
"entra_policy_default_users_cannot_create_security_groups",
|
||||
@@ -707,4 +707,4 @@
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"Provider": "azure",
|
||||
"CheckID": "entra_conditional_access_policy_require_mfa_for_management_api",
|
||||
"CheckID": "entra_require_mfa_for_management_api",
|
||||
"CheckTitle": "Tenant requires MFA for all users to access Windows Azure Service Management API",
|
||||
"CheckType": [],
|
||||
"ServiceName": "entra",
|
||||
@@ -26,7 +26,7 @@
|
||||
},
|
||||
"Recommendation": {
|
||||
"Text": "Enforce **MFA** via Conditional Access for `Windows Azure Service Management API` scoped to `All users`, with only break-glass exclusions. Prefer **phishing-resistant** methods, apply **least privilege** and **separation of duties**, and monitor sign-ins. Also secure related admin apps and explicitly protect Azure DevOps as a distinct target.",
|
||||
"Url": "https://hub.prowler.com/check/entra_conditional_access_policy_require_mfa_for_management_api"
|
||||
"Url": "https://hub.prowler.com/check/entra_require_mfa_for_management_api"
|
||||
}
|
||||
},
|
||||
"Categories": [
|
||||
@@ -3,7 +3,7 @@ from prowler.providers.azure.config import WINDOWS_AZURE_SERVICE_MANAGEMENT_API
|
||||
from prowler.providers.azure.services.entra.entra_client import entra_client
|
||||
|
||||
|
||||
class entra_conditional_access_policy_require_mfa_for_management_api(Check):
|
||||
class entra_require_mfa_for_management_api(Check):
|
||||
def execute(self) -> Check_Report_Azure:
|
||||
findings = []
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
{
|
||||
"Provider": "m365",
|
||||
"CheckID": "entra_require_mfa_for_management_api",
|
||||
"CheckTitle": "Conditional Access Policy enforces MFA for Azure Management API access",
|
||||
"CheckType": [],
|
||||
"ServiceName": "entra",
|
||||
"SubServiceName": "",
|
||||
"ResourceIdTemplate": "",
|
||||
"Severity": "high",
|
||||
"ResourceType": "Conditional Access Policy",
|
||||
"ResourceGroup": "IAM",
|
||||
"Description": "This check verifies that at least one **enabled** Conditional Access policy requires **multifactor authentication** for the **Windows Azure Service Management API**, covering Azure Portal, CLI, PowerShell, and IaC tools.",
|
||||
"Risk": "Without MFA on Azure management endpoints, compromised credentials allow **control-plane access**. Attackers can modify configurations, create or delete resources, extract secrets, and pivot laterally, compromising confidentiality, integrity, and availability.",
|
||||
"RelatedUrl": "",
|
||||
"AdditionalURLs": [
|
||||
"https://learn.microsoft.com/en-us/entra/identity/conditional-access/policy-old-require-mfa-azure-mgmt",
|
||||
"https://learn.microsoft.com/en-us/entra/identity/conditional-access/concept-conditional-access-cloud-apps"
|
||||
],
|
||||
"Remediation": {
|
||||
"Code": {
|
||||
"CLI": "",
|
||||
"NativeIaC": "",
|
||||
"Other": "1. In the Microsoft Entra admin center, go to Protection > Conditional Access > Policies.\n2. Click New policy.\n3. Under Users, select Include > All users.\n4. Under Target resources, select Include > Select resources > choose \"Windows Azure Service Management API\".\n5. Under Grant, select Grant access > check Require multifactor authentication > Select.\n6. Set Enable policy to On and click Create.",
|
||||
"Terraform": ""
|
||||
},
|
||||
"Recommendation": {
|
||||
"Text": "Enforce **MFA** via Conditional Access for the Windows Azure Service Management API scoped to all users. Prefer **phishing-resistant** methods, apply **least privilege**, and monitor sign-ins for anomalous activity. Only exclude dedicated break-glass accounts.",
|
||||
"Url": "https://hub.prowler.com/check/entra_require_mfa_for_management_api"
|
||||
}
|
||||
},
|
||||
"Categories": [
|
||||
"identity-access"
|
||||
],
|
||||
"DependsOn": [],
|
||||
"RelatedTo": [
|
||||
"entra_emergency_access_exclusion"
|
||||
],
|
||||
"Notes": "Conditional Access policies require Microsoft Entra ID P1 or P2 licenses. The Windows Azure Service Management API (appId: 797f4846-ba00-4fd7-ba43-dac1f8f63013) covers Azure Portal, Azure CLI, Azure PowerShell, Azure mobile app, and IaC tools."
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
from prowler.lib.check.models import Check, CheckReportM365
|
||||
from prowler.providers.m365.services.entra.entra_client import entra_client
|
||||
from prowler.providers.m365.services.entra.entra_service import (
|
||||
ConditionalAccessGrantControl,
|
||||
ConditionalAccessPolicyState,
|
||||
)
|
||||
|
||||
# Windows Azure Service Management API application ID
|
||||
AZURE_MANAGEMENT_API_APP_ID = "797f4846-ba00-4fd7-ba43-dac1f8f63013"
|
||||
|
||||
|
||||
class entra_require_mfa_for_management_api(Check):
|
||||
"""Check if at least one enabled Conditional Access policy requires MFA for Azure Management API.
|
||||
|
||||
This check verifies that at least one enabled Conditional Access policy
|
||||
requires multifactor authentication (MFA) for the Windows Azure Service
|
||||
Management API (appId: 797f4846-ba00-4fd7-ba43-dac1f8f63013), which covers
|
||||
Azure Portal, Azure CLI, Azure PowerShell, and IaC tools.
|
||||
|
||||
- PASS: At least one enabled CA policy requires MFA for Azure Management API.
|
||||
- FAIL: No enabled CA policy enforces MFA for Azure Management API access.
|
||||
"""
|
||||
|
||||
def execute(self) -> list[CheckReportM365]:
|
||||
"""Execute the check logic.
|
||||
|
||||
Returns:
|
||||
A list of reports containing the result of the check.
|
||||
"""
|
||||
findings = []
|
||||
report = CheckReportM365(
|
||||
metadata=self.metadata(),
|
||||
resource={},
|
||||
resource_name="Conditional Access Policies",
|
||||
resource_id="conditionalAccessPolicies",
|
||||
)
|
||||
report.status = "FAIL"
|
||||
report.status_extended = (
|
||||
"No Conditional Access Policy requires MFA for Azure Management API."
|
||||
)
|
||||
|
||||
for policy in entra_client.conditional_access_policies.values():
|
||||
if policy.state == ConditionalAccessPolicyState.DISABLED:
|
||||
continue
|
||||
|
||||
if not policy.conditions.application_conditions:
|
||||
continue
|
||||
|
||||
if (
|
||||
AZURE_MANAGEMENT_API_APP_ID
|
||||
not in policy.conditions.application_conditions.included_applications
|
||||
and "All"
|
||||
not in policy.conditions.application_conditions.included_applications
|
||||
):
|
||||
continue
|
||||
|
||||
if "All" not in policy.conditions.user_conditions.included_users:
|
||||
continue
|
||||
|
||||
if (
|
||||
ConditionalAccessGrantControl.MFA
|
||||
not in policy.grant_controls.built_in_controls
|
||||
):
|
||||
continue
|
||||
|
||||
report = CheckReportM365(
|
||||
metadata=self.metadata(),
|
||||
resource=policy,
|
||||
resource_name=policy.display_name,
|
||||
resource_id=policy.id,
|
||||
)
|
||||
|
||||
if policy.state == ConditionalAccessPolicyState.ENABLED_FOR_REPORTING:
|
||||
report.status = "FAIL"
|
||||
report.status_extended = f"Conditional Access Policy {policy.display_name} targets Azure Management API with MFA but is only in report-only mode."
|
||||
else:
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"Conditional Access Policy {policy.display_name} requires MFA for Azure Management API."
|
||||
break
|
||||
|
||||
findings.append(report)
|
||||
return findings
|
||||
@@ -8,7 +8,7 @@ from tests.providers.azure.azure_fixtures import (
|
||||
)
|
||||
|
||||
|
||||
class Test_entra_conditional_access_policy_require_mfa_for_management_api:
|
||||
class Test_entra_require_mfa_for_management_api:
|
||||
def test_entra_no_subscriptions(self):
|
||||
entra_client = mock.MagicMock
|
||||
|
||||
@@ -18,18 +18,18 @@ class Test_entra_conditional_access_policy_require_mfa_for_management_api:
|
||||
return_value=set_mocked_azure_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.azure.services.entra.entra_conditional_access_policy_require_mfa_for_management_api.entra_conditional_access_policy_require_mfa_for_management_api.entra_client",
|
||||
"prowler.providers.azure.services.entra.entra_require_mfa_for_management_api.entra_require_mfa_for_management_api.entra_client",
|
||||
new=entra_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.azure.services.entra.entra_conditional_access_policy_require_mfa_for_management_api.entra_conditional_access_policy_require_mfa_for_management_api import (
|
||||
entra_conditional_access_policy_require_mfa_for_management_api,
|
||||
from prowler.providers.azure.services.entra.entra_require_mfa_for_management_api.entra_require_mfa_for_management_api import (
|
||||
entra_require_mfa_for_management_api,
|
||||
)
|
||||
|
||||
entra_client.conditional_access_policy = {}
|
||||
entra_client.tenant_ids = TENANT_IDS
|
||||
|
||||
check = entra_conditional_access_policy_require_mfa_for_management_api()
|
||||
check = entra_require_mfa_for_management_api()
|
||||
result = check.execute()
|
||||
assert len(result) == 0
|
||||
|
||||
@@ -42,19 +42,19 @@ class Test_entra_conditional_access_policy_require_mfa_for_management_api:
|
||||
return_value=set_mocked_azure_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.azure.services.entra.entra_conditional_access_policy_require_mfa_for_management_api.entra_conditional_access_policy_require_mfa_for_management_api.entra_client",
|
||||
"prowler.providers.azure.services.entra.entra_require_mfa_for_management_api.entra_require_mfa_for_management_api.entra_client",
|
||||
new=entra_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.azure.services.entra.entra_conditional_access_policy_require_mfa_for_management_api.entra_conditional_access_policy_require_mfa_for_management_api import (
|
||||
entra_conditional_access_policy_require_mfa_for_management_api,
|
||||
from prowler.providers.azure.services.entra.entra_require_mfa_for_management_api.entra_require_mfa_for_management_api import (
|
||||
entra_require_mfa_for_management_api,
|
||||
)
|
||||
|
||||
# No policies configured
|
||||
entra_client.conditional_access_policy = {DOMAIN: {}}
|
||||
entra_client.tenant_ids = TENANT_IDS
|
||||
|
||||
check = entra_conditional_access_policy_require_mfa_for_management_api()
|
||||
check = entra_require_mfa_for_management_api()
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
@@ -76,12 +76,12 @@ class Test_entra_conditional_access_policy_require_mfa_for_management_api:
|
||||
return_value=set_mocked_azure_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.azure.services.entra.entra_conditional_access_policy_require_mfa_for_management_api.entra_conditional_access_policy_require_mfa_for_management_api.entra_client",
|
||||
"prowler.providers.azure.services.entra.entra_require_mfa_for_management_api.entra_require_mfa_for_management_api.entra_client",
|
||||
new=entra_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.azure.services.entra.entra_conditional_access_policy_require_mfa_for_management_api.entra_conditional_access_policy_require_mfa_for_management_api import (
|
||||
entra_conditional_access_policy_require_mfa_for_management_api,
|
||||
from prowler.providers.azure.services.entra.entra_require_mfa_for_management_api.entra_require_mfa_for_management_api import (
|
||||
entra_require_mfa_for_management_api,
|
||||
)
|
||||
from prowler.providers.azure.services.entra.entra_service import (
|
||||
ConditionalAccessPolicy,
|
||||
@@ -99,7 +99,7 @@ class Test_entra_conditional_access_policy_require_mfa_for_management_api:
|
||||
entra_client.conditional_access_policy = {DOMAIN: {policy_id: policy}}
|
||||
entra_client.tenant_ids = TENANT_IDS
|
||||
|
||||
check = entra_conditional_access_policy_require_mfa_for_management_api()
|
||||
check = entra_require_mfa_for_management_api()
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
@@ -122,12 +122,12 @@ class Test_entra_conditional_access_policy_require_mfa_for_management_api:
|
||||
return_value=set_mocked_azure_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.azure.services.entra.entra_conditional_access_policy_require_mfa_for_management_api.entra_conditional_access_policy_require_mfa_for_management_api.entra_client",
|
||||
"prowler.providers.azure.services.entra.entra_require_mfa_for_management_api.entra_require_mfa_for_management_api.entra_client",
|
||||
new=entra_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.azure.services.entra.entra_conditional_access_policy_require_mfa_for_management_api.entra_conditional_access_policy_require_mfa_for_management_api import (
|
||||
entra_conditional_access_policy_require_mfa_for_management_api,
|
||||
from prowler.providers.azure.services.entra.entra_require_mfa_for_management_api.entra_require_mfa_for_management_api import (
|
||||
entra_require_mfa_for_management_api,
|
||||
)
|
||||
from prowler.providers.azure.services.entra.entra_service import (
|
||||
ConditionalAccessPolicy,
|
||||
@@ -145,7 +145,7 @@ class Test_entra_conditional_access_policy_require_mfa_for_management_api:
|
||||
entra_client.conditional_access_policy = {DOMAIN: {policy_id: policy}}
|
||||
entra_client.tenant_ids = TENANT_IDS
|
||||
|
||||
check = entra_conditional_access_policy_require_mfa_for_management_api()
|
||||
check = entra_require_mfa_for_management_api()
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "PASS"
|
||||
@@ -167,12 +167,12 @@ class Test_entra_conditional_access_policy_require_mfa_for_management_api:
|
||||
return_value=set_mocked_azure_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.azure.services.entra.entra_conditional_access_policy_require_mfa_for_management_api.entra_conditional_access_policy_require_mfa_for_management_api.entra_client",
|
||||
"prowler.providers.azure.services.entra.entra_require_mfa_for_management_api.entra_require_mfa_for_management_api.entra_client",
|
||||
new=entra_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.azure.services.entra.entra_conditional_access_policy_require_mfa_for_management_api.entra_conditional_access_policy_require_mfa_for_management_api import (
|
||||
entra_conditional_access_policy_require_mfa_for_management_api,
|
||||
from prowler.providers.azure.services.entra.entra_require_mfa_for_management_api.entra_require_mfa_for_management_api import (
|
||||
entra_require_mfa_for_management_api,
|
||||
)
|
||||
from prowler.providers.azure.services.entra.entra_service import (
|
||||
ConditionalAccessPolicy,
|
||||
@@ -190,7 +190,7 @@ class Test_entra_conditional_access_policy_require_mfa_for_management_api:
|
||||
entra_client.conditional_access_policy = {DOMAIN: {policy_id: policy}}
|
||||
entra_client.tenant_ids = TENANT_IDS
|
||||
|
||||
check = entra_conditional_access_policy_require_mfa_for_management_api()
|
||||
check = entra_require_mfa_for_management_api()
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
@@ -213,12 +213,12 @@ class Test_entra_conditional_access_policy_require_mfa_for_management_api:
|
||||
return_value=set_mocked_azure_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.azure.services.entra.entra_conditional_access_policy_require_mfa_for_management_api.entra_conditional_access_policy_require_mfa_for_management_api.entra_client",
|
||||
"prowler.providers.azure.services.entra.entra_require_mfa_for_management_api.entra_require_mfa_for_management_api.entra_client",
|
||||
new=entra_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.azure.services.entra.entra_conditional_access_policy_require_mfa_for_management_api.entra_conditional_access_policy_require_mfa_for_management_api import (
|
||||
entra_conditional_access_policy_require_mfa_for_management_api,
|
||||
from prowler.providers.azure.services.entra.entra_require_mfa_for_management_api.entra_require_mfa_for_management_api import (
|
||||
entra_require_mfa_for_management_api,
|
||||
)
|
||||
from prowler.providers.azure.services.entra.entra_service import (
|
||||
ConditionalAccessPolicy,
|
||||
@@ -236,7 +236,7 @@ class Test_entra_conditional_access_policy_require_mfa_for_management_api:
|
||||
entra_client.conditional_access_policy = {DOMAIN: {policy_id: policy}}
|
||||
entra_client.tenant_ids = TENANT_IDS
|
||||
|
||||
check = entra_conditional_access_policy_require_mfa_for_management_api()
|
||||
check = entra_require_mfa_for_management_api()
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
@@ -259,12 +259,12 @@ class Test_entra_conditional_access_policy_require_mfa_for_management_api:
|
||||
return_value=set_mocked_azure_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.azure.services.entra.entra_conditional_access_policy_require_mfa_for_management_api.entra_conditional_access_policy_require_mfa_for_management_api.entra_client",
|
||||
"prowler.providers.azure.services.entra.entra_require_mfa_for_management_api.entra_require_mfa_for_management_api.entra_client",
|
||||
new=entra_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.azure.services.entra.entra_conditional_access_policy_require_mfa_for_management_api.entra_conditional_access_policy_require_mfa_for_management_api import (
|
||||
entra_conditional_access_policy_require_mfa_for_management_api,
|
||||
from prowler.providers.azure.services.entra.entra_require_mfa_for_management_api.entra_require_mfa_for_management_api import (
|
||||
entra_require_mfa_for_management_api,
|
||||
)
|
||||
from prowler.providers.azure.services.entra.entra_service import (
|
||||
ConditionalAccessPolicy,
|
||||
@@ -282,7 +282,7 @@ class Test_entra_conditional_access_policy_require_mfa_for_management_api:
|
||||
entra_client.conditional_access_policy = {DOMAIN: {policy_id: policy}}
|
||||
entra_client.tenant_ids = TENANT_IDS
|
||||
|
||||
check = entra_conditional_access_policy_require_mfa_for_management_api()
|
||||
check = entra_require_mfa_for_management_api()
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
@@ -0,0 +1,696 @@
|
||||
from unittest import mock
|
||||
from uuid import uuid4
|
||||
|
||||
from prowler.providers.m365.services.entra.entra_service import (
|
||||
ApplicationsConditions,
|
||||
ConditionalAccessGrantControl,
|
||||
ConditionalAccessPolicyState,
|
||||
Conditions,
|
||||
GrantControlOperator,
|
||||
GrantControls,
|
||||
PersistentBrowser,
|
||||
SessionControls,
|
||||
SignInFrequency,
|
||||
SignInFrequencyInterval,
|
||||
UsersConditions,
|
||||
)
|
||||
from tests.providers.m365.m365_fixtures import DOMAIN, set_mocked_m365_provider
|
||||
|
||||
AZURE_MANAGEMENT_API_APP_ID = "797f4846-ba00-4fd7-ba43-dac1f8f63013"
|
||||
|
||||
CHECK_MODULE_PATH = "prowler.providers.m365.services.entra.entra_require_mfa_for_management_api.entra_require_mfa_for_management_api"
|
||||
|
||||
|
||||
class Test_m365_entra_require_mfa_for_management_api:
|
||||
def test_no_conditional_access_policies(self):
|
||||
"""Test FAIL when there are no Conditional Access policies."""
|
||||
entra_client = mock.MagicMock
|
||||
entra_client.audited_tenant = "audited_tenant"
|
||||
entra_client.audited_domain = DOMAIN
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_m365_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
f"{CHECK_MODULE_PATH}.entra_client",
|
||||
new=entra_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.m365.services.entra.entra_require_mfa_for_management_api.entra_require_mfa_for_management_api import (
|
||||
entra_require_mfa_for_management_api,
|
||||
)
|
||||
|
||||
entra_client.conditional_access_policies = {}
|
||||
|
||||
check = entra_require_mfa_for_management_api()
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== "No Conditional Access Policy requires MFA for Azure Management API."
|
||||
)
|
||||
assert result[0].resource == {}
|
||||
assert result[0].resource_name == "Conditional Access Policies"
|
||||
assert result[0].resource_id == "conditionalAccessPolicies"
|
||||
assert result[0].location == "global"
|
||||
|
||||
def test_policy_disabled(self):
|
||||
"""Test FAIL when the only matching policy is disabled."""
|
||||
policy_id = str(uuid4())
|
||||
display_name = "Require MFA for Azure Management"
|
||||
entra_client = mock.MagicMock
|
||||
entra_client.audited_tenant = "audited_tenant"
|
||||
entra_client.audited_domain = DOMAIN
|
||||
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_m365_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
f"{CHECK_MODULE_PATH}.entra_client",
|
||||
new=entra_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.m365.services.entra.entra_require_mfa_for_management_api.entra_require_mfa_for_management_api import (
|
||||
entra_require_mfa_for_management_api,
|
||||
)
|
||||
from prowler.providers.m365.services.entra.entra_service import (
|
||||
ConditionalAccessPolicy,
|
||||
)
|
||||
|
||||
entra_client.conditional_access_policies = {
|
||||
policy_id: ConditionalAccessPolicy(
|
||||
id=policy_id,
|
||||
display_name=display_name,
|
||||
conditions=Conditions(
|
||||
application_conditions=ApplicationsConditions(
|
||||
included_applications=[AZURE_MANAGEMENT_API_APP_ID],
|
||||
excluded_applications=[],
|
||||
included_user_actions=[],
|
||||
),
|
||||
user_conditions=UsersConditions(
|
||||
included_groups=[],
|
||||
excluded_groups=[],
|
||||
included_users=["All"],
|
||||
excluded_users=[],
|
||||
included_roles=[],
|
||||
excluded_roles=[],
|
||||
),
|
||||
client_app_types=[],
|
||||
user_risk_levels=[],
|
||||
),
|
||||
grant_controls=GrantControls(
|
||||
built_in_controls=[ConditionalAccessGrantControl.MFA],
|
||||
operator=GrantControlOperator.OR,
|
||||
authentication_strength=None,
|
||||
),
|
||||
session_controls=SessionControls(
|
||||
persistent_browser=PersistentBrowser(
|
||||
is_enabled=False, mode="always"
|
||||
),
|
||||
sign_in_frequency=SignInFrequency(
|
||||
is_enabled=False,
|
||||
frequency=None,
|
||||
type=None,
|
||||
interval=SignInFrequencyInterval.EVERY_TIME,
|
||||
),
|
||||
),
|
||||
state=ConditionalAccessPolicyState.DISABLED,
|
||||
)
|
||||
}
|
||||
|
||||
check = entra_require_mfa_for_management_api()
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== "No Conditional Access Policy requires MFA for Azure Management API."
|
||||
)
|
||||
assert result[0].resource == {}
|
||||
assert result[0].resource_name == "Conditional Access Policies"
|
||||
assert result[0].resource_id == "conditionalAccessPolicies"
|
||||
assert result[0].location == "global"
|
||||
|
||||
def test_policy_enabled_for_reporting_only(self):
|
||||
"""Test FAIL when the matching policy is only in report-only mode."""
|
||||
policy_id = str(uuid4())
|
||||
display_name = "Require MFA for Azure Management"
|
||||
entra_client = mock.MagicMock
|
||||
entra_client.audited_tenant = "audited_tenant"
|
||||
entra_client.audited_domain = DOMAIN
|
||||
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_m365_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
f"{CHECK_MODULE_PATH}.entra_client",
|
||||
new=entra_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.m365.services.entra.entra_require_mfa_for_management_api.entra_require_mfa_for_management_api import (
|
||||
entra_require_mfa_for_management_api,
|
||||
)
|
||||
from prowler.providers.m365.services.entra.entra_service import (
|
||||
ConditionalAccessPolicy,
|
||||
)
|
||||
|
||||
entra_client.conditional_access_policies = {
|
||||
policy_id: ConditionalAccessPolicy(
|
||||
id=policy_id,
|
||||
display_name=display_name,
|
||||
conditions=Conditions(
|
||||
application_conditions=ApplicationsConditions(
|
||||
included_applications=[AZURE_MANAGEMENT_API_APP_ID],
|
||||
excluded_applications=[],
|
||||
included_user_actions=[],
|
||||
),
|
||||
user_conditions=UsersConditions(
|
||||
included_groups=[],
|
||||
excluded_groups=[],
|
||||
included_users=["All"],
|
||||
excluded_users=[],
|
||||
included_roles=[],
|
||||
excluded_roles=[],
|
||||
),
|
||||
client_app_types=[],
|
||||
user_risk_levels=[],
|
||||
),
|
||||
grant_controls=GrantControls(
|
||||
built_in_controls=[ConditionalAccessGrantControl.MFA],
|
||||
operator=GrantControlOperator.OR,
|
||||
authentication_strength=None,
|
||||
),
|
||||
session_controls=SessionControls(
|
||||
persistent_browser=PersistentBrowser(
|
||||
is_enabled=False, mode="always"
|
||||
),
|
||||
sign_in_frequency=SignInFrequency(
|
||||
is_enabled=False,
|
||||
frequency=None,
|
||||
type=None,
|
||||
interval=SignInFrequencyInterval.EVERY_TIME,
|
||||
),
|
||||
),
|
||||
state=ConditionalAccessPolicyState.ENABLED_FOR_REPORTING,
|
||||
)
|
||||
}
|
||||
|
||||
check = entra_require_mfa_for_management_api()
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"Conditional Access Policy {display_name} targets Azure Management API with MFA but is only in report-only mode."
|
||||
)
|
||||
assert (
|
||||
result[0].resource
|
||||
== entra_client.conditional_access_policies[policy_id].dict()
|
||||
)
|
||||
assert result[0].resource_name == display_name
|
||||
assert result[0].resource_id == policy_id
|
||||
assert result[0].location == "global"
|
||||
|
||||
def test_policy_no_application_conditions(self):
|
||||
"""Test FAIL when the policy has no application conditions."""
|
||||
policy_id = str(uuid4())
|
||||
display_name = "Policy Without App Conditions"
|
||||
entra_client = mock.MagicMock
|
||||
entra_client.audited_tenant = "audited_tenant"
|
||||
entra_client.audited_domain = DOMAIN
|
||||
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_m365_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
f"{CHECK_MODULE_PATH}.entra_client",
|
||||
new=entra_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.m365.services.entra.entra_require_mfa_for_management_api.entra_require_mfa_for_management_api import (
|
||||
entra_require_mfa_for_management_api,
|
||||
)
|
||||
from prowler.providers.m365.services.entra.entra_service import (
|
||||
ConditionalAccessPolicy,
|
||||
)
|
||||
|
||||
entra_client.conditional_access_policies = {
|
||||
policy_id: ConditionalAccessPolicy(
|
||||
id=policy_id,
|
||||
display_name=display_name,
|
||||
conditions=Conditions(
|
||||
application_conditions=None,
|
||||
user_conditions=UsersConditions(
|
||||
included_groups=[],
|
||||
excluded_groups=[],
|
||||
included_users=["All"],
|
||||
excluded_users=[],
|
||||
included_roles=[],
|
||||
excluded_roles=[],
|
||||
),
|
||||
client_app_types=[],
|
||||
user_risk_levels=[],
|
||||
),
|
||||
grant_controls=GrantControls(
|
||||
built_in_controls=[ConditionalAccessGrantControl.MFA],
|
||||
operator=GrantControlOperator.OR,
|
||||
authentication_strength=None,
|
||||
),
|
||||
session_controls=SessionControls(
|
||||
persistent_browser=PersistentBrowser(
|
||||
is_enabled=False, mode="always"
|
||||
),
|
||||
sign_in_frequency=SignInFrequency(
|
||||
is_enabled=False,
|
||||
frequency=None,
|
||||
type=None,
|
||||
interval=SignInFrequencyInterval.EVERY_TIME,
|
||||
),
|
||||
),
|
||||
state=ConditionalAccessPolicyState.ENABLED,
|
||||
)
|
||||
}
|
||||
|
||||
check = entra_require_mfa_for_management_api()
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== "No Conditional Access Policy requires MFA for Azure Management API."
|
||||
)
|
||||
assert result[0].resource == {}
|
||||
assert result[0].resource_name == "Conditional Access Policies"
|
||||
assert result[0].resource_id == "conditionalAccessPolicies"
|
||||
assert result[0].location == "global"
|
||||
|
||||
def test_policy_does_not_target_azure_management_api(self):
|
||||
"""Test FAIL when the policy targets a different application."""
|
||||
policy_id = str(uuid4())
|
||||
display_name = "Require MFA for All Apps"
|
||||
entra_client = mock.MagicMock
|
||||
entra_client.audited_tenant = "audited_tenant"
|
||||
entra_client.audited_domain = DOMAIN
|
||||
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_m365_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
f"{CHECK_MODULE_PATH}.entra_client",
|
||||
new=entra_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.m365.services.entra.entra_require_mfa_for_management_api.entra_require_mfa_for_management_api import (
|
||||
entra_require_mfa_for_management_api,
|
||||
)
|
||||
from prowler.providers.m365.services.entra.entra_service import (
|
||||
ConditionalAccessPolicy,
|
||||
)
|
||||
|
||||
entra_client.conditional_access_policies = {
|
||||
policy_id: ConditionalAccessPolicy(
|
||||
id=policy_id,
|
||||
display_name=display_name,
|
||||
conditions=Conditions(
|
||||
application_conditions=ApplicationsConditions(
|
||||
included_applications=["some-other-app-id"],
|
||||
excluded_applications=[],
|
||||
included_user_actions=[],
|
||||
),
|
||||
user_conditions=UsersConditions(
|
||||
included_groups=[],
|
||||
excluded_groups=[],
|
||||
included_users=["All"],
|
||||
excluded_users=[],
|
||||
included_roles=[],
|
||||
excluded_roles=[],
|
||||
),
|
||||
client_app_types=[],
|
||||
user_risk_levels=[],
|
||||
),
|
||||
grant_controls=GrantControls(
|
||||
built_in_controls=[ConditionalAccessGrantControl.MFA],
|
||||
operator=GrantControlOperator.OR,
|
||||
authentication_strength=None,
|
||||
),
|
||||
session_controls=SessionControls(
|
||||
persistent_browser=PersistentBrowser(
|
||||
is_enabled=False, mode="always"
|
||||
),
|
||||
sign_in_frequency=SignInFrequency(
|
||||
is_enabled=False,
|
||||
frequency=None,
|
||||
type=None,
|
||||
interval=SignInFrequencyInterval.EVERY_TIME,
|
||||
),
|
||||
),
|
||||
state=ConditionalAccessPolicyState.ENABLED,
|
||||
)
|
||||
}
|
||||
|
||||
check = entra_require_mfa_for_management_api()
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== "No Conditional Access Policy requires MFA for Azure Management API."
|
||||
)
|
||||
assert result[0].resource == {}
|
||||
assert result[0].resource_name == "Conditional Access Policies"
|
||||
assert result[0].resource_id == "conditionalAccessPolicies"
|
||||
assert result[0].location == "global"
|
||||
|
||||
def test_policy_no_mfa_grant_control(self):
|
||||
"""Test FAIL when the policy does not require MFA as a grant control."""
|
||||
policy_id = str(uuid4())
|
||||
display_name = "Azure Management No MFA"
|
||||
entra_client = mock.MagicMock
|
||||
entra_client.audited_tenant = "audited_tenant"
|
||||
entra_client.audited_domain = DOMAIN
|
||||
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_m365_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
f"{CHECK_MODULE_PATH}.entra_client",
|
||||
new=entra_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.m365.services.entra.entra_require_mfa_for_management_api.entra_require_mfa_for_management_api import (
|
||||
entra_require_mfa_for_management_api,
|
||||
)
|
||||
from prowler.providers.m365.services.entra.entra_service import (
|
||||
ConditionalAccessPolicy,
|
||||
)
|
||||
|
||||
entra_client.conditional_access_policies = {
|
||||
policy_id: ConditionalAccessPolicy(
|
||||
id=policy_id,
|
||||
display_name=display_name,
|
||||
conditions=Conditions(
|
||||
application_conditions=ApplicationsConditions(
|
||||
included_applications=[AZURE_MANAGEMENT_API_APP_ID],
|
||||
excluded_applications=[],
|
||||
included_user_actions=[],
|
||||
),
|
||||
user_conditions=UsersConditions(
|
||||
included_groups=[],
|
||||
excluded_groups=[],
|
||||
included_users=["All"],
|
||||
excluded_users=[],
|
||||
included_roles=[],
|
||||
excluded_roles=[],
|
||||
),
|
||||
client_app_types=[],
|
||||
user_risk_levels=[],
|
||||
),
|
||||
grant_controls=GrantControls(
|
||||
built_in_controls=[
|
||||
ConditionalAccessGrantControl.COMPLIANT_DEVICE
|
||||
],
|
||||
operator=GrantControlOperator.OR,
|
||||
authentication_strength=None,
|
||||
),
|
||||
session_controls=SessionControls(
|
||||
persistent_browser=PersistentBrowser(
|
||||
is_enabled=False, mode="always"
|
||||
),
|
||||
sign_in_frequency=SignInFrequency(
|
||||
is_enabled=False,
|
||||
frequency=None,
|
||||
type=None,
|
||||
interval=SignInFrequencyInterval.EVERY_TIME,
|
||||
),
|
||||
),
|
||||
state=ConditionalAccessPolicyState.ENABLED,
|
||||
)
|
||||
}
|
||||
|
||||
check = entra_require_mfa_for_management_api()
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== "No Conditional Access Policy requires MFA for Azure Management API."
|
||||
)
|
||||
assert result[0].resource == {}
|
||||
assert result[0].resource_name == "Conditional Access Policies"
|
||||
assert result[0].resource_id == "conditionalAccessPolicies"
|
||||
assert result[0].location == "global"
|
||||
|
||||
def test_policy_does_not_target_all_users(self):
|
||||
"""Test FAIL when the policy does not target all users."""
|
||||
policy_id = str(uuid4())
|
||||
display_name = "Require MFA for Azure Management - Specific Users"
|
||||
entra_client = mock.MagicMock
|
||||
entra_client.audited_tenant = "audited_tenant"
|
||||
entra_client.audited_domain = DOMAIN
|
||||
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_m365_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
f"{CHECK_MODULE_PATH}.entra_client",
|
||||
new=entra_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.m365.services.entra.entra_require_mfa_for_management_api.entra_require_mfa_for_management_api import (
|
||||
entra_require_mfa_for_management_api,
|
||||
)
|
||||
from prowler.providers.m365.services.entra.entra_service import (
|
||||
ConditionalAccessPolicy,
|
||||
)
|
||||
|
||||
entra_client.conditional_access_policies = {
|
||||
policy_id: ConditionalAccessPolicy(
|
||||
id=policy_id,
|
||||
display_name=display_name,
|
||||
conditions=Conditions(
|
||||
application_conditions=ApplicationsConditions(
|
||||
included_applications=[AZURE_MANAGEMENT_API_APP_ID],
|
||||
excluded_applications=[],
|
||||
included_user_actions=[],
|
||||
),
|
||||
user_conditions=UsersConditions(
|
||||
included_groups=[],
|
||||
excluded_groups=[],
|
||||
included_users=[str(uuid4())],
|
||||
excluded_users=[],
|
||||
included_roles=[],
|
||||
excluded_roles=[],
|
||||
),
|
||||
client_app_types=[],
|
||||
user_risk_levels=[],
|
||||
),
|
||||
grant_controls=GrantControls(
|
||||
built_in_controls=[ConditionalAccessGrantControl.MFA],
|
||||
operator=GrantControlOperator.OR,
|
||||
authentication_strength=None,
|
||||
),
|
||||
session_controls=SessionControls(
|
||||
persistent_browser=PersistentBrowser(
|
||||
is_enabled=False, mode="always"
|
||||
),
|
||||
sign_in_frequency=SignInFrequency(
|
||||
is_enabled=False,
|
||||
frequency=None,
|
||||
type=None,
|
||||
interval=SignInFrequencyInterval.EVERY_TIME,
|
||||
),
|
||||
),
|
||||
state=ConditionalAccessPolicyState.ENABLED,
|
||||
)
|
||||
}
|
||||
|
||||
check = entra_require_mfa_for_management_api()
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== "No Conditional Access Policy requires MFA for Azure Management API."
|
||||
)
|
||||
assert result[0].resource == {}
|
||||
assert result[0].resource_name == "Conditional Access Policies"
|
||||
assert result[0].resource_id == "conditionalAccessPolicies"
|
||||
assert result[0].location == "global"
|
||||
|
||||
def test_policy_enabled_with_all_apps_included(self):
|
||||
"""Test PASS when an enabled policy targets 'All' apps with MFA, covering Azure Management API."""
|
||||
policy_id = str(uuid4())
|
||||
display_name = "Require MFA for All Apps"
|
||||
entra_client = mock.MagicMock
|
||||
entra_client.audited_tenant = "audited_tenant"
|
||||
entra_client.audited_domain = DOMAIN
|
||||
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_m365_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
f"{CHECK_MODULE_PATH}.entra_client",
|
||||
new=entra_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.m365.services.entra.entra_require_mfa_for_management_api.entra_require_mfa_for_management_api import (
|
||||
entra_require_mfa_for_management_api,
|
||||
)
|
||||
from prowler.providers.m365.services.entra.entra_service import (
|
||||
ConditionalAccessPolicy,
|
||||
)
|
||||
|
||||
entra_client.conditional_access_policies = {
|
||||
policy_id: ConditionalAccessPolicy(
|
||||
id=policy_id,
|
||||
display_name=display_name,
|
||||
conditions=Conditions(
|
||||
application_conditions=ApplicationsConditions(
|
||||
included_applications=["All"],
|
||||
excluded_applications=[],
|
||||
included_user_actions=[],
|
||||
),
|
||||
user_conditions=UsersConditions(
|
||||
included_groups=[],
|
||||
excluded_groups=[],
|
||||
included_users=["All"],
|
||||
excluded_users=[],
|
||||
included_roles=[],
|
||||
excluded_roles=[],
|
||||
),
|
||||
client_app_types=[],
|
||||
user_risk_levels=[],
|
||||
),
|
||||
grant_controls=GrantControls(
|
||||
built_in_controls=[ConditionalAccessGrantControl.MFA],
|
||||
operator=GrantControlOperator.OR,
|
||||
authentication_strength=None,
|
||||
),
|
||||
session_controls=SessionControls(
|
||||
persistent_browser=PersistentBrowser(
|
||||
is_enabled=False, mode="always"
|
||||
),
|
||||
sign_in_frequency=SignInFrequency(
|
||||
is_enabled=False,
|
||||
frequency=None,
|
||||
type=None,
|
||||
interval=SignInFrequencyInterval.EVERY_TIME,
|
||||
),
|
||||
),
|
||||
state=ConditionalAccessPolicyState.ENABLED,
|
||||
)
|
||||
}
|
||||
|
||||
check = entra_require_mfa_for_management_api()
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "PASS"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"Conditional Access Policy {display_name} requires MFA for Azure Management API."
|
||||
)
|
||||
assert (
|
||||
result[0].resource
|
||||
== entra_client.conditional_access_policies[policy_id].dict()
|
||||
)
|
||||
assert result[0].resource_name == display_name
|
||||
assert result[0].resource_id == policy_id
|
||||
assert result[0].location == "global"
|
||||
|
||||
def test_policy_enabled_and_compliant(self):
|
||||
"""Test PASS when an enabled policy requires MFA for Azure Management API."""
|
||||
policy_id = str(uuid4())
|
||||
display_name = "Require MFA for Azure Management"
|
||||
entra_client = mock.MagicMock
|
||||
entra_client.audited_tenant = "audited_tenant"
|
||||
entra_client.audited_domain = DOMAIN
|
||||
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_m365_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
f"{CHECK_MODULE_PATH}.entra_client",
|
||||
new=entra_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.m365.services.entra.entra_require_mfa_for_management_api.entra_require_mfa_for_management_api import (
|
||||
entra_require_mfa_for_management_api,
|
||||
)
|
||||
from prowler.providers.m365.services.entra.entra_service import (
|
||||
ConditionalAccessPolicy,
|
||||
)
|
||||
|
||||
entra_client.conditional_access_policies = {
|
||||
policy_id: ConditionalAccessPolicy(
|
||||
id=policy_id,
|
||||
display_name=display_name,
|
||||
conditions=Conditions(
|
||||
application_conditions=ApplicationsConditions(
|
||||
included_applications=[AZURE_MANAGEMENT_API_APP_ID],
|
||||
excluded_applications=[],
|
||||
included_user_actions=[],
|
||||
),
|
||||
user_conditions=UsersConditions(
|
||||
included_groups=[],
|
||||
excluded_groups=[],
|
||||
included_users=["All"],
|
||||
excluded_users=[],
|
||||
included_roles=[],
|
||||
excluded_roles=[],
|
||||
),
|
||||
client_app_types=[],
|
||||
user_risk_levels=[],
|
||||
),
|
||||
grant_controls=GrantControls(
|
||||
built_in_controls=[ConditionalAccessGrantControl.MFA],
|
||||
operator=GrantControlOperator.OR,
|
||||
authentication_strength=None,
|
||||
),
|
||||
session_controls=SessionControls(
|
||||
persistent_browser=PersistentBrowser(
|
||||
is_enabled=False, mode="always"
|
||||
),
|
||||
sign_in_frequency=SignInFrequency(
|
||||
is_enabled=False,
|
||||
frequency=None,
|
||||
type=None,
|
||||
interval=SignInFrequencyInterval.EVERY_TIME,
|
||||
),
|
||||
),
|
||||
state=ConditionalAccessPolicyState.ENABLED,
|
||||
)
|
||||
}
|
||||
|
||||
check = entra_require_mfa_for_management_api()
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "PASS"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"Conditional Access Policy {display_name} requires MFA for Azure Management API."
|
||||
)
|
||||
assert (
|
||||
result[0].resource
|
||||
== entra_client.conditional_access_policies[policy_id].dict()
|
||||
)
|
||||
assert result[0].resource_name == display_name
|
||||
assert result[0].resource_id == policy_id
|
||||
assert result[0].location == "global"
|
||||
Reference in New Issue
Block a user