From 70f6a731c9b8caf4f15ea5b9354b55908ae8ce60 Mon Sep 17 00:00:00 2001 From: Andrew Huynh <113476170+ahuynhMITRE@users.noreply.github.com> Date: Mon, 15 May 2023 10:12:03 -0400 Subject: [PATCH 01/33] Structural baseline updates (cleaned up) (#334) * Update aad.md all updates * Update defender.md all updates * Update exchange.md all updates * Rename exchange.md to exo.md * Update onedrive.md * Update powerbi.md all updates * Update powerplatform.md all updates * Update sharepoint.md all updates * Update teams.md all updates * Update baselines/defender.md good catch! Co-authored-by: Addam Schroll <108814318+schrolla@users.noreply.github.com> * Update baselines/powerbi.md Co-authored-by: Addam Schroll <108814318+schrolla@users.noreply.github.com> * Update baselines/powerbi.md Co-authored-by: Addam Schroll <108814318+schrolla@users.noreply.github.com> * Update baselines/aad.md Co-authored-by: Addam Schroll <108814318+schrolla@users.noreply.github.com> * Update aad.md referenced old policy number * Update powerbi.md --------- Co-authored-by: Addam Schroll <108814318+schrolla@users.noreply.github.com> --- baselines/aad.md | 416 +++++++++++++++++------------- baselines/defender.md | 395 +++++++++++++++++----------- baselines/{exchange.md => exo.md} | 372 ++++++++++++++++---------- baselines/onedrive.md | 122 +++++---- baselines/powerbi.md | 300 +++++++-------------- baselines/powerplatform.md | 99 ++++--- baselines/sharepoint.md | 94 ++++--- baselines/teams.md | 330 +++++++++++++----------- 8 files changed, 1173 insertions(+), 955 deletions(-) rename baselines/{exchange.md => exo.md} (78%) diff --git a/baselines/aad.md b/baselines/aad.md index d5c65398e0..8052d30c32 100644 --- a/baselines/aad.md +++ b/baselines/aad.md @@ -1,6 +1,6 @@ -# 1. Introduction +# Introduction -## 1.1 Key Terminology +## Key Terminology The following are key terms and descriptions used in this document. @@ -17,7 +17,7 @@ hosts the M365 resources being used. [home tenant](https://docs.microsoft.com/en-us/azure/active-directory/external-identities/authentication-conditional-access) is the one that owns the external user’s (e.g., guest) account. -## 1.2 Assumptions +## Assumptions The agency has created emergency access accounts in Azure AD and implemented strong security measures to protect the credentials of those @@ -35,9 +35,9 @@ or [G3](https://www.microsoft.com/en-us/microsoft-365/government) license level. Therefore, only licenses not included in E3/G3 are listed. -## 1.3 Common guidance +## Common guidance -### 1.3.1 Conditional Access Policies +### Conditional Access Policies This section provides common guidance that should be applied when implementing baseline instructions related to Azure AD Conditional @@ -52,7 +52,7 @@ assist with running test simulations is the [What If tool](https://docs.microsof Microsoft also describes [Conditional Access insights and reporting features](https://docs.microsoft.com/en-us/azure/active-directory/conditional-access/howto-conditional-access-insights-reporting) that can assist with testing. -### 1.3.2 Azure AD Privileged Identity Management +### Azure AD Privileged Identity Management Some of the guidance in this baseline document leverages specific features of the Azure AD Privileged Identity Management (PIM) service to @@ -63,7 +63,7 @@ Azure AD PIM, there are third-party vendors that provide products or services with privileged access management capabilities that can be leveraged if an agency chooses to do so. -## 1.4 Resources +## Resources License Compliance and Copyright @@ -74,33 +74,35 @@ and GitHub repositories. The respective documents are subject to copyright and are adapted under the terms of the Creative Commons Attribution 4.0 International license. Source documents are linked throughout this -document. The United States government has adapted selections of these +document. The United States government has adpted selections of these documents to develop innovative and scalable configuration standards to strengthen the security of widely used cloud-based software services. -# 2. Baseline +# Baseline -## 2.1 Legacy Authentication SHALL Be Blocked +## 1. Legacy Authentication Block legacy authentication protocols using a conditional access policy. Legacy authentication does not support multifactor authentication (MFA), which is required to minimize the impact of user credential theft. -### 2.1.1 Policy +### Policies +#### MS.AAD.1.1v1 +Legacy authentication SHALL be blocked. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- Legacy authentication SHALL be blocked. - -### 2.1.2 Resources +### Resources - [Conditional Access: Block Legacy Authentication](https://docs.microsoft.com/en-us/azure/active-directory/conditional-access/howto-conditional-access-policy-block-legacy) - [Five steps to securing your identity infrastructure](https://docs.microsoft.com/en-us/azure/security/fundamentals/steps-secure-identity) -### 2.1.3 License Requirements +### License Requirements - N/A -### 2.1.4 Implementation +### Implementation 1. Before blocking legacy authentication across the entire application base, follow [these instructions](https://docs.microsoft.com/en-us/azure/active-directory/conditional-access/block-legacy-authentication#identify-legacy-authentication-use) @@ -112,7 +114,7 @@ which is required to minimize the impact of user credential theft. to block legacy authentication. **Note:** The instructions suggest using Report-only mode which will not block legacy authentication. -## 2.2 High Risk Users SHALL Be Blocked +## 2. High Risk Users Azure AD Identity Protection uses various signals to detect the risk level for each user and determine if an account has likely been @@ -123,14 +125,18 @@ with a block is implemented, if a high-risk user attempts to login, the user will receive an error message with instructions to contact the administrator to re-enable their access. -### 2.2.1 Policy - -- Users detected as high risk SHALL be blocked. +### Policies +#### MS.AAD.2.1v1 +Users detected as high risk SHALL be blocked. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- A notification SHOULD be sent to the administrator when high-risk - users are detected. +#### MS.AAD.2.2v1 +A notification SHOULD be sent to the administrator when high-risk users are detected. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -### 2.2.2 Resources +### Resources - [Conditional Access: User risk-based Conditional Access](https://docs.microsoft.com/en-us/azure/active-directory/conditional-access/howto-conditional-access-policy-risk-user) @@ -143,13 +149,13 @@ administrator to re-enable their access. - [Five steps to securing your identity infrastructure](https://docs.microsoft.com/en-us/azure/security/fundamentals/steps-secure-identity) -### 2.2.3 License Requirements +### License Requirements - Requires an AAD P2 license -### 2.2.4 Implementation +### Implementation -**Policy \#1:** +**Policy MS.AAD.2.1v1:** 1. To create the conditional access policy that implements the block for users at the risk level of High, follow the instructions in the @@ -158,7 +164,7 @@ administrator to re-enable their access. 2. Under **Access Controls** -\> **Grant**, select **Block access**. -**Policy \#2**: +**Policy MS.AAD.2.2v1**: 1. Follow the instructions in the [Configure users at risk detected alerts](https://docs.microsoft.com/en-us/azure/active-directory/identity-protection/howto-identity-protection-configure-notifications#configure-users-at-risk-detected-alerts) section to configure Azure AD Identity Protection to email the @@ -166,17 +172,19 @@ administrator to re-enable their access. determined to be high risk so that they can review and respond to threats. -## 2.3 High Risk Sign-ins SHALL Be Blocked +## 3. High Risk Sign-ins Azure AD Identity Protection uses various signals to detect the risk level for each user sign-in. Sign-ins detected as high risk are to be blocked via Conditional Access. -### 2.3.1 Policy - +### Policies +#### MS.AAD.3.1v1 Sign-ins detected as high risk SHALL be blocked. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -### 2.3.2 Resources +### Resources - [Conditional Access: Sign-in risk-based Conditional Access](https://docs.microsoft.com/en-us/azure/active-directory/conditional-access/howto-conditional-access-policy-risk) @@ -191,11 +199,11 @@ Sign-ins detected as high risk SHALL be blocked. Protection](https://docs.microsoft.com/en-us/azure/active-directory/identity-protection/concept-identity-protection-user-experience) (Examples of how these policies are applied in practice) -### 2.3.3 License Requirements +### License Requirements - Requires an AAD P2 license -### 2.3.4 Implementation +### Implementation To create the conditional access policy that implements the block for sign-ins at the risk level of **High**, follow the instructions in the @@ -218,7 +226,7 @@ locations. Azure AD Identity Protection considers the Trusted Location data when it calculates sign-in risk, and this may help to prevent users signing in from legitimate locations from being flagged as high risk. -## 2.4 Phishing-Resistant Multifactor Authentication SHALL Be Required for All Users +## 4. Phishing-Resistant Multifactor Authentication Phishing-resistant multifactor authentication protects against sophisticated phishing attacks. Recognizing the significant risk these @@ -242,11 +250,14 @@ alt="Weak MFA (SMS/Voice) Stronger MFA (Push Notifications, Software OTP, Hardwa Figure 1: Options for Weak MFA, Stronger MFA Options, and Strongest MFA -### 2.4.1 Policy +### Policies +#### MS.AAD.4.1v1 +MFA SHALL be required for all users. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- MFA SHALL be required for all users. - -- Phishing-resistant MFA SHALL be used for all users. +#### MS.AAD.4.2v1 +Phishing-resistant MFA SHALL be used for all users. - Phishing-resistant methods: @@ -259,8 +270,11 @@ Figure 1: Options for Weak MFA, Stronger MFA Options, and Strongest MFA - Federal Personal Identity Verification (PIV) card (Federated from agency Active Directory or other identity provider) +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- If phishing-resistant MFA cannot be used, an MFA method from the list +#### MS.AAD.4.3v1 +If phishing-resistant MFA cannot be used, an MFA method from the list below SHALL be used in the interim: - Microsoft Authenticator (Push Notifications) @@ -277,10 +291,15 @@ Figure 1: Options for Weak MFA, Stronger MFA Options, and Strongest MFA - Software Tokens One-Time Password (OTP) – This option is commonly implemented using mobile phone authenticator apps - Hardware tokens OTP +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- SMS or Voice as the MFA method SHALL NOT be used. +#### MS.AAD.4.4v1 +SMS or Voice as the MFA method SHALL NOT be used. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -### 2.4.2 Resources +### Resources - [What authentication and verification methods are available in Azure Active @@ -297,11 +316,11 @@ Figure 1: Options for Weak MFA, Stronger MFA Options, and Strongest MFA - [M-22-09 Federal Zero Trust Strategy](https://www.whitehouse.gov/wp-content/uploads/2022/01/M-22-09.pdf) -### 2.4.3 License Requirements +### License Requirements - N/A -### 2.4.4 Implementation +### Implementation **Policy \#1:** @@ -414,34 +433,39 @@ Passwordless Sign-in) or Microsoft Authenticator (Push Notifications)** 5. Under **verification options**, make sure that **Text message to phone** and **Call to phone** are **disabled**. -## 2.5 Azure AD logs SHALL Be Collected +## 5. Azure AD logs Configure Azure AD to send critical logs to the agency’s centralized SIEM and to CISA’s central analysis system so that they can be audited and queried. Configure Azure AD to send logs to a storage account and retain them for when incident response is needed. -### 2.5.1 Policy - -- The following critical logs SHALL be sent at a minimum: AuditLogs, - SignInLogs, RiskyUsers, UserRiskEvents, NonInteractiveUserSignInLogs, - ServicePrincipalSignInLogs, ADFSSignInLogs, RiskyServicePrincipals, - ServicePrincipalRiskEvents. +### Policies +#### MS.AAD.5.1v1 +The following critical logs SHALL be sent at a minimum: AuditLogs, SignInLogs, RiskyUsers, UserRiskEvents, NonInteractiveUserSignInLogs, ServicePrincipalSignInLogs, ADFSSignInLogs, RiskyServicePrincipals, ServicePrincipalRiskEvents. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- If managed identities are used for Azure resources, also include the - ManagedIdentitySignInLogs log type. +#### MS.AAD.5.2v1 +If managed identities are used for Azure resources, logs SHALL include the ManagedIdentitySignInLogs log type. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- If the Azure AD Provisioning Service is used to provision users to - SaaS apps or other systems, also include the ProvisioningLogs log - type. +#### MS.AAD.5.3v1 +If the Azure AD Provisioning Service is used to provision users to SaaS apps or other systems, also include the ProvisioningLogs log type. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- The logs SHALL be sent to the agency’s SOC for monitoring. +#### MS.AAD.5.4v1 +The logs SHALL be sent to the agencys SOC for monitoring. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -### 2.5.2 Resources +### Resources - [Everything you wanted to know about Security and Audit Logging in Office @@ -458,11 +482,11 @@ retain them for when incident response is needed. Architecture Volume 2](https://www.cisa.gov/sites/default/files/publications/NCPS%20Cloud%20Interface%20RA%20Volume%20Two%202021-06-11%20%28508%20COMPLIANT%29.pdf) -### 2.5.3 License Requirements +### License Requirements - N/A -### 2.5.4 Implementation +### Implementation [Follow these instructions](https://docs.microsoft.com/en-us/azure/active-directory/reports-monitoring/quickstart-azure-monitor-route-logs-to-storage-account) to configure sending the logs to a storage account: @@ -478,26 +502,27 @@ to configure sending the logs to a storage account: 4. In the **Retention** field enter “365” days. -## 2.6 Only Administrators SHALL Be Allowed to Register Third-Party Applications +## 6. Register Third-Party Applications Ensure that only administrators can register third-party applications that can access the tenant. -### 2.6.1 Policy - -- Only administrators SHALL be allowed to register third-party - applications. +### Policies +#### MS.AAD.6.1v1 +Only administrators SHALL be allowed to register third-party applications. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -### 2.6.2 Resources +### Resources - [Restrict Application Registration for Non-Privileged Users](https://www.trendmicro.com/cloudoneconformity/knowledge-base/azure/ActiveDirectory/users-can-register-applications.html) -### 2.6.3 License Requirements +### License Requirements - N/A -### 2.6.4 Implementation +### Implementation 1. In the **Azure Portal**, navigate to **Azure Active Directory.** @@ -512,7 +537,7 @@ that can access the tenant. 5. Click **Save**. -## 2.7 Non-admin Users SHALL Be Prevented from Providing Consent to Third-Party Applications +## 7. Consenting to Third-Party Applications Ensure that only administrators can consent to third-party applications and only administrators can control which permissions are granted. An @@ -521,17 +546,24 @@ will be blocked when they try to access an application that requires permissions to access organizational data. Develop a process for approving and managing third-party applications. -### 2.7.1 Policy - -- Only administrators SHALL be allowed to consent to third-party +### Policies +#### MS.AAD.7.1v1 +Only administrators SHALL be allowed to consent to third-party applications. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- An admin consent workflow SHALL be configured. +#### MS.AAD.7.2v1 +An admin consent workflow SHALL be configured. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- Group owners SHALL NOT be allowed to consent to third-party - applications. +#### MS.AAD.7.3v1 +Group owners SHALL NOT be allowed to consent to third-party applications. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -### 2.7.2 Resources +### Resources - [Enforce Administrators to Provide Consent for Apps Before Use](https://www.trendmicro.com/cloudoneconformity/knowledge-base/azure/ActiveDirectory/users-can-consent-to-apps-accessing-company-data-on-their-behalf.html) @@ -539,11 +571,11 @@ approving and managing third-party applications. - [Configure the admin consent workflow](https://docs.microsoft.com/en-us/azure/active-directory/manage-apps/configure-admin-consent-workflow) -### 2.7.3 License Requirements +### License Requirements - N/A -### 2.7.4 Implementation +### Implementation 1. In the **Azure Portal**, navigate to **Azure Active Directory.** @@ -569,23 +601,25 @@ approving and managing third-party applications. 9. Under **Admin consent requests** -\> **Users can request admin consent to apps they are unable to consent to**, select **Yes.** -10. Under **Who can review admin consent requests**​, select the group +10. Under **Who can review admin consent requests**, select the group created in step two that is responsible for reviewing and adjudicating app requests. 11. Click **Save** -## 2.8 Passwords SHALL NOT Expire +## 8. Passwords Ensure that user passwords do not expire. Both the National Institute of Standards and Technology (NIST) and Microsoft emphasize MFA because they indicate that mandated password changes make user accounts less secure. -### 2.8.1 Policy - -- User passwords SHALL NOT expire. +### Policies +#### MS.AAD.8.1v1 +User passwords SHALL NOT expire. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -### 2.8.2 Resources +### Resources - [Password policy recommendations - Microsoft 365 admin \| Microsoft Docs](https://docs.microsoft.com/en-us/microsoft-365/admin/misc/password-policy-recommendations?view=o365-worldwide#password-expiration-requirements-for-users) @@ -596,26 +630,28 @@ indicate that mandated password changes make user accounts less secure. - [NIST Special Publication 800-63B - Digital Identity Guidelines](https://pages.nist.gov/800-63-3/sp800-63b.html) -### 2.8.3 License Requirements +### License Requirements - N/A -### 2.8.4 Implementation +### Implementation [Follow the instructions at this link](https://docs.microsoft.com/en-us/microsoft-365/admin/manage/set-password-expiration-policy?view=o365-worldwide#set-password-expiration-policy) to configure the password expiration policy. -## 2.9 Session Length SHALL Be Limited +## 9. Session Length To reduce the risk of credential theft during user sessions, configure the sign-in frequency to a limited period of time. -### 2.9.1 Policy +### Policies +#### MS.AAD.9.1v1 +Sign-in frequency SHALL be configured to 12 hours. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- Sign-in frequency SHALL be configured to 12 hours. - -### 2.9.2 Resources +### Resources - [Configure authentication session management with Conditional Access](https://docs.microsoft.com/en-us/azure/active-directory/conditional-access/howto-conditional-access-session-lifetime) @@ -623,11 +659,11 @@ the sign-in frequency to a limited period of time. - [NIST Special Publication 800-63B - Digital Identity Guidelines](https://pages.nist.gov/800-63-3/sp800-63b.html) -### 2.9.3 License Requirements +### License Requirements - N/A -### 2.9.4 Implementation +### Implementation [Follow the instructions at this link](https://docs.microsoft.com/en-us/azure/active-directory/conditional-access/howto-conditional-access-session-lifetime#policy-1-sign-in-frequency-control) @@ -642,26 +678,28 @@ frequency, 3. Set the **Access Controls** -\> **Session** -\> **Sign-in frequency** to a value of “12 hours”. -## 2.10 Browser Sessions SHALL NOT Be Persistent +## 10. Browser Sessions To reduce the risk of credential theft during user sessions, disallow persistent browser sessions. -### 2.10.1 Policy - -- Browser sessions SHALL not be persistent. +### Policies +#### MS.AAD.10.1v1 +Browser sessions SHALL not be persistent. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -### 2.10.2 Resources +### Resources - [Configure authentication session management with Conditional Access](https://docs.microsoft.com/en-us/azure/active-directory/conditional-access/howto-conditional-access-session-lifetime) - [NIST Special Publication 800-63B - Digital Identity Guidelines](https://pages.nist.gov/800-63-3/sp800-63b.html) -### 2.10.3 License Requirements +### License Requirements - N/A -### 2.10.4 Implementation +### Implementation [Follow the instructions at this link](https://docs.microsoft.com/en-us/azure/active-directory/conditional-access/howto-conditional-access-session-lifetime#policy-2-persistent-browser-session) to implement the conditional access policy that prevents persistent @@ -674,7 +712,7 @@ browser sessions. 3. Set the **Access Controls -**\> **Session** -\> **Persistent browser session** to **Never persistent.** -## 2.11 The Number of Users with the Highest Privilege Roles SHALL Be Limited +## 11. Global Administrators Global Administrator is the highest privileged role in Azure AD because it provides unfettered access to the tenant. Therefore, if a user’s @@ -684,23 +722,24 @@ users that are assigned the role of Global Administrator. Assign users to finer-grained administrative roles that they need to perform their duties instead of being assigned the Global Administrator role. -### 2.11.1 Policy - -- A minimum of two users and a maximum of four users SHALL be - provisioned with the Global Administrator role. +### Policies +#### MS.AAD.11.1v1 +A minimum of two users and a maximum of four users SHALL be provisioned with the Global Administrator role. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -### 2.11.2 Resources +### Resources - [Best practices for Azure AD roles (Limit number of Global Administrators to less than 5)](https://docs.microsoft.com/en-us/azure/active-directory/roles/best-practices#5-limit-the-number-of-global-administrators-to-less-than-5) - [About admin roles](https://docs.microsoft.com/en-us/microsoft-365/admin/add-users/about-admin-roles?view=o365-worldwide) -### 2.11.3 License Requirements +### License Requirements - N/A -### 2.11.4 Implementation +### Implementation **Policy bullet \#1:** @@ -754,21 +793,20 @@ duties instead of being assigned the Global Administrator role. Administrator. Once the roles are reassigned according to the guidance, check the score again after 48 hours to ensure compliance. -## 2.12 Highly Privileged User Accounts SHALL Be Cloud-Only +## 12. Highly Privileged User Accounts Assign users that need to perform highly privileged tasks to cloud-only Azure AD accounts to minimize the collateral damage of an on-premises identity compromise.[^1] -### 2.12.1 Policy +### Policies +#### MS.AAD.12.1v1 +Users that need to be assigned to highly privileged Azure AD roles SHALL be provisioned cloud-only accounts that are separate from the on-premises directory or other federated identity providers. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- Users that need to be assigned to highly privileged Azure AD roles - SHALL be provisioned cloud-only accounts that are separate from the - on-premises directory or other federated identity providers. - -- The following built-in Azure AD roles are considered highly privileged - at a minimum. Additional built-in roles that are considered highly - privileged in the agency’s environment can be added to this list: +#### MS.AAD.12.2v1 +The following built-in Azure AD roles are considered highly privileged at a minimum. Additional built-in roles that are considered highly privileged in the agency's environment can be added to this list: - Global Administrator @@ -784,32 +822,36 @@ identity compromise.[^1] - Application Administrator - - Cloud Application Administrator + - Cloud Application Administrator. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -### 2.12.2 Resources +### Resources - [Securing privileged access for hybrid and cloud deployments in Azure AD](https://docs.microsoft.com/en-us/azure/active-directory/roles/security-planning#ensure-separate-user-accounts-and-mail-forwarding-for-global-administrator-accounts) -### 2.12.3 License Requirements +### License Requirements - N/A -### 2.12.4 Implementation +### Implementation Review [these](https://docs.microsoft.com/en-us/azure/active-directory/roles/view-assignments) instructions to identify users assigned to highly privileged roles and verify the account does not exist outside Azure AD. -## 2.13 Multifactor Authentication SHALL Be Required for Highly Privileged Roles +## 13. Multifactor Authentication for Highly Privileged Roles Require users to perform MFA to access highly privileged roles. This configuration provides a backup policy to enforce MFA for highly privileged users in case the main conditional access policy—which requires MFA for all users—is disabled or misconfigured. -### 2.13.1 Policy - -- MFA SHALL be required for user access to highly privileged roles. +### Policies +#### MS.AAD.13.1v1 +MFA SHALL be required for user access to highly privileged roles. +- _Rationale:_ TODO +- _Last modified:_ June 2023 @@ -820,17 +862,17 @@ requires MFA for all users—is disabled or misconfigured. additional built-in roles that are considered highly privileged in the agency’s environment based on its risk tolerance. -### 2.13.2 Resources +### Resources - [Five steps to securing your identity infrastructure](https://docs.microsoft.com/en-us/azure/security/fundamentals/steps-secure-identity) - [M-22-09 Federal Zero Trust Strategy](https://www.whitehouse.gov/wp-content/uploads/2022/01/M-22-09.pdf) -### 2.13.3 License Requirements +### License Requirements - N/A -### 2.13.4 Implementation +### Implementation [Follow these instructions](https://docs.microsoft.com/en-us/azure/active-directory/conditional-access/howto-conditional-access-policy-all-users-mfa) to create a conditional access policy requiring MFA for access, but @@ -843,12 +885,12 @@ policy to privileged roles. 2. Under **Include**, choose **Select users and groups**, then click the **Directory roles** checkbox. Select each of the roles listed in - the baseline statement, [Highly Privileged User Accounts SHALL be Cloud-Only](#2121-Policy). + the baseline statement, [Highly Privileged User Accounts SHALL be Cloud-Only](Policy MS.AAD.12.1v1). 3. Under **Exclude**, follow Microsoft’s guidance from the previously provided instructions link. -## 2.14 Users Assigned to Highly Privileged Roles SHALL NOT Have Permanent Permissions +## 14. Permanent Permissions Do not assign users to highly privileged roles using permanent active role assignments. Instead, assign users to eligible role assignments in @@ -859,33 +901,30 @@ upon expiration. **Note**: Although Azure AD PIM is referenced in the implementation instructions, an equivalent third-party PAM service may be used instead. -### 2.14.1 Policy - -- Permanent active role assignments SHALL NOT be allowed for highly - privileged roles. Active assignments SHALL have an expiration period. - - Refer to the baseline statement, [Highly Privileged User Accounts SHALL be Cloud-Only](#2121-Policy), - for a recommended minimum list of Azure AD built-in roles that are - considered highly privileged. It is also possible to designate - additional built-in roles that are considered highly privileged in the - agency’s environment based on its risk tolerance. +### Policies +#### MS.AAD.14.1v1 +Permanent active role assignments SHALL NOT be allowed for highly privileged roles. Active assignments SHALL have an expiration period. +- Refer to the baseline statement, [Highly Privileged User Accounts SHALL be Cloud-Only](#2121-Policy), for a recommended minimum list of Azure AD built-in roles that are considered highly privileged. It is also possible to designate additional built-in roles that are considered highly privileged in the agency’s environment based on its risk tolerance. +- _Rationale:_ TODO +- _Last modified:_ June 2023 +#### MS.AAD.14.2v1 +Provisioning of users to highly privileged roles SHALL NOT occur outside of a PAM system, such as the Azure AD PIM service, because this bypasses the controls the PAM system provides. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- Provisioning of users to highly privileged roles SHALL NOT occur - outside of a PAM system, such as the Azure AD PIM service, because - this bypasses the controls the PAM system provides. - -### 2.14.2 Resources +### Resources - [Assign Azure AD roles in Privileged Identity Management](https://docs.microsoft.com/en-us/azure/active-directory/privileged-identity-management/pim-how-to-add-role-to-user) -### 2.14.3 License Requirements +### License Requirements - Use of an Azure AD PIM or an equivalent third-party PAM service. - Azure AD PIM requires an AAD P2 license -### 2.14.4 Implementation +### Implementation Note: Any parts of the following implementation instructions that reference the Azure AD PIM service will vary if using a third-party PAM @@ -951,7 +990,7 @@ system. non-compliant role assignments and then recreate them using the PIM service. -## 2.15 Activation of Highly Privileged Roles SHOULD Require Approval +## 15. Activation of Highly Privileged Roles Require approval for a user to activate a highly privileged role, such as Global Administrator. This makes it more challenging for an attacker @@ -961,9 +1000,11 @@ ensures that privileged access is monitored closely. **Note**: Although Azure AD PIM is referenced in the implementation instructions, an equivalent third-party PAM service may be used instead. -### 2.15.1 Policy - -- Activation of highly privileged roles SHOULD require approval +### Policies +#### MS.AAD.15.1v1 +Activation of highly privileged roles SHOULD require approval. +- _Rationale:_ TODO +- _Last modified:_ June 2023 @@ -973,17 +1014,17 @@ instructions, an equivalent third-party PAM service may be used instead. that are considered highly privileged in the agency’s environment based on its risk tolerance. -### 2.15.2 Resources +### Resources - [Approve or deny requests for Azure AD roles in Privileged Identity Management](https://docs.microsoft.com/en-us/azure/active-directory/privileged-identity-management/azure-ad-pim-approval-workflow) -### 2.15.3 License Requirements +### License Requirements - Use an Azure AD PIM or an equivalent third-party PAM service - Azure AD PIM requires an AAD P2 license -### 2.15.4 Implementation +### Implementation **Note**: Any parts of the following implementation instructions that reference the Azure AD PIM service will vary if using a third-party PAM @@ -1020,7 +1061,7 @@ system. Approvers**, and then click **Select**. 6. Click **Update**. -## 2.16 Highly Privileged Role Assignment and Activation SHALL Be Monitored +## 16. Highly Privileged Role Assignment and Activation Since many cyber attacks leverage privileged access, it is imperative to closely monitor the assignment and activation of the highest privileged @@ -1031,10 +1072,11 @@ privileged role. Note: Although Azure AD PIM is referenced in the implementation instructions, an equivalent third-party PAM service may be used instead. -### 2.16.1 Policy - -- Eligible and Active highly privileged role assignments SHALL trigger - an alert. +### Policies +#### MS.AAD.16.1v1 +Eligible and Active highly privileged role assignments SHALL trigger an alert. +- _Rationale:_ TODO +- _Last modified:_ June 2023 @@ -1046,11 +1088,16 @@ instructions, an equivalent third-party PAM service may be used instead. -- User activation of the Global Administrator role SHALL trigger an +#### MS.AAD.16.2v1 +User activation of the Global Administrator role SHALL trigger an alert. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- User activation of other highly privileged roles SHOULD trigger an - alert. +#### MS.AAD.16.3v1 +User activation of other highly privileged roles SHOULD trigger an alert. +- _Rationale:_ TODO +- _Last modified:_ June 2023 @@ -1064,17 +1111,17 @@ instructions, an equivalent third-party PAM service may be used instead. versus the mailbox configured for the Global Administrator role, which should be monitored closely since that role is sensitive. -### 2.16.2 Resources +### Resources - [Assign Azure AD roles in Privileged Identity Management](https://docs.microsoft.com/en-us/azure/active-directory/privileged-identity-management/pim-how-to-add-role-to-user) -### 2.16.3 License Requirements +### License Requirements - Use an Azure AD PIM or an equivalent third-party PAM service. - Azure AD PIM requires an AAD P2 license -### 2.16.4 Implementation +### Implementation Note: Any parts of the following implementation instructions that reference the Azure AD PIM service will vary if using a third-party PAM @@ -1123,7 +1170,7 @@ system. of a mailbox that is different from the one used to monitor Global Administrator activations. -## 2.17 Managed Devices SHOULD Be Required for Authentication +## 17. Managed Devices Require that users connect to M365 from a device that is managed using conditional access. Agencies that are implementing a hybrid Azure AD @@ -1146,11 +1193,13 @@ The implementation section describes the cross-tenant settings that must be configured in both the home and the resource tenants to facilitate guest access with managed devices. -### 2.17.1 Policy - -- Managed devices SHOULD be required for authentication. +### Policies +#### MS.AAD.17.1v1 +Managed devices SHOULD be required for authentication. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -### 2.17.2 Resources +### Resources - [Configure hybrid Azure AD join](https://docs.microsoft.com/en-us/azure/active-directory/devices/howto-hybrid-azure-ad-join) @@ -1158,12 +1207,12 @@ guest access with managed devices. - [Set up enrollment for Windows devices (for Intune)](https://docs.microsoft.com/en-us/mem/intune/enrollment/windows-enroll) -### 2.17.3 License Requirements +### License Requirements - Use Microsoft Intune (if implementing the requirement for the device to be compliant). -### 2.17.4 Implementation +### Implementation [Follow these instructions](https://docs.microsoft.com/en-us/azure/active-directory/conditional-access/howto-conditional-access-policy-compliant-device#create-a-conditional-access-policy) to create a conditional access policy that requires the device to be @@ -1232,32 +1281,37 @@ of the tenant): 5. Under **Users and Groups** -\> **Applies to**, select **All users.** -## 2.18 Guest User Access SHOULD Be Restricted +## 18. Guest User Access Ensure that only users with specific privileges can invite guest users to the tenant and that invites can only be sent to specific external domains. Also ensure that guest users have limited access to Azure AD directory objects. -### 2.18.1 Policy - -- Only users with the Guest Inviter role SHOULD be able to invite guest - users. +#### MS.AAD.18.1v1 +Only users with the Guest Inviter role SHOULD be able to invite guest users. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- Guest invites SHOULD only be allowed to specific external domains that - have been authorized by the agency for legitimate business purposes. +#### MS.AAD.18.2v1 +Guest invites SHOULD only be allowed to specific external domains that have been authorized by the agency for legitimate business purposes. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- Guest users SHOULD have limited access to Azure AD directory objects. +#### MS.AAD.18.3v1 +Guest users SHOULD have limited access to Azure AD directory objects. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -### 2.18.2 Resources +### Resources - [Configure external collaboration settings](https://docs.microsoft.com/en-us/azure/active-directory/external-identities/external-collaboration-settings-configure) -### 2.18.3 License Requirements +### License Requirements - N/A -### 2.18.4 Implementation +### Implementation [Follow these instructions](https://docs.microsoft.com/en-us/azure/active-directory/external-identities/external-collaboration-settings-configure#configure-settings-in-the-portal) to configure the Azure AD **External collaboration settings**. diff --git a/baselines/defender.md b/baselines/defender.md index 86f03a7d1a..da3a9a79fa 100644 --- a/baselines/defender.md +++ b/baselines/defender.md @@ -1,4 +1,4 @@ -# 1. Introduction +# Introduction Microsoft 365 Defender is a cloud-based enterprise defense suite that coordinates prevention, detection, investigation, and response. This set @@ -22,7 +22,7 @@ In addition to these controls, agencies should consider using a Cloud Access Security Broker to secure their environments as they adopt zero trust principles. -## 1.1 Assumptions +## Assumptions The **License Requirements** sections of this document assume the organization is using an [M365 @@ -31,7 +31,7 @@ or [G3](https://www.microsoft.com/en-us/microsoft-365/government) license level. Therefore, only licenses not included in E3/G3 are listed. -## 1.2 Resources +## Resources **License Compliance and Copyright** @@ -47,9 +47,9 @@ document. The United States Government has adapted selections of these documents to develop innovative and scalable configuration standards to strengthen the security of widely used cloud-based software services. -# 2. Baseline +# Baseline -## 2.1 Preset Security Profiles SHOULD NOT Be Used +## 1. Preset Security Profiles Microsoft Defender defines two [preset security profiles](https://docs.microsoft.com/en-us/microsoft-365/security/office-365-security/preset-security-policies?view=o365-worldwide): @@ -59,50 +59,61 @@ the use of the preset profiles. Instead, it enumerates all relevant settings, as the preset security profiles are inflexible and take precedence over all other present policies. -### 2.1.1 Policy +### Policies +#### MS.DEFENDER.1.1v1 +Preset security profiles SHOULD NOT be used. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- Preset security profiles SHOULD NOT be used. - -### 2.1.2 Resources +### Resources - [Recommended settings for EOP and Microsoft Defender for Office 365 security \| Microsoft Docs](https://docs.microsoft.com/en-us/microsoft-365/security/office-365-security/recommended-settings-for-eop-and-office365?view=o365-worldwide#eop-anti-spam-policy-settings) -### 2.1.3 License Requirements +### License Requirements - N/A -## 2.2 Data Loss Prevention SHALL Be Enabled +## 2. Data Loss Prevention There are multiple, different ways to secure sensitive information, such as warning users, encryption, or blocking attempts to share. The agency’s data loss prevention (DLP) policy will dictate what agency information is sensitive and how that information is handled. -### 2.2.1 Policy - -- A custom policy SHALL be configured to protect PII and sensitive - information, as defined by the agency. At a minimum, credit card - numbers, Taxpayer Identification Numbers (TIN), and Social Security - Numbers (SSN) SHALL be blocked. +### Policies +#### MS.DEFENDER.2.1v1 +A custom policy SHALL be configured to protect PII and sensitive information, as defined by the agency. At a minimum, credit card numbers, Taxpayer Identification Numbers (TIN), and Social Security Numbers (SSN) SHALL be blocked. + - _Rationale:_ TODO +- _Last modified:_ June 2023 -- The custom policy SHOULD be applied in Exchange, OneDrive, Teams Chat, - and Microsoft Defender. +#### MS.DEFENDER.2.2v1 +The custom policy SHOULD be applied in Exchange, OneDrive, Teams Chat, and Microsoft Defender. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- The action for the DLP policy SHOULD be set to block sharing sensitive - information with everyone when DLP conditions are met. +#### MS.DEFENDER.2.3v1 +The action for the DLP policy SHOULD be set to block sharing sensitive information with everyone when DLP conditions are met. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- Notifications to inform users and help educate them on the proper use - of sensitive information SHOULD be enabled. +#### MS.DEFENDER.2.4v1 +Notifications to inform users and help educate them on the proper use of sensitive information SHOULD be enabled. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- A list of apps that are not allowed to access files protected by DLP - policy SHOULD be defined. +#### MS.DEFENDER.2.5v1 +A list of apps that are not allowed to access files protected by DLP policy SHOULD be defined. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- A list of browsers that are not allowed to access files protected by - DLP policy SHOULD be defined. +#### MS.DEFENDER.2.6v1 +A list of browsers that are not allowed to access files protected by DLP policy SHOULD be defined. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -### 2.2.2 Resources +### Resources - [Plan for data loss prevention (DLP) \| Microsoft Docs](https://docs.microsoft.com/en-us/microsoft-365/compliance/dlp-overview-plan-for-dlp?view=o365-worldwide) @@ -116,7 +127,7 @@ information is sensitive and how that information is handled. - [Sensitive information \| NIST](https://csrc.nist.gov/glossary/term/sensitive_information) -### 2.2.3 License Requirements +### License Requirements - DLP for Teams requires an E5 or G5 license. See [Information Protection: Data Loss Prevention for Teams \| Microsoft @@ -129,7 +140,7 @@ information is sensitive and how that information is handled. Docs](https://docs.microsoft.com/en-us/microsoft-365/compliance/endpoint-dlp-getting-started?view=o365-worldwide) for more information. -### 2.2.4 Implementation +### Implementation 1. Sign in to the [Microsoft 365 compliance](https://compliance.microsoft.com) admin center. @@ -143,7 +154,7 @@ information is sensitive and how that information is handled. 5. Select **Edit policy**. 6. Edit the name and description of the policy if desired, then click - **Next**.  + **Next**. 7. Under **Locations to apply the policy**, set **Status** to **On** for all products except Power BI (preview). @@ -209,7 +220,7 @@ information is sensitive and how that information is handled. 8. Switch **Always audit file activity for devices** to **ON**. -## 2.3 Common Attachments Filter SHALL Be Enabled +## 3. Common Attachments Filter Filtering emails by attachment file types will flag emails as malware if the file type has been put in a predefined list of disallowed file @@ -217,15 +228,18 @@ types. The Common Attachments Filter also attempts to look beyond just the file extension and automatically detect the file type using true typing. -### 2.3.1 Policy - -- The common attachments filter SHALL be enabled in the default - anti-malware policy and in all existing policies. +### Policies +#### MS.DEFENDER.3.1v1 +The common attachments filter SHALL be enabled in the default anti-malware policy and in all existing policies. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- Disallowed file types SHALL be determined and set. At a minimum, - click-to-run files SHOULD be blocked (e.g., .exe, .cmd, and .vbe). +#### MS.DEFENDER.3.2v1 +Disallowed file types SHALL be determined and set. At a minimum, click-to-run files SHOULD be blocked (e.g., .exe, .cmd, and .vbe). +- _Rationale:_ TODO +- _Last modified:_ June 2023 -### 2.3.2 Resources +### Resources - [Configure anti-malware policies in EOP \| Microsoft Docs](https://docs.microsoft.com/en-us/microsoft-365/security/office-365-security/configure-anti-malware-policies?view=o365-worldwide) @@ -233,12 +247,12 @@ typing. - [Anti-malware policies \| Microsoft Docs](https://docs.microsoft.com/en-us/microsoft-365/security/office-365-security/anti-malware-protection?view=o365-worldwide#anti-malware-policies) -### 2.3.3 License Requirements +### License Requirements - Requires Defender for Office 365 Plan 1 or 2. These are included with E5 and G5 and are available as add-ons for E3 and G3. -### 2.3.4 Implementation +### Implementation To enable common attachments filter in the default policy: @@ -265,18 +279,20 @@ To create a new, custom policy, follow the instructions on [Use the Microsoft 365 Defender portal to create anti-malware policies](https://docs.microsoft.com/en-us/microsoft-365/security/office-365-security/configure-anti-malware-policies?view=o365-worldwide#use-the-microsoft-365-defender-portal-to-create-anti-malware-policies). -## 2.4 Zero-Hour Auto Purge for Malware SHOULD Be Enabled +## 4. Zero-Hour Auto Purge This setting determines whether emails can be quarantined automatically after delivery to a user’s mailbox (e.g., in the case of a match with an updated malware classification rule). -### 2.4.1 Policy +### Policies -- Zero-hour Auto Purge (ZAP) for malware SHOULD be enabled in the - default anti-malware policy and in all existing custom policies. +#### MS.DEFENDER.4.1v1 +Zero-hour Auto Purge (ZAP) for malware SHOULD be enabled in the default anti-malware policy and in all existing custom policies. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -### 2.4.2 Resources +### Resources - [Configure anti-malware policies in EOP \| Microsoft Docs](https://docs.microsoft.com/en-us/microsoft-365/security/office-365-security/configure-anti-malware-policies?view=o365-worldwide) @@ -289,7 +305,7 @@ updated malware classification rule). - Requires Defender for Office 365 Plan 1 or 2. These are included with E5 and G5 and are available as add-ons for E3 and G3. -### 2.4.4 Implementation +### Implementation To enable ZAP: @@ -310,7 +326,7 @@ To enable ZAP: 8. Click **Save**. -## 2.5 Phishing Protections SHOULD Be Enabled +## 5. Phishing Protections There are multiple ways to protect against phishing, including impersonation protection, mailbox intelligence and safety tips. @@ -320,27 +336,48 @@ the sender address is significantly similar, as to indicate an impersonation attempt, the email is quarantined. Mailbox intelligence is an AI-based tool for identifying potential impersonation attempts. -### 2.5.1 Policy - -- User impersonation protection SHOULD be enabled for key agency +### Policies +#### MS.DEFENDER.5.1v1 +User impersonation protection SHOULD be enabled for key agency leaders. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- Domain impersonation protection SHOULD be enabled for domains owned by +#### MS.DEFENDER.5.2v1 +Domain impersonation protection SHOULD be enabled for domains owned by the agency. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- Domain impersonation protection SHOULD be added for frequent partners. +#### MS.DEFENDER.5.3v1 +Domain impersonation protection SHOULD be added for frequent partners. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- Trusted senders and domains MAY be added in the event of false +#### MS.DEFENDER.5.4v1 +Trusted senders and domains MAY be added in the event of false positives. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- Intelligence for impersonation protection SHALL be enabled. +#### MS.DEFENDER.5.5v1 +Intelligence for impersonation protection SHALL be enabled. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- Message action SHALL be set to quarantine if the message is detected +#### MS.DEFENDER.5.6v1 +Message action SHALL be set to quarantine if the message is detected as impersonated. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- Mail classified as spoofed SHALL be quarantined. +#### MS.DEFENDER.5.7v1 +Mail classified as spoofed SHALL be quarantined. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- All safety tips SHALL be enabled, including: +#### MS.DEFENDER.5.8v1 +All safety tips SHALL be enabled, including: - first contact, @@ -350,14 +387,19 @@ an AI-based tool for identifying potential impersonation attempts. - user impersonation unusual characters, - - “?” for unauthenticated senders for spoof, and + - ? for unauthenticated senders for spoof, and - - “via” tag. + - via tag. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- The above configurations SHALL be set in the default policy and SHOULD +#### MS.DEFENDER.5.9v1 +The above configurations SHALL be set in the default policy and SHOULD be set in all existing custom policies. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -### 2.5.2 Resources +### Resources - [Configure anti-phishing policies in EOP \| Microsoft Docs](https://docs.microsoft.com/en-us/microsoft-365/security/office-365-security/configure-anti-phishing-policies-eop?view=o365-worldwide) @@ -365,7 +407,7 @@ an AI-based tool for identifying potential impersonation attempts. - [EOP anti-phishing policy settings \| Microsoft Docs](https://docs.microsoft.com/en-us/microsoft-365/security/office-365-security/recommended-settings-for-eop-and-office365?view=o365-worldwide#eop-anti-phishing-policy-settings) -### 2.5.3 License Requirements +### License Requirements - Impersonation protection and advanced phishing thresholds require Defender for Office 365 Plan 1 or 2. These are included with E5 and G5 @@ -376,7 +418,7 @@ an AI-based tool for identifying potential impersonation attempts. Docs](https://docs.microsoft.com/en-us/office365/servicedescriptions/office-365-platform-service-description/office-365-us-government/office-365-us-government#platform-features) for current offerings). -### 2.5.4 Implementation +### Implementation 1. Sign in to [Microsoft 365 Defender](https://security.microsoft.com/). @@ -442,37 +484,59 @@ an AI-based tool for identifying potential impersonation attempts. 22. Click **Save**. -## 2.6 Inbound Anti-Spam Protections SHALL Be Enabled +## 6. Inbound Anti-Spam Protections There are several features that protect against inbound spam. Bulk compliant level, quarantines, safety tips, and zero-hour auto purge. -### 2.6.1 Policy +### Policies -- The bulk complaint level (BCL) threshold SHOULD be set to six or - lower. +#### MS.DEFENDER.6.1v1 +The bulk complaint level (BCL) threshold SHOULD be set to six or lower. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- Spam and high confidence spam SHALL be moved to either the junk email - folder or the quarantine folder. +#### MS.DEFENDER.6.2v1 +Spam and high confidence spam SHALL be moved to either the junk email folder or the quarantine folder. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- Phishing and high confidence phishing SHALL be quarantined. +#### MS.DEFENDER.6.3v1 +Phishing and high confidence phishing SHALL be quarantined. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- Bulk email SHOULD be moved to either the junk email folder or the - quarantine folder. +#### MS.DEFENDER.6.4v1 +Bulk email SHOULD be moved to either the junk email folder or the quarantine folder. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- Spam in quarantine SHOULD be retained for at least 30 days. +#### MS.DEFENDER.6.5v1 +Spam in quarantine SHOULD be retained for at least 30 days. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- Spam safety tips SHOULD be turned on. +#### MS.DEFENDER.6.6v1 +Spam safety tips SHOULD be turned on. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- Zero-hour auto purge (ZAP) SHALL be enabled for both phishing and spam - messages. +#### MS.DEFENDER.6.7v1 +Zero-hour auto purge (ZAP) SHALL be enabled for both phishing and spam messages. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- Allowed senders MAY be added but allowed domains SHALL NOT be added. +#### MS.DEFENDER.6.8v1 +Allowed senders MAY be added but allowed domains SHALL NOT be added. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- The previously listed configurations SHALL be set in the default - policy and SHOULD be set in all existing custom policies. +#### MS.DEFENDER.6.9v1 +The previously listed configurations SHALL be set in the default policy and SHOULD be set in all existing custom policies. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -### 2.6.2 Resources +### Resources - [Bulk complaint level (BCL) in EOP \| Microsoft Docs](https://docs.microsoft.com/en-us/microsoft-365/security/office-365-security/bulk-complaint-level-values?view=o365-worldwide) @@ -483,11 +547,11 @@ compliant level, quarantines, safety tips, and zero-hour auto purge. - [Configure anti-spam policies in EOP \| Microsoft Docs](https://docs.microsoft.com/en-us/microsoft-365/security/office-365-security/configure-your-spam-filter-policies?view=o365-worldwide) -### 2.6.3 License Requirements +### License Requirements - N/A -### 2.6.4 Implementation +### Implementation 1. Sign in to [Microsoft 365 Defender](https://security.microsoft.com/). @@ -527,7 +591,7 @@ compliant level, quarantines, safety tips, and zero-hour auto purge. 11. Click **Save.** -## 2.7 Safe Link Policies SHOULD Be Enabled +## 7. Safe Links When enabled, URLs in emails are rewritten by prepending @@ -548,28 +612,53 @@ scanning service. Their proxy can perform the following: If all checks pass, the user is redirected to the original URL. -### 2.7.1 Policy - -- The Safe Links Policy SHALL include all agency domains—and by - extension—all users. - -- URL rewriting and malicious link click checking SHALL be enabled. - -- Malicious link click checking SHALL be enabled with Microsoft Teams. - -- Real-time suspicious URL and file-link scanning SHALL be enabled. - -- URLs SHALL be scanned completely before message delivery. - -- Internal agency email messages SHALL have safe links enabled. - -- User click tracking SHALL be enabled. - -- Safe Links in Office 365 apps SHALL be turned on. - -- Users SHALL NOT be enabled to click through to the original URL. - -### 2.7.2 Resources +### Policies +#### MS.DEFENDER.7.1v1 +The Safe Links Policy SHALL include all agency domains and by extension all users. +- _Rationale:_ TODO +- _Last modified:_ June 2023 + +#### MS.DEFENDER.7.2v1 +URL rewriting and malicious link click checking SHALL be enabled. +- _Rationale:_ TODO +- _Last modified:_ June 2023 + +#### MS.DEFENDER.7.3v1 +Malicious link click checking SHALL be enabled with Microsoft Teams. +- _Rationale:_ TODO +- _Last modified:_ June 2023 + +#### MS.DEFENDER.7.4v1 +Real-time suspicious URL and file-link scanning SHALL be enabled. +- _Rationale:_ TODO +- _Last modified:_ June 2023 + +#### MS.DEFENDER.7.5v1 +URLs SHALL be scanned completely before message delivery. +- _Rationale:_ TODO +- _Last modified:_ June 2023 + +#### MS.DEFENDER.7.6v1 +Internal agency email messages SHALL have safe links enabled. +- _Rationale:_ TODO +- _Last modified:_ June 2023 + +#### MS.DEFENDER.7.7v1 +User click tracking SHALL be enabled. +- _Rationale:_ TODO +- _Last modified:_ June 2023 + +#### MS.DEFENDER.7.8v1 +Safe Links in Office 365 apps SHALL be turned on. +- _Rationale:_ TODO +- _Last modified:_ June 2023 + +#### MS.DEFENDER.7.9v1 +Users SHALL NOT be enabled to click through to the original URL. +- _Rationale:_ TODO +- _Last modified:_ June 2023 + +### Resources - [Safe Links in Microsoft Defender for Office 365 \| Microsoft Docs](https://docs.microsoft.com/en-us/microsoft-365/security/office-365-security/safe-links?view=o365-worldwide) @@ -578,12 +667,12 @@ If all checks pass, the user is redirected to the original URL. Microsoft Docs](https://docs.microsoft.com/en-us/microsoft-365/security/office-365-security/set-up-safe-links-policies?view=o365-worldwide) -### 2.7.3 License Requirements +### License Requirements - Requires Defender for Office 365 Plan 1 or 2. These are included with E5 and G5 and are available as add-ons for E3 and G3. -### 2.7.4 Implementation +### Implementation For more information about recommended Safe Links settings, see [Safe](https://docs.microsoft.com/en-us/microsoft-365/security/office-365-security/recommended-settings-for-eop-and-office365?view=o365-worldwide#safe-links-settings) @@ -640,7 +729,7 @@ message.** 5. Review the new policy, then click **Submit**. -## 2.8 Safe-Attachments SHALL Be Enabled +## 8. Safe-Attachments The Safe Attachments will scan messages for attachments with malicious content. It routes all messages and attachments that do not have a @@ -649,20 +738,28 @@ learning and analysis techniques to detect malicious intent. Enabling this feature may slow down message delivery to the user due to the scanning. -### 2.8.1 Policy - -- At least one Safe Attachments Policy SHALL include all agency - domains—and by extension—all users. +### Policies +#### MS.DEFENDER.8.1v1 +At least one Safe Attachments Policy SHALL include all agency domains and by extension all users. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- The action for malware in email attachments SHALL be set to block. +#### MS.DEFENDER.8.2v1 +The action for malware in email attachments SHALL be set to block. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- Redirect emails with detected attachments to an agency-specified email - SHOULD be enabled. +#### MS.DEFENDER.8.3v1 +Redirect emails with detected attachments to an agency-specified email SHOULD be enabled. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- Safe attachments SHOULD be enabled for SharePoint, OneDrive, and - Microsoft Teams. +#### MS.DEFENDER.8.4v1 +Safe attachments SHOULD be enabled for SharePoint, OneDrive, and Microsoft Teams. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -### 2.8.2 Resources +### Resources - [Safe Attachments in Microsoft Defender for Office 365 \| Microsoft Docs](https://docs.microsoft.com/en-us/microsoft-365/security/office-365-security/safe-attachments?view=o365-worldwide#safe-attachments-policy-settings) @@ -678,12 +775,12 @@ scanning. Teams \| Microsoft Docs](https://docs.microsoft.com/en-us/microsoft-365/security/office-365-security/turn-on-mdo-for-spo-odb-and-teams?view=o365-worldwide) -### 2.8.3 License Requirements +### License Requirements - Requires Defender for Office 365 Plan 1 or 2. These are included with E5 and G5 and are available as add-ons for E3 and G3. -### 2.8.4 Implementation +### Implementation To configure safe attachments for Exchange Online, follow the instructions listed on [Use the Microsoft 365 Defender portal to create @@ -732,30 +829,33 @@ Docs](https://docs.microsoft.com/en-us/microsoft-365/security/office-365-securit 6. Set **Turn on Defender for Office 365 for SharePoint, OneDrive, and Microsoft Teams** to on. -## 2.9 Alerts SHALL Be Enabled +## 9. Alerts There are several pre-built alert policies available pertaining to various apps in the M365 suite. These alerts give admins better real-time insight into possible security incidents. -### 2.9.1 Policy +### Policies +#### MS.DEFENDER.9.1v1 +At a minimum, the alerts required by the *Exchange Online Minimum Viable Secure Configuration Baseline* SHALL be enabled. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- At a minimum, the alerts required by the *Exchange Online Minimum - Viable Secure Configuration Baseline* SHALL be enabled. +#### MS.DEFENDER.9.2v1 +The alerts SHOULD be sent to a monitored address or incorporated into a SIEM. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- The alerts SHOULD be sent to a monitored address or incorporated into - a SIEM. - -### 2.9.2 Resources +### Resources - [Alert policies in Microsoft 365 \| Microsoft Docs](https://docs.microsoft.com/en-us/microsoft-365/compliance/alert-policies?view=o365-worldwide) -### 2.9.3 License Requirements +### License Requirements - N/A -### 2.9.4 Implementation +### Implementation 1. Sign in to [Microsoft 365 Defender](https://security.microsoft.com/). @@ -770,7 +870,7 @@ real-time insight into possible security incidents. 6. Ensure **Email recipients** includes at least one monitored address. -## 2.10 Unified Audit Logging SHALL Be Enabled +## 10. Microsoft Purview Audit Unified audit logging generates logs of user activity in M365 services. These logs are essential for conducting incident response and threat detection activity. @@ -786,35 +886,42 @@ policy](https://docs.microsoft.com/en-us/microsoft-365/compliance/audit-log-rete OMB M-21-13 also requires Advanced Audit be configured in M365. Advanced Audit adds additional event types to the Unified Audit Log. -### 2.10.1 Policy - -- Unified audit logging SHALL be enabled. +### Policies +#### MS.DEFENDER.10.1v1 +Microsoft Purview Audit (Standard) logging SHALL be enabled. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- Advanced audit SHALL be enabled. +#### MS.DEFENDER.10.2v1 +Microsoft Purview Audit (Premium) logging SHALL be enabled. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- Audit logs SHALL be maintained for at least the minimum duration - dictated by OMB M-21-31. +#### MS.DEFENDER.10.3v1 +Audit logs SHALL be maintained for at least the minimum duration dictated by OMB M-21-31. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -### 2.10.2 Resources +### Resources - [OMB M-21-31 \| Office of Management and Budget](https://www.whitehouse.gov/wp-content/uploads/2021/08/M-21-31-Improving-the-Federal-Governments-Investigative-and-Remediation-Capabilities-Related-to-Cybersecurity-Incidents.pdf) - [Turn auditing on or off \| Microsoft - Docs](https://docs.microsoft.com/en-us/microsoft-365/compliance/turn-audit-log-search-on-or-off?view=o365-worldwide)  + Docs](https://docs.microsoft.com/en-us/microsoft-365/compliance/turn-audit-log-search-on-or-off?view=o365-worldwide) - [Create an audit log retention policy \| Microsoft Docs](https://docs.microsoft.com/en-us/microsoft-365/compliance/audit-log-retention-policies?view=o365-worldwide#create-an-audit-log-retention-policy) - [Search the audit log in the compliance center \| Microsoft - Docs ](https://docs.microsoft.com/en-us/microsoft-365/compliance/search-the-audit-log-in-security-and-compliance?view=o365-worldwide)  + Docs ](https://docs.microsoft.com/en-us/microsoft-365/compliance/search-the-audit-log-in-security-and-compliance?view=o365-worldwide) - [Audited Activities \| Microsoft Docs](https://docs.microsoft.com/en-us/microsoft-365/compliance/search-the-audit-log-in-security-and-compliance?view=o365-worldwide#audited-activities) -### 2.10.3 License Requirements +### License Requirements -- Advanced audit capabilities, including the creation of a custom audit +- Microsoft Purview Audit (Premium) logging capabilities, including the creation of a custom audit log retention policy, requires E5/G5 licenses or E3/G3 licenses with add-on compliance licenses. @@ -823,7 +930,7 @@ OMB M-21-13 also requires Advanced Audit be configured in M365. Advanced Audit a [Licensing requirements \| Microsoft Docs](https://docs.microsoft.com/en-us/microsoft-365/compliance/auditing-solutions-overview?view=o365-worldwide#licensing-requirements). -### 2.10.4 Implementation +### Implementation Auditing can be enabled from the Microsoft 365 compliance admin center and the Exchange Online PowerShell. Follow the instructions listed on diff --git a/baselines/exchange.md b/baselines/exo.md similarity index 78% rename from baselines/exchange.md rename to baselines/exo.md index 863dddcf65..7e913386f4 100644 --- a/baselines/exchange.md +++ b/baselines/exo.md @@ -1,4 +1,4 @@ -# 1. Introduction +# Introduction Microsoft Exchange Online provides users easy access to their email and supports organizational meetings, contacts, and calendars. @@ -14,7 +14,7 @@ this baseline. When noted, alternative products may be used in lieu of Defender, on the condition that they fulfill these required baseline settings. -## 1.1 Assumptions +## Assumptions The **License Requirements** sections of this document assume the organization is using an [M365 @@ -23,7 +23,7 @@ or [G3](https://www.microsoft.com/en-us/microsoft-365/government) license level. Therefore, only licenses not included in E3/G3 are listed. -## 1.2 Resources +## Resources **License Compliance and Copyright** @@ -39,28 +39,31 @@ document. The United States Government has adapted selections of these documents to develop innovative and scalable configuration standards to strengthen the security of widely used cloud-based software services. -# 2. Baseline +# Baseline -## 2.1 Automatic Forwarding to External Domains SHALL Be Disabled +## 1. Automatic Forwarding to External Domains This control is intended to prevent bad actors from using client-side forwarding rules to exfiltrate data to external recipients. -### 2.1.1 Policy +### Policies -- Automatic forwarding to external domains SHALL be disabled. +#### MS.EXO.1.1v1 +Automatic forwarding to external domains SHALL be disabled. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -### 2.1.2 Resources +### Resources - [Reducing or increasing information flow to another company \| Microsoft Docs](https://docs.microsoft.com/en-us/exchange/mail-flow-best-practices/remote-domains/remote-domains#reducing-or-increasing-information-flow-to-another-company) -### 2.1.3 License Requirements +### License Requirements - N/A -### 2.1.4 Implementation +### Implementation To disallow automatic forwarding to external domains: @@ -76,7 +79,7 @@ To disallow automatic forwarding to external domains: 5. Clear the checkbox next to **Allow automatic forwarding**, then click **Save**. -## 2.2 Sender Policy Framework SHALL Be Enabled +## 2. Sender Policy Framework The Sender Policy Framework (SPF) is a mechanism that allows domain administrators to specify which IP addresses are explicitly approved to @@ -86,14 +89,19 @@ rather via DNS records hosted by the agency’s domain. Thus, the exact steps needed to set up SPF varies from agency to agency, but Microsoft’s documentation provides some helpful starting points. -### 2.2.1 Policy +### Policies -- A list of approved IP addresses for sending mail SHALL be maintained. +#### MS.EXO.2.1v1 +A list of approved IP addresses for sending mail SHALL be maintained. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- An SPF policy(s) that designates only these addresses as approved - senders SHALL be published. +#### MS.EXO.2.2v1 +An SPF policy(s) that designates only these addresses as approved senders SHALL be published. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -### 2.2.2 Resources +### Resources - [Binding Operational Directive 18-01 - Enhance Email and Web Security \| DHS](https://cyber.dhs.gov/bod/18-01/) @@ -108,11 +116,11 @@ documentation provides some helpful starting points. spoofing \| Microsoft Docs](https://docs.microsoft.com/en-us/microsoft-365/security/office-365-security/how-office-365-uses-spf-to-prevent-spoofing?view=o365-worldwide) -### 2.2.3 License Requirements +### License Requirements - N/A -### 2.2.4 Implementation +### Implementation SPF is not configured through the Exchange admin center, but rather via DNS records hosted by the agency’s domain. Thus, the exact steps needed @@ -123,7 +131,7 @@ PowerShell tool Resolve-DnsName. For example: `Resolve-DnsName example.com txt` -## 2.3 DomainKeys Identified Mail SHOULD Be Enabled +## 3. DomainKeys Identified Mail DomainKeys Identified Mail (DKIM) allows digital signatures to be added to email messages in the message header, providing a layer of both @@ -133,11 +141,13 @@ agency manages its DNS. DKIM is enabled for your tenant's default domain (e.g., onmicrosoft.com domains), but it must be manually enabled for custom domains. -### 2.3.1 Policy +### Policies +#### MS.EXO.3.1v1 +DKIM SHOULD be enabled for any custom domain. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- DKIM SHOULD be enabled for any custom domain. - -### 2.3.2 Resources +### Resources - [Binding Operational Directive 18-01 - Enhance Email and Web Security \| DHS](https://cyber.dhs.gov/bod/18-01/) @@ -155,13 +165,13 @@ custom domains. - [What is EOP? \| Microsoft Docs](https://docs.microsoft.com/en-us/microsoft-365/security/office-365-security/eop-general-faq?view=o365-worldwide#what-is-eop-) -### 2.3.3 License Requirements +### License Requirements - DKIM signing is included with Exchange Online Protection (EOP), which in turn is included in all Microsoft 365 subscriptions that contain Exchange Online mailboxes. -### 2.3.4 Implementation +### Implementation To enable DKIM, follow the instructions listed on [Steps to Create, enable and disable DKIM from Microsoft 365 Defender portal \| Microsoft @@ -188,7 +198,7 @@ Docs](https://docs.microsoft.com/en-us/microsoft-365/security/office-365-securit 8. Return to the DKIM page on the Defender admin center to finish enabling DKIM. -## 2.4 Domain-Based Message Authentication, Reporting, and Conformance SHALL Be Enabled +## 4 Domain-Based Message Authentication, Reporting, and Conformance (DMARC) Domain-based Message Authentication, Reporting, and Conformance (DMARC) works with SPF and DKIM to authenticate mail senders and ensure that @@ -196,19 +206,28 @@ destination email systems can validate messages sent from your domain. DMARC helps receiving mail systems determine what to do with messages sent from your domain that fail SPF or DKIM checks. -### 2.4.1 Policy - -- A DMARC policy SHALL be published for every second-level domain. +### Policies +#### MS.EXO.4.1v1 +A DMARC policy SHALL be published for every second-level domain. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- The DMARC message rejection option SHALL be “p=reject”. +#### MS.EXO.4.2v1 +The DMARC message rejection option SHALL be p=reject. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- The DMARC point of contact for aggregate reports SHALL include - . +#### MS.EXO.4.3v1 +The DMARC point of contact for aggregate reports SHALL include . +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- An agency point of contact SHOULD be included for aggregate and/or - failure reports. +#### MS.EXO.4.4v1 +An agency point of contact SHOULD be included for aggregate and/or failure reports. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -### 2.4.2 Resources +### Resources - [Binding Operational Directive 18-01 - Enhance Email and Web Security \| DHS](https://cyber.dhs.gov/bod/18-01/) @@ -225,11 +244,11 @@ sent from your domain that fail SPF or DKIM checks. - [How Office 365 handles outbound email that fails DMARC \| Microsoft Docs](https://docs.microsoft.com/en-us/microsoft-365/security/office-365-security/use-dmarc-to-validate-email?view=o365-worldwide#how-microsoft-365-handles-inbound-email-that-fails-dmarc) -### 2.4.3 License Requirements +### License Requirements - N/A -### 2.4.4 Implementation +### Implementation DMARC implementation varies depending on how an agency manages its DNS records. See [Form the DMARC TXT record for your domain \| Microsoft @@ -247,7 +266,7 @@ is included in the policy returned from the query, and that (3) is included as a point for contact for aggregate feedback. -## 2.5 Simple Mail Transfer Protocol Authentication SHALL Be Disabled +## 5. Simple Mail Transfer Protocol Authentication (SMTP AUTH) Modern email clients that connect to Exchange Online mailboxes—including Outlook, Outlook on the web, iOS Mail, and Outlook for iOS and @@ -255,13 +274,19 @@ Android—do not use Simple Mail Transfer Protocol Authentication (SMTP AUTH) to send email messages. SMTP AUTH is only needed for applications outside of Outlook that send email messages. -### 2.5.1 Policy +### Policies -- SMTP AUTH SHALL be disabled in Exchange Online. +#### MS.EXO.5.1v1 +SMTP AUTH SHALL be disabled in Exchange Online. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- SMTP AUTH MAY be enabled on a per-mailbox basis as needed. +#### MS.EXO.5.2v1 +SMTP AUTH MAY be enabled on a per-mailbox basis as needed. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -### 2.5.2 Resources +### Resources - [Enable or disable authenticated client SMTP submission (SMTP AUTH) in Exchange Online \| Microsoft @@ -271,11 +296,11 @@ outside of Outlook that send email messages. specific mailboxes \| Microsoft Docs](https://docs.microsoft.com/en-us/exchange/clients-and-mobile-in-exchange-online/authenticated-client-smtp-submission#use-the-microsoft-365-admin-center-to-enable-or-disable-smtp-auth-on-specific-mailboxes) -### 2.5.3 License Requirements +### License Requirements - N/A -### 2.5.4 Implementation +### Implementation SMTP AUTH can only be disabled tenant-wide using Exchange Online PowerShell. Follow the instructions listed at [Disable SMTP AUTH in your @@ -287,22 +312,27 @@ listed at [Use the Microsoft 365 admin center to enable or disable SMTP AUTH on specific mailboxes \| Microsoft Docs](https://docs.microsoft.com/en-us/exchange/clients-and-mobile-in-exchange-online/authenticated-client-smtp-submission#use-the-microsoft-365-admin-center-to-enable-or-disable-smtp-auth-on-specific-mailboxes). -## 2.6 Calendar and Contact Sharing SHALL Be Restricted +## 6. Calendar and Contact Sharing Exchange Online allows the creation of sharing polices that soften default restrictions on contact and calendar details sharing. These policies should only be enabled with caution and must comply with the following policies. -### 2.6.1 Policy +### Policies -- Contact folders SHALL NOT be shared with all domains, although they +#### MS.EXO.6.1v1 +Contact folders SHALL NOT be shared with all domains, although they MAY be shared with specific domains. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- Calendar details SHALL NOT be shared with all domains, although they - MAY be shared with specific domains. +#### MS.EXO.6.2v1 +Calendar details SHALL NOT be shared with all domains, although they MAY be shared with specific domains. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -### 2.6.2 Resources +### Resources - [Sharing in Exchange Online \| Microsoft Docs](https://docs.microsoft.com/en-us/exchange/sharing/sharing) @@ -313,11 +343,11 @@ following policies. - [Sharing policies in Exchange Online \| Microsoft Docs](https://docs.microsoft.com/en-us/exchange/sharing/sharing-policies/sharing-policies) -### 2.6.3 License Requirements +### License Requirements - N/A -### 2.6.4 Implementation +### Implementation To restrict sharing with all domains: @@ -329,17 +359,19 @@ To restrict sharing with all domains: 3. Under **Individual Sharing**, for all existing policies, ensure that for all sharing rules, **Sharing with all domains** is not selected. -## 2.7 External Sender Warnings SHALL Be Implemented +## 7. External Sender Warnings Mail flow rules allow the modification of incoming mail, such that mail from external users can be easily identified, for example by prepending the subject line with “\[External\].” -### 2.7.1 Policy +### Policies +#### MS.EXO.7.1v1 +External sender warnings SHALL be implemented. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- External sender warnings SHALL be implemented. - -### 2.7.2 Resources +### Resources - [Mail flow rules (transport rules) in Exchange Online \| Microsoft Docs](https://docs.microsoft.com/en-us/exchange/security-and-compliance/mail-flow-rules/mail-flow-rules) @@ -352,11 +384,11 @@ the subject line with “\[External\].” \| Cisa](https://www.cisa.gov/sites/default/files/publications/CISA_Insights_Actions_to_Counter_Email-Based_Attacks_on_Election-Related_S508C.pdf) -### 2.7.3 License Requirements +### License Requirements - N/A -### 2.7.4 Implementation +### Implementation To enable external sender warnings: @@ -386,7 +418,7 @@ To enable external sender warnings: 11. Click **Save**. -## 2.8 Data Loss Prevention Solutions SHALL Be Enabled +## 8. Data Loss Prevention Solutions Data loss prevention (DLP) helps prevent both accidental leakage of sensitive information as well as intentional exfiltration of data. DLP @@ -404,22 +436,23 @@ Minimum Viable Secure Configuration Baseline*. The DLP solution selected by an agency should offer services comparable to those offered by Microsoft. -### 2.8.1 Policy - -- A DLP solution SHALL be used. The selected DLP solution SHOULD offer - services comparable to the native DLP solution offered by Microsoft. +### Policies +#### MS.EXO.8.1v1 +A DLP solution SHALL be used. The selected DLP solution SHOULD offer services comparable to the native DLP solution offered by Microsoft. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- The DLP solution SHALL protect PII and sensitive information, as - defined by the agency. At a minimum, the sharing of credit card - numbers, Taxpayer Identification Numbers (TIN), and Social Security - Numbers (SSN) via email SHALL be restricted. +#### MS.EXO.8.2v1 +The DLP solution SHALL protect PII and sensitive information, as defined by the agency. At a minimum, the sharing of credit card numbers, Taxpayer Identification Numbers (TIN), and Social Security Numbers (SSN) via email SHALL be restricted. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -### 2.8.2 Resources +### Resources - The “Data Loss Prevention SHALL Be Enabled” section of the *Defender for Office 365 Minimum Viable Secure Configuration Baseline*. -## 2.9 Emails SHALL Be Filtered by Attachment File Type +## 9. Attachment File Type For some types of files (e.g., executable files), the dangers of allowing them to be sent over email outweigh any potential benefits. @@ -436,25 +469,29 @@ Be Enabled” section of the Defender for Office 365 Minimum Viable Secure Configuration Baseline. The solution selected by an agency should offer services comparable to those offered by Microsoft. -### 2.9.1 Policy - -- Emails SHALL be filtered by the file types of included attachments. - The selected filtering solution SHOULD offer services comparable to - Microsoft Defender’s Common Attachment Filter. +### Policies +#### MS.EXO.9.1v1 +Emails SHALL be filtered by the file types of included attachments. The selected filtering solution SHOULD offer services comparable to Microsoft Defenders Common Attachment Filter. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- The attachment filter SHOULD attempt to determine the true file type - and assess the file extension. +#### MS.EXO.9.2v1 +The attachment filter SHOULD attempt to determine the true file type and assess the file extension. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- Disallowed file types SHALL be determined and set. At a minimum, - click-to-run files SHOULD be blocked (e.g., .exe, .cmd, and .vbe). +#### MS.EXO.9.3v1 +Disallowed file types SHALL be determined and set. At a minimum, click-to-run files SHOULD be blocked (e.g., .exe, .cmd, and .vbe). +- _Rationale:_ TODO +- _Last modified:_ June 2023 -### 2.9.2 Resources +### Resources - The “Common Attachments Filter SHALL Be Enabled” section of the *Defender for Office 365 Minimum Viable Secure Configuration Baseline*. -## 2.10 Emails SHALL Be Scanned for Malware +## 10. Malware Though any product that fills the requirements outlined in this baseline setting may be used, for guidance on implementing malware scanning using @@ -465,16 +502,24 @@ Office 365 Minimum Viable Secure Configuration Baseline*: - “Zero-hour Auto Purge for Malware SHALL Be Enabled” -### 2.10.1 Policy +### Policies -- Emails SHALL be scanned for malware. +#### MS.EXO.10.1v1 +Emails SHALL be scanned for malware. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- Emails identified as containing malware SHALL be quarantined or - dropped. +#### MS.EXO.10.2v1 +Emails identified as containing malware SHALL be quarantined or dropped. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- Email scanning SHOULD be capable of reviewing emails after delivery. +#### MS.EXO.10.3v1 +Email scanning SHOULD be capable of reviewing emails after delivery. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -### 2.10.2 Resources +### Resources - The “Safe-Attachments SHALL Be Enabled” section of the *Defender for Office 365 Minimum Viable Secure Configuration Baseline.* @@ -483,7 +528,7 @@ Office 365 Minimum Viable Secure Configuration Baseline*: *Defender for Office 365 Minimum Viable Secure Configuration Baseline.* -## 2.11 Phishing Protections SHOULD Be Enabled +## 11. Phishing Protections Several techniques exist for protecting against phishing attacks, including the following techniques: @@ -505,22 +550,28 @@ phishing protections with Microsoft’s native solutions, see the “Phishing Protections SHOULD Be Enabled,” section of the *Defender for Office 365 Minimum Viable Secure Configuration Baseline*. -### 2.11.1 Policy +### Policies +#### MS.EXO.11.1v1 +Impersonation protection checks SHOULD be used. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- Impersonation protection checks SHOULD be used. +#### MS.EXO.11.2v1 +User warnings, comparable to the user safety tips included with EOP, SHOULD be displayed. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- User warnings, comparable to the user safety tips included with EOP, - SHOULD be displayed. +#### MS.EXO.11.3v1 +The phishing protection solution SHOULD include an AI-based phishing detection tool comparable to EOP Mailbox Intelligence. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- The phishing protection solution SHOULD include an AI-based phishing - detection tool comparable to EOP Mailbox Intelligence. - -### 2.11.2 Resources +### Resources - The “Phishing Protections SHOULD Be Enabled” section of the *Defender for Office 365 Minimum Viable Secure Configuration Baseline.* -## 2.12 IP Allow Lists SHOULD NOT be Implemented +## 12. IP Allow Lists Microsoft Defender supports the creations of IP “allow lists,” intended to ensure that emails from *specific* senders are not blocked. However, @@ -537,15 +588,23 @@ Microsoft sources from various third-party subscriptions. As with senders in the allow list, emails from these senders bypass important security mechanisms. -### 2.12.1 Policy - -- IP allow lists SHOULD NOT be created. +### Policies +#### MS.EXO.12.1v1 +IP allow lists SHOULD NOT be created. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- Safe lists SHOULD NOT be enabled. +#### MS.EXO.12.2v1 +Safe lists SHOULD NOT be enabled. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- A connection filter MAY be implemented to create an IP “Block list.” +#### MS.EXO.12.3v1 +A connection filter MAY be implemented to create an IP Block list. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -### 2.12.2 Resources +### Resources - [Use the IP Allow List \| Microsoft Docs](https://docs.microsoft.com/en-us/microsoft-365/security/office-365-security/create-safe-sender-lists-in-office-365?view=o365-worldwide#use-the-ip-allow-list) @@ -557,11 +616,11 @@ security mechanisms. connection filter policy \| Microsoft Docs](https://docs.microsoft.com/en-us/microsoft-365/security/office-365-security/configure-the-connection-filter-policy?view=o365-worldwide#use-the-microsoft-365-defender-portal-to-modify-the-default-connection-filter-policy) -### 2.12.3 License Requirements +### License Requirements - Exchange Online Protection -### 2.12.4 Implementation +### Implementation To modify the connection filters, follow the instructions found on [Use the Microsoft 365 Defender portal to modify the default connection @@ -587,7 +646,7 @@ policy](https://docs.microsoft.com/en-us/microsoft-365/security/office-365-secur 8. Ensure **Turn on safe list** is not selected. -## 2.13 Mailbox Auditing SHALL Be Enabled +## 13. Mailbox Auditing Mailbox auditing helps users investigate compromised accounts or discover illicit access to Exchange Online. Some actions performed by @@ -595,11 +654,13 @@ administrators, delegates, and owners are logged automatically. While mailbox auditing is enabled by default, agencies should ensure that it has not been inadvertently disabled. -### 2.13.1 Policy - -- Mailbox auditing SHALL be enabled. +### Policies +#### MS.EXO.13.1v1 +Mailbox auditing SHALL be enabled. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -### 2.13.2 Resources +### Resources - [Manage mailbox auditing in Office 365 \| Microsoft Docs](https://docs.microsoft.com/en-us/microsoft-365/compliance/enable-mailbox-auditing?view=o365-worldwide) @@ -610,11 +671,11 @@ has not been inadvertently disabled. - [Microsoft Compliance Manager - Microsoft 365 Compliance \|Microsoft Docs](https://docs.microsoft.com/en-us/microsoft-365/compliance/compliance-manager?view=o365-worldwide) -### 2.13.3 License Requirements +### License Requirements - N/A -### 2.13.4 Implementation +### Implementation Mailbox auditing can be enabled from the Exchange Online PowerShell. Follow the instructions listed on [Manage mailbox auditing in Office @@ -636,7 +697,7 @@ To enable mailbox auditing via PowerShell: `Set-OrganizationConfig –AuditDisabled $false` -## 2.14 Inbound Anti-Spam Protections SHALL Be Enabled +## 14. Inbound Anti-Spam Protections Microsoft Defender includes several capabilities for protecting against inbound spam emails. Use of Microsoft Defender is not strictly required @@ -645,24 +706,30 @@ this baseline setting may be used. See the “Inbound Anti-Spam Protections SHALL Be Enabled” section of the *Defender for Office 365 Minimum Viable Secure Configuration Baseline* for additional guidance. -### 2.14.1 Policy - -- A spam filter SHALL be enabled. The filtering solution selected SHOULD - offer services comparable to the native spam filtering offered by +### Policies +#### MS.EXO.14.1v1 +A spam filter SHALL be enabled. The filtering solution selected SHOULD offer services comparable to the native spam filtering offered by Microsoft. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- Spam and high confidence spam SHALL be moved to either the junk email - folder or the quarantine folder. +#### MS.EXO.14.2v1 +Spam and high confidence spam SHALL be moved to either the junk email folder or the quarantine folder. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- Allowed senders MAY be added, but allowed domains SHALL NOT be added. +#### MS.EXO.14.3v1 +Allowed senders MAY be added, but allowed domains SHALL NOT be added. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -### 2.14.2 Resources +### Resources - The “Inbound Anti-Spam Protections SHALL Be Enabled” section of the *Defender for Office 365 Minimum Viable Secure Configuration Baseline*. -## 2.15 Link Protection SHOULD Be Enabled +## 15. Link Protection Several technologies exist for protecting users from malicious links included in emails. For example, Microsoft Defender accomplishes this by @@ -688,20 +755,29 @@ guidance for enabling link scanning using Microsoft Defender is included in the “Safe Links Policies SHALL Be Enabled” section of the *Defender for Office 365 Minimum Viable Secure Configuration Baseline.* -### 2.15.1 Policy +### Policies -- URL comparison with a block-list SHOULD be enabled. +#### MS.EXO.15.1v1 +URL comparison with a block-list SHOULD be enabled. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- Direct download links SHOULD be scanned for malware. +#### MS.EXO.15.2v1 +Direct download links SHOULD be scanned for malware. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- User click tracking SHOULD be enabled. +#### MS.EXO.15.3v1 +User click tracking SHOULD be enabled. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -### 2.15.2 Resources +### Resources - The “Safe Links Policies SHOULD Be Enabled” section of the *Defender for Office 365 Minimum Viable Secure Configuration Baseline*. -## 2.16 Alerts SHALL Be Enabled +## 16. Alerts Microsoft Defender includes several prebuilt alert policies, many of which pertain to Exchange Online. These alerts give admins better @@ -710,9 +786,9 @@ configuring alerts in Microsoft Defender is given in the “Alerts SHALL Be Enabled” section of the *Defender for Office 365 Minimum Viable Secure Configuration Baseline*. -### 2.16.1 Policy - -- At a minimum, the following alerts SHALL be enabled: +### Policies +#### MS.EXO.16.1v1 +At a minimum, the following alerts SHALL be enabled: - Suspicious email sending patterns detected. @@ -731,16 +807,20 @@ Secure Configuration Baseline*. - Malware campaign detected after delivery. - A potentially malicious URL click was detected. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- The alerts SHOULD be sent to a monitored address or incorporated into - a SIEM. +#### MS.EXO.16.2v1 +The alerts SHOULD be sent to a monitored address or incorporated into a SIEM. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -### 2.16.2 Resources +### Resources - The “Alerts SHALL Be Enabled” section of the *Defender for Office 365 Minimum Viable Secure Configuration Baseline*. -## 2.17 Unified Audit Logging SHALL Be Enabled +## 17. Unified Audit Logging Unified audit logging generates logs of user activity in M365 services. These logs are essential for conducting incident response and threat detection activity. @@ -757,17 +837,23 @@ guidance configuring audit logging, see the “Audit Logging SHALL Be Enabled” section of the *Defender for Office 365 Minimum Viable Secure Configuration Baseline*. -### 2.17.1 Policy - -- Unified audit logging SHALL be enabled. +### Policies +#### MS.EXO.17.1v1 +Unified audit logging SHALL be enabled. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- Advanced audit SHALL be enabled. +#### MS.EXO.17.2v1 +Advanced audit SHALL be enabled. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- Audit logs SHALL be maintained for at least the minimum duration - dictated by [OMB M-21-31 (Appendix - C)](https://www.whitehouse.gov/wp-content/uploads/2021/08/M-21-31-Improving-the-Federal-Governments-Investigative-and-Remediation-Capabilities-Related-to-Cybersecurity-Incidents.pdf). +#### MS.EXO.17.3v1 +Audit logs SHALL be maintained for at least the minimum duration dictated by [OMB M-21-31 (Appendix C)](https://www.whitehouse.gov/wp-content/uploads/2021/08/M-21-31-Improving-the-Federal-Governments-Investigative-and-Remediation-Capabilities-Related-to-Cybersecurity-Incidents.pdf). +- _Rationale:_ TODO +- _Last modified:_ June 2023 -### 2.17.2 Resources +### Resources - The “Unified Audit Logging SHALL Be Enabled” section of the *Defender for Office 365 Minimum Viable Secure Configuration Baseline*. diff --git a/baselines/onedrive.md b/baselines/onedrive.md index b54c4fa911..170eea0baf 100644 --- a/baselines/onedrive.md +++ b/baselines/onedrive.md @@ -1,4 +1,4 @@ -# 1. Introduction +# Introduction OneDrive for Business is a cloud-based file storage system with online editing and collaboration tools for Microsoft Office documents and is @@ -9,7 +9,7 @@ collaboration with multiple people. This security baseline applies guidance from industry benchmarks on how to secure cloud solutions on Azure. -## 1.1 Assumptions +## Assumptions These baseline specifications assume that the agency is using OneDrive for Business, not personal or school versions, and allowing access using @@ -25,7 +25,7 @@ or [G3](https://www.microsoft.com/en-us/microsoft-365/government) license level. Therefore, only licenses not included in E3/G3 are listed. -## 1.2 Resources +## Resources **License Compliance and Copyright** @@ -41,9 +41,9 @@ document. The United States Government has adapted selections of these documents to develop innovative and scalable configuration standards to strengthen the security of widely used cloud-based software services. -# 2. Baseline +# Baseline -## 2.1 Anyone Links SHOULD Be Turned Off +## 1. Anyone Links Unauthenticated sharing (Anyone links) is used to share data without authentication and users are free to pass it on to others outside the @@ -51,20 +51,23 @@ agency. To prevent users from unauthenticated sharing of content, turn off Anyone sharing for users outside the tenant when accessing content in SharePoint, Groups, or Teams. -### 2.1.1 Policy +### Policies -- Anyone links SHOULD be disabled. +#### MS.ONEDRIVE.1.1v1 +Anyone links SHOULD be disabled. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -### 2.1.2 Resources +### Resources - [Limit accidental exposure \| Microsoft Docs](https://docs.microsoft.com/en-us/microsoft-365/solutions/share-limit-accidental-exposure?view=o365-worldwide) -### 2.1.3 License Requirements +### License Requirements - N/A -### 2.1.4 Implementation +### Implementation **Note**: OneDrive settings can be more restrictive than the SharePoint setting, but not more permissive. @@ -95,7 +98,7 @@ To turn off Anyone links for a site: 5. Click **Save**. -## 2.2 Expiration Date SHOULD Be Set for Anyone Links +## 2. Expiration Date for Anyone Links Files that are stored in SharePoint sites, Groups, and Teams for months and years could lead to unexpected modifications to files if shared with @@ -104,22 +107,28 @@ can help avoid unwanted changes. If Anyone links are enabled, the expiration date SHOULD be set to thirty days or as determined by mission needs or agency policy. -### 2.2.1 Policy +### Policies -- An expiration date SHOULD be set for Anyone links. +#### MS.ONEDRIVE.2.1v1 +Expiration Date SHOULD Be Set for Anyone Links. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- Expiration date SHOULD be set to thirty days. +#### MS.ONEDRIVE.2.2v1 +Expiration date SHOULD be set to thirty days. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -### 2.2.2 Resources +### Resources - [Best practices for unauthenticated sharing \| Microsoft Docs](https://docs.microsoft.com/en-us/microsoft-365/solutions/best-practices-anonymous-sharing?view=o365-worldwide) -### 2.2.3 License Requirements +### License Requirements - N/A -### 2.2.4 Implementation +### Implementation To set an expiration date for Anyone links across the agency (**Note**: Anyone links must be enabled). @@ -153,27 +162,30 @@ To set an expiration date for Anyone links on a specific site: 5. Click **Save**. -## 2.3 Link Permissions SHOULD Be Set to Enabled Anyone Links to View +## 3. Link Permissions The Anyone links default to allow people to edit files, as well as edit and view files and upload new files to folders. To allow unauthenticated sharing but keep unauthenticated people from modifying the agency's content, consider setting the file and folder permissions to **View**. -### 2.3.1 Policy +### Policies -- Anyone link permissions SHOULD be limited to View. +#### MS.ONEDRIVE.3.1v1 +Link Permissions SHOULD Be Set to Enabled Anyone Links to View. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -### 2.3.2 Resources +### Resources - [Set link permissions \| Microsoft Docs](https://docs.microsoft.com/en-us/microsoft-365/solutions/best-practices-anonymous-sharing?view=o365-worldwide#set-link-permissions) -### 2.3.3 License Requirements +### License Requirements - N/A -### 2.3.4 Implementation +### Implementation 1. Open the **SharePoint admin center**. @@ -183,27 +195,29 @@ content, consider setting the file and folder permissions to **View**. 3. Under **Advanced settings for Anyone links**, set the file and folder permissions to **View**. -## 2.4 OneDrive Client SHALL Be Restricted to Windows for Agency-Defined Domain(s) +## 4. OneDrive Client Configuring OneDrive to sync only to agency-defined domains ensures that users can only sync to agency-managed computers. -### 2.4.1 Policy +### Policies -- OneDrive Client for Windows SHALL be restricted to agency-Defined - Domain(s). +#### MS.ONEDRIVE.4.1v1 +OneDrive Client SHALL Be Restricted to Windows for Agency-Defined Domain(s). +- _Rationale:_ TODO +- _Last modified:_ June 2023 -### 2.4.2 Resources +### Resources - [Allow syncing only on computers joined to specific domains – OneDrive \| Microsoft Docs](https://docs.microsoft.com/en-us/onedrive/allow-syncing-only-on-specific-domains) -### 2.4.3 License Requirements +### License Requirements - N/A -### 2.4.4 Implementation +### Implementation 1. Open the **SharePoint admin center.** @@ -218,7 +232,7 @@ users can only sync to agency-managed computers. domains** check box. 5. Add the [Globally Unique Identifier (GUID) of each - domain](https://docs.microsoft.com/en-us/powershell/module/activedirectory/get-addomain?view=windowsserver2022-ps) for + domain](https://docs.microsoft.com/en-us/powershell/module/activedirectory/get-addomain?view=windowsserver2022-ps) for the member computers that the agency wants to be able to sync. **Note:** Add the domain GUID of the computer domain membership. If @@ -233,28 +247,30 @@ instead. 6. Click **Save**. -## 2.5 OneDrive Client SHALL Be Restricted to Sync with Mac for Agency-Defined Devices +## 5. Sync with Mac for Agency-Defined Devices Set restrictions on whether users can sync items to non-domain joined machines, control the list of allowed domains, and manage whether Mac clients (which do not support domain join) can sync. -### 2.5.1 Policy +### Policies -- OneDrive Client Sync SHALL only be allowed only within the local - domain. +#### MS.ONEDRIVE.5.1v1 +OneDrive Client SHALL Be Restricted to Sync with Mac for Agency-Defined Devices. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -### 2.5.2 Resources +### Resources - [Set-SPOTenantSyncClientRestriction (SharePointOnlinePowerShell) \| Microsoft Docs](https://docs.microsoft.com/en-us/powershell/module/sharepoint-online/set-spotenantsyncclientrestriction?view=sharepoint-ps#:~:text=In%20order%20to%20explicitly%20block%20Microsoft%20OneDrive%20client,cmdlet%20with%20the%20BlockMacSync%20parameter%20set%20to%20true.?msclkid=f80f95c5c4c611ecac7de0980370f33c) -### 2.5.3 License Requirements +### License Requirements - N/A -### 2.5.4 Implementation +### Implementation The `Set-SPOTenantSyncClientRestriction` cmdlet can be used to enable the feature for tenancy and set the domain GUIDs in the safe recipients @@ -266,26 +282,29 @@ reflected within five minutes. "786548DD-877B-4760-A749-6B1EFBC1190A; 877564FF-877B-4760-A749-6B1EFBC1190A" -BlockMacSync:$false` -## 2.6 OneDrive Client Sync SHALL Only Be Allowed Within the Local Domain +## 6. Local Domain Sync Configuring OneDrive to sync only to agency-defined domains ensures that users can only sync to agency-managed computers. -### 2.6.1 Policy +### Policies -- OneDrive Client Sync SHALL be restricted to the local domain. +#### MS.ONEDRIVE.6.1v1 +OneDrive Client Sync SHALL Only Be Allowed Within the Local Domain. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -### 2.6.2 Resources +### Resources - [Allow syncing only on computers joined to specific domains \| Microsoft Documents](https://docs.microsoft.com/en-us/onedrive/allow-syncing-only-on-specific-domains) -### 2.6.3 License Requirements +### License Requirements - N/A -### 2.6.4 Implementation +### Implementation 1. Open the **SharePoint admin center**. @@ -298,7 +317,7 @@ users can only sync to agency-managed computers. computers joined to specific domains** is checked, and that a domain GUID displays in the box below it. -## 2.7 Legacy Authentication SHALL Be Blocked +## 7. Legacy Authentication Modern authentication, based on Active Directory Authentication Library (ADAL) and Open Authorization 2 (OAuth2), is a critical component of @@ -311,20 +330,23 @@ important to make sure that only apps that support modern authentication are allowed to connect, assuring that only authorized devices are allowed to access enterprise data. -### 2.7.1 Policy +### Policies -- Legacy Authentication SHALL be blocked. +#### MS.ONEDRIVE.7.1v1 +Legacy Authentication SHALL Be Blocked. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -### 2.7.2 Resources +### Resources - [Control access from unmanaged devices \| Microsoft Documents](https://docs.microsoft.com/en-us/sharepoint/control-access-from-unmanaged-devices) -### 2.7.3 License Requirements +### License Requirements - N/A -### 2.7.4 Implementation +### Implementation 1. Open the **SharePoint admin center**. diff --git a/baselines/powerbi.md b/baselines/powerbi.md index 0259e6770d..adcf40d9ff 100644 --- a/baselines/powerbi.md +++ b/baselines/powerbi.md @@ -1,4 +1,4 @@ -# 1. Introduction +# Introduction Power BI is a Software as a Service (SaaS) offering from Microsoft that facilitates self-service business intelligence dashboards, reports, @@ -20,7 +20,7 @@ additional detail, please refer to the [Power BI Security](https://docs.microsoft.com/en-us/power-bi/enterprise/service-admin-power-bi-security) documentation page.) -## 1.1 Scope +## Scope This baseline focuses on the Power BI SaaS service that comes integrated with Microsoft 365, noting that there is also a desktop version of Power @@ -32,7 +32,7 @@ separate Power BI desktop baseline with tailored security requirements and considerations should be developed by security and end user operations staff. -## 1.2 Resources +## Resources **License Compliance and Copyright** @@ -48,7 +48,7 @@ document. The United States Government has adapted selections of these documents to develop innovative and scalable configuration standards to strengthen the security of widely used cloud-based software services. -## 1.3 Assumptions +## Assumptions Agencies using Power BI have a data classification scheme in place for the data entering Power BI. @@ -69,9 +69,9 @@ Agencies using Power BI have a data classification scheme in place for simplification of data management and access at enterprise scale. -# 2. Baseline +# Baseline -## 2.1 External Sharing SHOULD be Disabled +## 1. External Sharing External sharing can represent a potential security risk, therefore, disabling it is a best practice unless specific, approved use cases make @@ -102,35 +102,27 @@ People outside the tenant agency cannot see any data if role or row-level security is implemented on on-premises Analysis Services tabular models. -### 2.1.1 Policy +### Policies +#### MS.POWERBI.1.1v1 +External sharing SHOULD be disabled unless the agency mission requires the capability. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- External sharing SHOULD be disabled unless the agency mission requires - the capability. +#### MS.POWERBI.1.2v1 +If external sharing is deemed appropriate, the agency SHOULD limit the sharing ability to a security group. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- If external sharing is deemed appropriate, the agency SHOULD limit the - sharing ability to a security group instead of the entire agency. - -### 2.1.2 Resources +### Resources - [Power BI Tenant settings \| Microsoft Docs](https://docs.microsoft.com/en-us/power-bi/guidance/admin-tenant-settings) -### 2.1.3 License Requirements +### License Requirements - N/A -### 2.1.4 Implementation - -1. In the **Power BI tenant admin portal**, go to **Export and Sharing - Settings.** - -2. Disable the **External sharing** toggle. - -3. If the agency approves external sharing, select a specific security - group that includes users who should be able to share data and - reports externally. - -## 2.2 Publish to Web SHOULD be Disabled +## 2. Publish to Web Power BI has a capability to publish reports and content to the web. This capability creates a publicly accessible web URL that does not @@ -144,12 +136,13 @@ admins should limit the ability to publish to the web to only specific security groups, instead of allowing the entire agency to publish data to the web. -### 2.2.1 Policy - -- The Publish to Web feature SHOULD be disabled unless the agency - mission requires the capability. +### Policies +#### MS.POWERBI.2.1v1 +The Publish to Web feature SHOULD be disabled unless the agency mission requires the capability. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -### 2.2.2 Resources +### Resources - [Power BI Tenant settings \| Microsoft Docs](https://docs.microsoft.com/en-us/power-bi/guidance/admin-tenant-settings) @@ -157,27 +150,12 @@ to the web. - [Power BI Security Baseline v2.0 \| Microsoft benchmarks GitHub repo](https://github.com/MicrosoftDocs/SecurityBenchmarks/blob/master/Azure%20Offer%20Security%20Baselines/2.0/power-bi-security-baseline-v2.0.xlsx) -### 2.2.3 License Requirements +### License Requirements - N/A -### 2.2.4 Implementation - -***Confirm Publish to web is disabled*** -The **Publish to web** setting in the admin portal gives options for -users to create embed codes. It is recommended that agencies disallow -publishing to the web pending further justification reviews by -information security. - -1. Administrators can set **Publish to web** to **Disabled.** - -2. However, if **Publish to web** is set to **enabled**, admins - can **Choose how embed codes work** to **Allow only existing embed - codes**. In that case, users can create embed codes, but they must - contact the tenant’s Power BI admin to allow them to do so. - -## 2.3 Power BI Guest Access SHOULD be Disabled +## 3. Power BI Guest Access A best practice is to disallow guest user access. Disallowing guest access also aligns with zero trust principles. The agency with @@ -215,12 +193,13 @@ allow these users to use people pickers within the Power BI UX. Since Power BI integrates natively with AAD, the AAD Baseline should be consulted for additional guidance on managing guest users. -### 2.3.1 Policy +### Policies +#### MS.POWERBI.3.1v1 +Guest user access to the Power BI tenant SHOULD be disabled unless the agency mission requires the capability. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- Guest user access to the Power BI tenant SHOULD be disabled unless the - agency mission requires the capability. - -### 2.3.2 Resources +### Resources - [Power BI Tenant settings \| Microsoft Docs](https://docs.microsoft.com/en-us/power-bi/guidance/admin-tenant-settings) @@ -228,19 +207,12 @@ consulted for additional guidance on managing guest users. - [Power BI Security Baseline v2.0 \| Microsoft benchmarks GitHub repo](https://github.com/MicrosoftDocs/SecurityBenchmarks/blob/master/Azure%20Offer%20Security%20Baselines/2.0/power-bi-security-baseline-v2.0.xlsx) -### 2.3.3 License Requirements +### License Requirements - N/A -### 2.3.4 Implementation - -1. In the **tenant admin portal**, go to **Export and Sharing - Settings**. - -2. Disable the **Allow Azure Active Directory guest users to access - Power BI** toggle. -## 2.4 External Invitations SHOULD be Disabled +## 4. External Invitations This setting controls whether Power BI allows inviting external users to the agency’s organization through Power BI’s sharing workflows and @@ -266,12 +238,13 @@ controls the ability to invite guest users through Power BI. See the *AAD Minimum Viable Secure Configuration Baseline* for more information on roles. -### 2.4.1 Policy +### Policies +#### MS.POWERBI.4.1v1 +The **Invite external users to your organization** feature SHOULD be disabled unless agency mission requires the capability. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- The **Invite external users to your organization** feature SHOULD be - disabled unless agency mission requires the capability. - -### 2.4.2 Resources +### Resources - [Power BI Tenant settings \| Microsoft Docs](https://docs.microsoft.com/en-us/power-bi/guidance/admin-tenant-settings) @@ -283,17 +256,12 @@ on roles. - [Power BI Security Baseline v2.0 \| Microsoft benchmarks GitHub repo](https://github.com/MicrosoftDocs/SecurityBenchmarks/blob/master/Azure%20Offer%20Security%20Baselines/2.0/power-bi-security-baseline-v2.0.xlsx) -### 2.4.3 License Requirements +### License Requirements - N/A -### 2.4.4 Implementation - -1. In the tenant admin portal, go to **Export and Sharing Settings**. - -2. Disable the **Invite external users to your organization** toggle. -## 2.5 The External Editing Capability SHOULD be Disabled +## 5. The External Editing It is possible to give external guest users the ability to edit and manage Power BI content; however, this could have considerable data @@ -305,12 +273,13 @@ If there is a mission need to allow external users to edit and manage Power BI content, the recommended best practice is to assign these entities to a security group. -### 2.5.1 Policy +### Policies +#### MS.POWERBI.5.1v1 +The external editing capability SHOULD be disabled unless agency mission requires the capability. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- The external editing capability SHOULD be disabled unless agency - mission requires the capability. - -### 2.5.2 Resources +### Resources - [Power BI Tenant settings \| Microsoft Docs](https://docs.microsoft.com/en-us/power-bi/guidance/admin-tenant-settings) @@ -322,20 +291,14 @@ entities to a security group. - [Power BI Security Baseline v2.0 \| Microsoft benchmarks GitHub repo](https://github.com/MicrosoftDocs/SecurityBenchmarks/blob/master/Azure%20Offer%20Security%20Baselines/2.0/power-bi-security-baseline-v2.0.xlsx) -### 2.5.3 License Requirements +### License Requirements If this setting is enabled, an AAD B2B guest user must have a Power BI Pro license in a workspace other than the “My workspace” area to edit and manage content within the inviting organization’s Power BI tenant. -### 2.5.4 Implementation - -1. In the tenant admin portal, go to **Export and Sharing Settings**. - -2. Disable the toggle labeled **Allow Azure Active Directory guest - users to edit and manage content in the organization**. -## 2.6 Service Principals SHALL be Allowed to be Used to Securely Manage Application Identities +## 6. Service Principals Power BI supports the use of service principals to manage application identities. Service principals can use application programming @@ -374,15 +337,19 @@ permissions. - Instead of enabling service principals for the entire agency, implement for a dedicated security group. -### 2.6.1 Policy +### Policies +#### MS.POWERBI.6.1v1 +Service Principals SHOULD be allowed for Power BI where applicable. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- Service Principals SHOULD be allowed for Power BI where applicable. - -- Service Principal credentials used for encrypting or accessing Power - BI SHALL NOT be stored in scripts or config files and SHALL be stored +#### MS.POWERBI.6.2v1 +Service Principal credentials used for encrypting or accessing Power BI SHALL NOT be stored in scripts or config files and SHALL be stored in a secure vault such as Azure Key Vault. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -### 2.6.2 Resources +### Resources - [Automate Premium workspace and dataset tasks with service principal \| Microsoft @@ -407,31 +374,11 @@ permissions. Microsoft Docs](https://docs.microsoft.com/en-us/security/benchmark/azure/baselines/power-bi-security-baseline) -### 2.6.3 License Requirements +### License Requirements - N/A -### 2.6.4 Implementation - -Standardize on a single authoritative identity and access management -source (note that AAD integrates natively for Power BI). - -1. In the **tenant settings** - -2. Confirm that service principals are enabled in the **Allow service principals to use Power BI APIs** option. - -3. Confirm that the service principal is restricted to a security group -related to Power BI, rather than open to the entire agency. (Note: -Service principals have access to any tenant settings for which -they are enabled. Depending on the agency’s admin settings, this -includes specific security groups or the entire agency.) - -To restrict service principal access to specific tenant settings, it is -recommended to allow access only to specific security groups. -Alternatively, one can create a dedicated security group for service -principals and exclude it from the desired tenant settings. - -## 2.7 ResourceKey Authentication SHOULD be Blocked +## 7. ResourceKey Authentication This setting pertains to the security and development of Power BI embedded content. The Power BI tenant states that “for extra security, @@ -452,12 +399,13 @@ to streaming and PUSH datasets using the API with a resource key. However, if developers have an approved need to leverage this feature, an exception to the policy can be investigated. -### 2.7.1 Policy - -- ResourceKey Authentication SHOULD be blocked unless a specific use - case (e.g., streaming and/or PUSH datasets) merits its use. +### Policies +#### MS.POWERBI.7.1v1 +RourceKey Authentication SHOULD be blocked unless a specific use case (e.g., streaming and/or PUSH datasets) merits its use. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -### 2.7.2 Resources +### Resources - [Power BI Tenant settings \| Microsoft Docs](https://docs.microsoft.com/en-us/power-bi/guidance/admin-tenant-settings) @@ -465,16 +413,11 @@ an exception to the policy can be investigated. - [Real-time streaming in Power BI \| Microsoft Docs](https://docs.microsoft.com/en-us/power-bi/connect-data/service-real-time-streaming) -### 2.7.3 License Requirements +### License Requirements - N/A -### 2.7.4 Implementation - -1. Under **Developer Settings** in the Power BI tenant admin portal, - toggle **Block ResourceKey Authentication** to an enabled state. - -## 2.8 Python and R Visual Sharing SHOULD be Disabled +## 8. Python and R Visual Sharing Power BI can interact with Python and R scripts to integrate visualizations from these languages. Python visuals are created from @@ -485,27 +428,23 @@ visuals should only be enabled if the author and source are trusted, or after a code review of the Python/R script(s) in question is conducted and deems the scripts free of security risks. -### 2.8.1 Policy - -- R and Python interactions SHOULD be disabled. +### Policies +#### MS.POWERBI.8.1v1 +R and Python interactions SHOULD be disabled. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -### 2.8.2 Resources +### Resources - [Power BI Visuals and Python \| Microsoft Docs](https://docs.microsoft.com/en-us/power-bi/connect-data/desktop-python-visuals) -### 2.8.3 License Requirements +### License Requirements - N/A -### 2.8.4 Implementation - -1. In the **Power BI tenant**, go to **R and Python Visuals Settings**. -2. Toggle off the **Interact with and share R and Python visuals** - option. - -## 2.9 Data Stewards and Power BI Admins SHOULD Discover, Classify, and Label Sensitive Data +## 9. Sensitive Data There are multiple ways to secure sensitive information, such as warning users, encryption, or blocking attempts to share. Use Microsoft @@ -521,12 +460,13 @@ tool for securing power Power BI datasets. Refer to the *Defender for Office 365 Minimum Viable Secure Configuration Baseline* for more on DLP. -### 2.9.1 Policy - -- Sensitivity labels SHOULD be enabled for Power BI and employed for - sensitive data per enterprise data protection policies. +### Policies +#### MS.POWERBI.9.1v1 +Sensitivity labels SHOULD be enabled for Power BI and employed for sensitive data per enterprise data protection policies. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -### 2.9.2 Resources +### Resources - [Enable sensitivity labels in Power BI \| Microsoft Docs](https://docs.microsoft.com/en-us/power-bi/admin/service-security-enable-data-sensitivity-labels) @@ -540,14 +480,14 @@ DLP. - [Power BI Security Baseline v2.0 \| Microsoft benchmarks GitHub repo](https://github.com/MicrosoftDocs/SecurityBenchmarks/blob/master/Azure%20Offer%20Security%20Baselines/2.0/power-bi-security-baseline-v2.0.xlsx) -### 2.9.3 License Requirements +### License Requirements - An Azure Information Protection Premium P1 or Premium P2 license is required to apply or view Microsoft Information Protection sensitivity labels in Power BI. Azure Information Protection can be purchased either standalone or through one of the Microsoft licensing suites. - See [Azure Information Protection - pricing](https://azure.microsoft.com/services/information-protection/) for + See [Azure Information Protection + pricing](https://azure.microsoft.com/services/information-protection/) for detail. - Azure Information Protection sensitivity labels need to be migrated to @@ -565,47 +505,7 @@ DLP. policies](https://docs.microsoft.com/en-us/microsoft-365/compliance/create-sensitivity-labels) for detail. -### 2.9.4 Implementation - -**Enable Sensitivity Labels in Power BI:** - -Sensitivity labels must be enabled on the tenant before they can be used -in both the Power BI service and in Desktop. This section describes how -to enable them in the tenant settings. - -To enable sensitivity labels on the tenant: - -1. Navigate to the **Power BI Admin portal**-\>**Tenant - settings** pane-\> **Information protection** section. - -2. In the **Information Protection** section, perform the following - steps: - -3. Open **Allow users to apply sensitivity labels for Power BI - content**. - -4. Enable the toggle. - -5. Define who can apply and change sensitivity labels in Power BI - assets. By default, everyone in the agency will be able to apply - sensitivity labels; however, one can choose to enable setting - sensitivity labels only for specific users or security groups. With - either the entire agency or specific security groups selected, one - can exclude specific subsets of users or security groups. - -6. When sensitivity labels are enabled for the entire agency, - exceptions are typically security groups. - -7. When sensitivity labels are enabled only for specific users or - security groups, exceptions are typically specific users. - -This approach makes it possible to prevent certain users from applying -sensitivity labels in Power BI, even if they belong to a group that -has permissions to do so. - -8. Click **Apply**. - -## 2.10 Audit Logs SHALL be Enabled in Power BI Tenant +## 10. Audit Logs The Power BI tenant has a setting for audit log generation to monitor internal activity and compliance. Users within the agency can use @@ -615,11 +515,13 @@ enabled recording user and admin activity in the Office 365 Admin Portal, in which case this setting appears enabled but greyed out in the tenant settings. -### 2.10.1 Policy - -- Power BI audit log generation SHALL be enabled in the Power BI tenant. +### Policies +#### MS.POWERBI.10.1v1 +Power BI audit log generation SHALL be enabled in the Power BI tenant. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -### 2.10.2 Resources +### Resources - [Power BI Tenant settings \| Microsoft Docs](https://docs.microsoft.com/en-us/power-bi/guidance/admin-tenant-settings) @@ -635,18 +537,10 @@ tenant settings. - [Power BI Security Baseline v2.0 \| Microsoft benchmarks GitHub repo](https://github.com/MicrosoftDocs/SecurityBenchmarks/blob/master/Azure%20Offer%20Security%20Baselines/2.0/power-bi-security-baseline-v2.0.xlsx) -### 2.10.3 License Requirements +### License Requirements - N/A -### 2.10.4 Implementation - -1. In the **Power BI tenant**, go to **Audit and Usage Settings.** - -2. Enable **Create audit logs for internal activity auditing and - compliance**. This setting may already be enabled and greyed out if - audit recording has been turned on in the M365 admin portal. - # Acknowledgements @@ -755,8 +649,8 @@ the agency. required to apply or view Microsoft Information Protection sensitivity labels in Power BI. Azure Information Protection can be purchased either standalone or through one of the Microsoft licensing suites. - See [Azure Information Protection - pricing](https://azure.microsoft.com/services/information-protection/) for + See [Azure Information Protection + pricing](https://azure.microsoft.com/services/information-protection/) for detail. - Azure Information Protection sensitivity labels need to be migrated to diff --git a/baselines/powerplatform.md b/baselines/powerplatform.md index 3afb419317..d677034ed1 100644 --- a/baselines/powerplatform.md +++ b/baselines/powerplatform.md @@ -1,4 +1,4 @@ -# 1. Introduction +# Introduction The Microsoft Power Platform is a group of applications involving low-code application development, business intelligence, a custom chat @@ -41,7 +41,7 @@ often used to store data in SQL-like tables. A Power App would then use a connector to connect to the Dataverse table and perform create, read, update and delete (CRUD) operations. -## 1.1 Assumptions +## Assumptions The **License Requirements** sections of this document assume the organization is using an [M365 @@ -50,7 +50,7 @@ or [G3](https://www.microsoft.com/en-us/microsoft-365/government) license level. Therefore, only licenses not included in E3/G3 are listed. -## 1.2 Resources +## Resources **License Compliance and Copyright** @@ -66,7 +66,7 @@ document. The United States Government has adapted selections of these documents to develop innovative and scalable configuration standards to strengthen the security of widely used cloud-based software services. -# 2. Baseline +# Baseline Baselines in this section are for administrative controls that apply to all Power Platform applications at the Power Platform tenant and @@ -74,7 +74,7 @@ environment level. Additional Power Platform security settings would be implemented at the app level, connector level, or Dataverse table level. Refer to Microsoft documentation for those additional controls. -## 2.1 Creation of Power Platform Environments SHALL Be Restricted +## 1. Power Platform Environments Power Platform environments are used to group together, manage, and store Power Apps and Power Virtual Agents. By default, any user in the @@ -83,12 +83,13 @@ control will restrict the creation of new environments to users with the following admin roles: Global admins, Dynamics 365 admins, and Power Platform admins. -### 2.1.1 Policy +### Policies +#### MS.POWERPLATFORM.1.1v1 +The ability to create additional environments SHALL be restricted to admins. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- The ability to create additional environments SHALL be restricted to - admins. - -### 2.1.2 Resources +### Resources - [Control who can create and manage environments in the Power Platform admin center \| Microsoft @@ -100,11 +101,11 @@ Platform admins. - [Microsoft Technical Documentation \| Power Apps](https://docs.microsoft.com/en-us/power-apps/) -### 2.1.3 License Requirements +### License Requirements - N/A -### 2.1.4 Implementation +### Implementation 1. Sign in to the [Power Platform admin center](https://admin.powerplatform.microsoft.com/) or for GCC @@ -125,7 +126,7 @@ Platform admins. Now only Global admins, Dynamics 365 service admins, Power Platform Service admins, and Delegated admins can create environments. -## 2.2 Data Loss Prevention Policies for Power Platform Environments SHALL Be Created +## 2. Data Loss Prevention Policies To secure Power Platform environments Data Loss Prevention (DLP) policies can be created to restrict the connectors that can be used with @@ -153,16 +154,19 @@ restrict users in the Azure AD tenant from creating Power Apps in the default Power Platform environment. Admins can restrict users from creating apps in all other created environments. -### 2.2.1 Policy - -- A DLP policy SHALL be created to restrict connector access in the - default Power Platform environment. +### Policies +#### MS.POWERPLATFORM.2.1v1 +A DLP policy SHALL be created to restrict connector access in the default Power Platform environment. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- Non-default environments SHOULD have at least one DLP policy that - affects them. +#### MS.POWERPLATFORM.2.2v1 +Non-default environments SHOULD have at least one DLP policy that affects them. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- All connectors except those listed below SHOULD be added to the - Blocked category in the default environment policy: +#### MS.POWERPLATFORM.2.3v1 +All connectors except those listed below SHOULD be added to the Blocked category in the default environment policy: - Approvals @@ -198,9 +202,12 @@ creating apps in all other created environments. - Shifts for Microsoft Teams - - Yammer + - Yammer. -### 2.2.2 Resources +- _Rationale:_ TODO +- _Last modified:_ June 2023 + +### Resources - [Data Policies for Power Automate and Power Apps \| Digital Transformation Agency of @@ -209,11 +216,11 @@ creating apps in all other created environments. - [Create a data loss prevention (DLP) policy \| Microsoft Docs](https://docs.microsoft.com/en-us/power-platform/admin/create-dlp-policy) -### 2.2.3 License Requirements +### License Requirements - N/A -### 2.2.4 Implementation +### Implementation 1. Sign in to the [Power Platform admin center](https://admin.powerplatform.microsoft.com/) (for GCC @@ -253,7 +260,7 @@ blocked to the **Blocked** category. 14. Select **Next**-\> **Create Policy** to finish. -## 2.3 Tenant Isolation SHALL Be Enabled to Prevent Cross Tenant Access of Power Platform environments +## 3. Tenant Isolation Power Platform tenant isolation is different from Azure AD-wide tenant restriction. It does not impact Azure AD-based access outside of Power @@ -273,24 +280,33 @@ external tenants) cross-tenant connections are blocked by Power Platform even if the user presents valid credentials to the Azure AD-secured data source. -### 2.3.1 Policy +### Policies -- Power Platform tenant isolation SHALL be enabled. +#### MS.POWERPLATFORM.3.1v1 +Power Platform tenant isolation SHALL be enabled. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- An inbound/outbound connection allowlist SHOULD be configured. +#### MS.POWERPLATFORM.3.2v1 +An inbound/outbound connection allowlist SHOULD be configured. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- The allowlist MAY be empty. +#### MS.POWERPLATFORM.3.3v1 +The allowlist MAY be empty. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -### 2.3.2 Resources +### Resources - [Enable tenant isolation and configure allowlist \| Microsoft Docs](https://docs.microsoft.com/en-us/power-platform/admin/cross-tenant-restrictions#enable-tenant-isolation-and-configure-allowlist) -### 2.3.3 License Requirements +### License Requirements - N/A -### 2.3.4 Implementation +### Implementation 1. Sign in to the [Power Platform admin center](https://admin.powerplatform.microsoft.com/) or for GCC @@ -306,7 +322,7 @@ source. the allowlist. However, these rules won't be enforced until tenant isolation is turned **On**. -## 2.4 Content Security Policy SHALL Be Enabled +## 4. Content Security Policy Content Security Policy (CSP) is an added layer of security that helps to detect and mitigate certain types of attacks, including Cross-Site @@ -320,21 +336,22 @@ to apply this setting. Also, there is no current way to implement this setting for Canvas Apps. When enabled, this setting will apply to all current Model-driven apps at only the environment level. -### 2.4.1 Policy - -- Content security policies for model-driven Power Apps SHALL be - enabled. +### Policies +#### MS.POWERPLATFORM.4.1v1 +Content security policies for model-driven Power Apps SHALL be enabled. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -### 2.4.2 Resources +### Resources - [Content Security Policy \| Microsoft Docs](https://docs.microsoft.com/en-us/power-platform/admin/content-security-policy) -### 2.4.3 License Requirements +### License Requirements - N/A -### 2.4.4 Implementation +### Implementation 1. Sign in to [Make Power Apps](https://make.powerapps.com) (for GCC environments sign in to the [GCC Make Power diff --git a/baselines/sharepoint.md b/baselines/sharepoint.md index c7f06858af..b153f02bc2 100644 --- a/baselines/sharepoint.md +++ b/baselines/sharepoint.md @@ -1,4 +1,4 @@ -# 1. Introduction +# Introduction SharePoint Online is a web-based collaboration and document management platform. Though highly flexible, it is primarily used to store @@ -39,7 +39,7 @@ SharePoint Online): Source: -## 1.1 Resources +## Resources **License Compliance and Copyright** @@ -55,7 +55,7 @@ document. The United States Government has adapted selections of these documents to develop innovative and scalable configuration standards to strengthen the security of widely used cloud-based software services. -## 1.2 Assumptions +## Assumptions The **License Requirements** sections of this document assume the organization is using an [M365 @@ -64,29 +64,31 @@ or [G3](https://www.microsoft.com/en-us/microsoft-365/government) license level. Therefore, only licenses not included in E3/G3 are listed. -# 2. Baselines +# Baselines -## 2.1 File and Folder Links Default Sharing Settings SHALL Be Set to "Specific People (Only the People the User Specifies)" +## 1. File and Folder Links Default Sharing Settings This policy ensures that when sharing files in SharePoint, there are several possible scopes, including agency-wide or “anyone with the link.” -### 2.1.1 Policy +### Policies -- File and folder links default sharing setting SHALL be set to - “Specific People (Only the People the User Specifies)”. +#### MS.SHAREPOINT.1.1v1 +File and folder links default sharing setting SHALL be set to Specific People (Only the People the User Specifies). +- _Rationale:_ TODO +- _Last modified:_ June 2023 -### 2.1.2 Resources +### Resources - [File and folder links \| Microsoft Documents](https://docs.microsoft.com/en-us/sharepoint/turn-external-sharing-on-or-off#file-and-folder-links) -### 2.1.3 License Requirements +### License Requirements - N/A -### 2.1.4 Implementation +### Implementation In the **SharePoint admin** **center**: @@ -96,7 +98,7 @@ In the **SharePoint admin** **center**: 2. Under **File and folder links**, ensure that the default link type is set to **Specific people (only the people the user specifies)**. -## 2.2 External Sharing SHOULD be Set to “New and Existing Guests” and Managed Through Approved Domains and/or Security Groups Per Interagency Collaboration Needs. +## 2. External Sharing SharePoint allows sharing with users who are outside the agency, which is convenient but may pose a data loss or other information security @@ -116,21 +118,22 @@ the CIO Council's [Interagency Collaboration Program](https://community.max.gov/display/Egov/Interagency+Collaboration+Program)’s OMB Max Site for a list of .gov domains for sharing). -### 2.2.1 Policy +### Policies +#### MS.SHAREPOINT.2.1v1 +External sharing SHOULD be limited to approved domains and security groups per interagency collaboration needs. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- External sharing SHOULD be limited to approved domains and security - groups per interagency collaboration needs. - -### 2.2.2 Resources +### Resources - [Manage sharing settings \| Microsoft Documents](https://docs.microsoft.com/en-us/sharepoint/turn-external-sharing-on-or-off) -### 2.2.3 License Requirements +### License Requirements - N/A -### 2.2.4 Implementation +### Implementation To adjust sharing settings, in the **SharePoint admin center**: @@ -157,7 +160,7 @@ To adjust sharing settings, in the **SharePoint admin center**: 11. Select **Save.** -## 2.3 Sensitive SharePoint Sites SHOULD Adjust Their Default Sharing Settings to Those Best Aligning to Their Sensitivity Level +## 3. Sensitivity Levels SharePoint allows sharing with users who are outside the agency, which is convenient but may pose a data loss or other information security @@ -166,21 +169,22 @@ organizational settings agencies should evaluate each created site and adjust sharing settings best aligned to their respective sensitivity level. -### 2.3.1 Policy - -- Sharing settings for specific SharePoint sites SHOULD align to their - sensitivity level. +### Policies +#### MS.SHAREPOINT.3.1v1 +Sharing settings for specific SharePoint sites SHOULD align to their sensitivity level. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -### 2.3.2 Resources +### Resources - [Managing SharePoint Online Security: A Team Effort \| Microsoft Build](https://docs.microsoft.com/en-us/microsoft-365/community/sharepoint-security-a-team-effort) -### 2.3.3 License Requirements +### License Requirements - N/A -### 2.3.4 Implementation +### Implementation To limit external sharing by domain, in the **SharePoint admin center**: @@ -201,7 +205,7 @@ To limit external sharing by domain, in the **SharePoint admin center**: 8. Select **Save.** -## 2.4 Expiration Times for Guest Access to a Site or OneDrive, and Reauthentication Expiration Times for People Who Use a Verification Code, SHOULD Be Determined By Mission Needs / Agency Policy or Else Defaulted to 30 Days. +## 4. Guest Access to a Site or OneDrive SharePoint allows sharing with users who are outside the agency, which is convenient but may pose a data loss or other information security @@ -211,23 +215,27 @@ access to the site or OneDrive. **Note**: Adjusting this setting will adjust external sharing for OneDrive and Teams to the same, specified expiration times. -### 2.4.1 Policy +### Policies +#### MS.SHAREPOINT.4.1v1 +Expiration timers for guest access to a site or OneDrive and people who use a verification code SHOULD be set. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- Expiration timers for ‘guest access to a site or OneDrive’ and ‘people - who use a verification code’ SHOULD be set. +#### MS.SHAREPOINT.4.2v1 +Expiration timers SHOULD be set to 30 days. +- _Rationale:_ TODO +- _Last modified:_ June 2023 -- Expiration timers SHOULD be set to 30 days. - -### 2.4.2 License Requirements +### License Requirements - N/A -### 2.4.3 Resources +### Resources - [Managing SharePoint Online Security: A Team Effort \| Microsoft Build](https://docs.microsoft.com/en-us/microsoft-365/community/sharepoint-security-a-team-effort) -### 2.4.4 Implementation +### Implementation To limit external sharing by domain, in the **SharePoint admin center**: @@ -245,26 +253,26 @@ To limit external sharing by domain, in the **SharePoint admin center**: 6. Enter “30 days”. -## 2.5 Users SHALL Be Prevented from Running Custom Scripts +## 5. Custom Scripts Allowing users to run custom scripts can potentially allow malicious scripts to run in a trusted environment. For this reason, running custom scripts should not be allowed. -### 2.5.1 Policy - -- Users SHALL be prevented from running custom scripts. +### Policy +#### MS.SHAREPOINT.5.1v1 +Users SHALL be prevented from running custom scripts. -### 2.5.2 Resources +### Resources - [Allow or prevent custom script \| Microsoft Documents](https://docs.microsoft.com/en-us/sharepoint/allow-or-prevent-custom-script) -### 2.5.3 License Requirements +### License Requirements - N/A -### 2.5.4 Implementation +### Implementation In the **SharePoint Classic admin center**: diff --git a/baselines/teams.md b/baselines/teams.md index 2931a9e87c..ad0498066d 100644 --- a/baselines/teams.md +++ b/baselines/teams.md @@ -1,4 +1,4 @@ -# 1. Introduction +# Introduction Microsoft Teams is a text and live chat workspace in Microsoft 365 that supports video calls, chat messaging, screen-sharing, and file sharing. @@ -30,7 +30,7 @@ across Microsoft documentation): users, meaning users that are not logged in to any Microsoft or organization account, such as dial-in users.[^1] -## 1.1 Assumptions +## Assumptions The **License Requirements** sections of this document assume the organization is using an [M365 @@ -39,7 +39,7 @@ or [G3](https://www.microsoft.com/en-us/microsoft-365/government) license level. Therefore, only licenses not included in E3/G3 are listed. -## 1.2 Resources +## Resources **License Compliance and Copyright** @@ -55,39 +55,39 @@ document. The United States Government has adapted selections of these documents to develop innovative and scalable configuration standards to strengthen the security of widely used cloud-based software services. -# 2. Baseline +# Baseline -## 2.1 External Participants SHOULD NOT Be Enabled to Request Control of Shared Desktops or Windows in Meetings +## 1. Requesting Control of Shared Desktops or Windows This setting controls whether external meeting participants can request control of the shared desktop or window during the meeting. In this instance, the term “external participants” includes external users, B2B guest users, unmanaged users and anonymous users. -While there is some inherent risk in granting an external participant +### Policies + +#### MS.TEAMS.1.1v1 +External participants SHOULD NOT be enabled to request control of shared desktops or windows in the Global (Org-wide default) meeting policy or in custom meeting policies if any exist. + +- _Rationale:_ While there is some inherent risk in granting an external participant control of a shared screen, legitimate use cases for this exist. Furthermore, the risk is minimal as users cannot gain control of another user’s screen unless the user giving control explicitly accepts a control request. As such, while enabling external participants to request control is discouraged, it may be done, depending on agency need. +- _Last modified:_ July 2023 -### 2.1.1 Policy - -- External participants SHOULD NOT be enabled to request control of shared -desktops or windows in the Global (Org-wide default) meeting policy or -in custom meeting policies if any exist. - -### 2.1.2 Resources +### Resources - [Configure desktop sharing in Microsoft Teams \| Microsoft Docs](https://docs.microsoft.com/en-us/microsoftteams/configure-desktop-sharing) -### 2.1.3 License Requirements +### License Requirements - N/A -### 2.1.4 Implementation +### Implementation To ensure external participants do not have the ability to request control of the shared desktop or window in the meeting: @@ -105,29 +105,27 @@ control of the shared desktop or window in the meeting: 5. If custom policies have been created, repeat these steps for each policy, selecting the appropriate policy in step 3. -## 2.2 Anonymous Users SHALL NOT Be Enabled to Start Meetings +## 2. Starting Teams Meetings This setting controls which meeting participants can start a meeting. In this instance, the term “anonymous users” refers to any Teams users joining calls that are not authenticated through the agency’s tenant. -### 2.2.1 Policy - -- Anonymous users SHALL NOT be enabled to start meetings in the Global -(Org-wide default) meeting policy or in custom meeting policies if any -exist. +### Policies -### 2.2.2 Resources +#### MS.TEAMS.2.1v1 +Anonymous users SHALL NOT be enabled to start meetings in the Global (Org-wide default) meeting policy or in custom meeting policies if any exist. +- _Rationale:_ TODO add rationale. +- _Last modified:_ July 2023 +### Resources - [Meeting policy settings - Participants & guests \| Microsoft Docs](https://docs.microsoft.com/en-us/microsoftteams/meeting-policies-participants-and-guests) -### 2.2.3 License Requirements - +### License Requirements - N/A -### 2.2.4 Implementation - +### Implementation To configure settings for anonymous users: 1. Sign in to the [**Microsoft Teams admin @@ -143,37 +141,45 @@ To configure settings for anonymous users: 5. If custom policies have been created, repeat these steps for each policy, selecting the appropriate policy in step 3. -## 2.3 Automatic Admittance to Meetings SHOULD Be Restricted - +## 3. Automatic Admittance into meetings This setting controls which meeting participants wait in the lobby before they are admitted to the meeting. -### 2.3.1 Policy +### Policies -- Anonymous users, including dial-in users, SHOULD NOT be admitted - automatically. +#### MS.TEAMS.3.1v1 +Anonymous users, including dial-in users, SHOULD NOT be admitted automatically. +- _Rationale:_ TODO add rationale. +- _Last modified:_ July 2023 -- Internal users SHOULD be admitted automatically. +#### MS.TEAMS.3.2v1 +Internal users SHOULD be admitted automatically. +- _Rationale:_ TODO add rationale. +- _Last modified:_ July 2023 -- B2B guest users MAY be admitted automatically. +#### MS.TEAMS.3.3v1 +B2B guest users MAY be admitted automatically. +- _Rationale:_ TODO add rationale. +- _Last modified:_ July 2023 -- The above settings SHOULD be set in the Global (Org-wide default) - meeting policy. +#### MS.TEAMS.3.4v1 +MS.TEAMS.3.1.1, MS.TEAMS.3.2.1, and MS.TEAMS.3.3.1 SHOULD be applied in the Global (Org-wide default) meeting policy. +- _Rationale:_ TODO add rationale. +- _Last modified:_ July 2023 -- Custom meeting policies MAY be created that allow more flexibility for - specific users. - -### 2.3.2 Resources +#### MS.TEAMS.3.5v1 +Custom meeting policies MAY be created that allow more flexibility for specific users. +- _Rationale:_ TODO add rationale. +- _Last modified:_ July 2023 +### Resources - [Meeting policy settings - Participants & guests \| Microsoft Docs](https://docs.microsoft.com/en-us/microsoftteams/meeting-policies-participants-and-guests) -### 2.3.3 License Requirements - +### License Requirements - N/A -### 2.3.4 Implementation - +### Implementation To configure settings for automatic meeting admittance: 1. Sign in to the [**Microsoft Teams admin @@ -192,7 +198,7 @@ To configure settings for automatic meeting admittance: 6. If custom policies have been created, repeat these steps for each policy, selecting the appropriate policy in step 3. -## 2.4 External User Access SHALL Be Restricted +## 4. External User Access External access allows external users to look up internal users by their email address to initiate chats and calls entirely within Teams. @@ -214,13 +220,14 @@ Importantly, this setting only pertains to external users (i.e., members of a different M365 tenant). Access for unmanaged users is controlled separately. -### 2.4.1 Policy - -- External access SHALL only be enabled on a per-domain basis. +### Policies -- Anonymous users SHOULD be enabled to join meetings. +#### MS.TEAMS.4.1v1 +External access SHALL only be enabled on a per-domain basis. +- _Rationale:_ TODO add rationale. +- _Last modified:_ July 2023 -### 2.4.2 Resources +### Resources - [Manage external access in Microsoft Teams \| Microsoft Docs](https://docs.microsoft.com/en-us/microsoftteams/manage-external-access) @@ -232,11 +239,11 @@ separately. outside your organization \| Microsoft Docs](https://docs.microsoft.com/en-us/microsoftteams/communicate-with-users-from-other-organizations) -### 2.4.3 License Requirements +### License Requirements - N/A -### 2.4.4 Implementation +### Implementation To enable external access for only specific domains: @@ -253,33 +260,7 @@ To enable external access for only specific domains: 5. Click **Save.** -To enable anonymous users to join meetings: - -1. Sign in to the [**Microsoft Teams admin - center**](https://admin.teams.microsoft.com). - -2. Select **Meetings** **-\>** **Meeting settings**. - -3. Under **Participants**, set **Anonymous users can join a meeting** - to **On**. - -4. Click **Save**. - -Anonymous users can also be enabled/blocked on a per-policy basis. - -1. Sign in to the [**Microsoft Teams admin - center**](https://admin.teams.microsoft.com). - -2. Select **Meetings** **-\>** **Meeting policies**. - -3. Select the **Global (Org-wide default)**, or other policy as needed. - -4. Under **Participants & guests**, set **Let anonymous people join a - meeting** to **On**. - -5. Click **Save**. - -## 2.5 Unmanaged User Access SHALL Be Restricted +## 5. Unmanaged User Access Blocking contact with unmanaged Teams users prevents these users from looking up internal users by their email address and initiating chats @@ -287,26 +268,30 @@ and calls within Teams. These users would still be able to join calls, assuming anonymous join is enabled. Additionally, unmanaged users may be added to Teams chats if the internal user initiates the contact. -### 2.5.1 Policy - -- Unmanaged users SHALL NOT be enabled to initiate contact with internal +### Policies +#### MS.TEAMS.5.1v1 +Unmanaged users SHALL NOT be enabled to initiate contact with internal users. +- _Rationale:_ TODO add rationale. +- _Last modified:_ July 2023 - -- Internal users SHOULD NOT be enabled to initiate contact with unmanaged +#### MS.TEAMS.5.2v1 +Internal users SHOULD NOT be enabled to initiate contact with unmanaged users. +- _Rationale:_ TODO add rationale. +- _Last modified:_ July 2023 -### 2.5.2 Resources +### Resources - [Manage contact with external Teams users not managed by an organization \| Microsoft Docs](https://docs.microsoft.com/en-us/microsoftteams/manage-external-access#manage-contact-with-external-teams-users-not-managed-by-an-organization) -### 2.5.3 License Requirements +### License Requirements - N/A -### 2.5.4 Implementation +### Implementation Steps are outlined in [Manage contact with external Teams users not managed by an @@ -329,16 +314,18 @@ organization](https://docs.microsoft.com/en-us/microsoftteams/manage-external-ac 2. Clear the check next to **External users with Teams accounts not managed by an organization can contact users in my organization**. -## 2.6 Contact with Skype Users SHALL Be Blocked - -Microsoft officially retired Skype for Business Online on July 31, 2021, -and it is no longer supported. +## 6. Skype Users +Microsoft officially retired Skype for Business Online on July 31, 2021, and it is no longer supported. Skype for Business 2015 is slated for Apr 11, 2023 and Skype for Business Server 2015, 2016, 2019 LTSC and Server 2019 is slated for Oct 14, 2025. -### 2.6.1 Policy +### Policies -- Contact with Skype users SHALL be blocked. +#### MS.TEAMS.6.1v1 +Contact with Skype users SHALL be blocked. +- _Rationale:_ Microsoft officially retired Skype for Business Online on July 31, 2021, +and it is no longer supported. +- _Last modified:_ July 2023 -### 2.6.2 Resources +### Resources - [Communicate with Skype users \| Microsoft Docs](https://docs.microsoft.com/en-us/microsoftteams/manage-external-access#communicate-with-skype-users) @@ -346,11 +333,11 @@ Docs](https://docs.microsoft.com/en-us/microsoftteams/manage-external-access#com - [Skype for Business Online to Be Retired in 2021 \| Microsoft Teams Blog](https://techcommunity.microsoft.com/t5/microsoft-teams-blog/skype-for-business-online-to-be-retired-in-2021/ba-p/777833) -### 2.6.3 License Requirements +### License Requirements - N/A -### 2.6.4 Implementation +### Implementation Instructions for *enabling* communications with Skype users are outlined in [Communicate with Skype @@ -366,7 +353,7 @@ users](https://docs.microsoft.com/en-us/microsoftteams/manage-external-access#co 4. Click **Save**. -## 2.7 Teams Email Integration SHALL Be Disabled +## 7. Teams Email Integration Teams provides an optional feature that allows channels to have an email address and receive email. These channel email addresses are not under @@ -376,21 +363,23 @@ agencies do not have control over the security settings associated with this email. For this reason, email channel integration should be disabled. -### 2.7.1 Policy - -- Teams email integration SHALL be disabled. +### Policies +#### MS.TEAMS.7.1v1 +Teams email integration SHALL be disabled. +- _Rationale:_ TODO +- _Last modified:_ July 2023 -### 2.7.2 Resources +### Resources - [Email Integration \| Microsoft Docs](https://docs.microsoft.com/en-us/microsoftteams/enable-features-office-365#email-integration) -### 2.7.3 License Requirements +### License Requirements - Teams email integration is only available with E3/E5 licenses. It is not available in GCC or DoD tenants. -### 2.7.4 Implementation +### Implementation To ensure that teams email integration is disabled: @@ -402,7 +391,7 @@ To ensure that teams email integration is disabled: 3. Under the **Email integration** section, set **Allow users to send emails to a channel email address** to **Off**. -## 2.8 Only Approved Apps SHOULD Be Installed +## 8. App Management Teams is capable of integrating with the following classes of apps: @@ -414,18 +403,24 @@ Teams store. *Custom apps*: apps not published to the Teams store, such as apps under development, that users “sideload” into Teams. -### 2.8.1 Policy +### Policies -- Agencies SHOULD allow all apps published by Microsoft, but MAY block -specific Microsoft apps as needed. +#### MS.TEAMS.8.1v1 +Agencies SHOULD allow all apps published by Microsoft, but MAY block specific Microsoft apps as needed. +- _Rationale:_ TODO +- _Last modified:_ July 2023 -- Agencies SHOULD NOT allow installation of all third-party apps or custom -apps, but MAY allow specific apps as needed. +#### MS.TEAMS.8.2v1 +Agencies SHOULD NOT allow installation of all third-party apps or custom apps, but MAY allow specific apps as needed. +- _Rationale:_ TODO +- _Last modified:_ July 2023 -- Agencies SHALL establish policy dictating the app review and approval -process to be used by the agency. +#### MS.TEAMS.8.3v1 +Agencies SHALL establish policy dictating the app review and approval process to be used by the agency. +- _Rationale:_ TODO +- _Last modified:_ July 2023 -### 2.8.2 Resources +### Resources - [Manage app permission policies in Microsoft Teams \| Microsoft Docs](https://docs.microsoft.com/en-us/microsoftteams/teams-app-permission-policies) @@ -433,11 +428,11 @@ Docs](https://docs.microsoft.com/en-us/microsoftteams/teams-app-permission-polic - [Upload your app in Microsoft Teams \| Microsoft Docs](https://docs.microsoft.com/en-us/microsoftteams/platform/concepts/deploy-and-publish/apps-upload) -### 2.8.3 License Requirements +### License Requirements - N/A -### 2.8.4 Implementation +### Implementation To restrict which Team apps can be installed: @@ -465,25 +460,31 @@ To restrict which Team apps can be installed: 8. If custom policies have been created, repeat these steps for each policy, selecting the appropriate policy in step 3. -## 2.9 Cloud Recording of Teams Meetings SHOULD Be Disabled for Unapproved Users +## 9. Cloud Recording of Teams Meetings This setting determines whether video can be recorded in meetings hosted by a user, during one-on-one calls, and on group calls started by a user. Agencies should comply with any other applicable policies or legislation in addition to this guidance. -### 2.9.1 Policy +### Policies -- Cloud video recording SHOULD be disabled in the global (org-wide -default) meeting policy. +#### MS.TEAMS.9.1v1 +Cloud video recording SHOULD be disabled in the global (org-wide default) meeting policy. +- _Rationale:_ TODO +- _Last modified:_ July 2023 -- Alternate meeting policies MAY be created that allow agency-approved -users the ability to record. +#### MS.TEAMS.9.2v1 + Alternate meeting policies MAY be created that allow agency-approved users the ability to record. +- _Rationale:_ TODO +- _Last modified:_ July 2023 -- For all meeting polices that allow cloud recording, recordings SHOULD be -stored inside the country of that agency’s tenant. +#### MS.TEAMS.9.3v1 +For all meeting polices that allow cloud recording, recordings SHOULD be stored inside the country of that agencys tenant. +- _Rationale:_ TODO +- _Last modified:_ July 2023 -### 2.9.2 Resources +### Resources - [Teams cloud meeting recording \| Microsoft Docs](https://docs.microsoft.com/en-us/microsoftteams/cloud-recording) @@ -491,11 +492,11 @@ Docs](https://docs.microsoft.com/en-us/microsoftteams/cloud-recording) - [Assign policies in Teams – getting started \| Microsoft Docs](https://docs.microsoft.com/en-us/microsoftteams/policy-assignment-overview) -### 2.9.3 License Requirements +### License Requirements - N/A -### 2.9.4 Implementation +### Implementation To configure the Meeting policies for cloud video recording: @@ -539,26 +540,28 @@ record meetings: 9. Select **Apply**. -## 2.10 Only the Meeting Organizer SHOULD Be Able to Record Live Events +## 10. Recording of Live Events Live events are recorded by default. Agencies should increase their privacy by changing the policy so that events are only recorded at the organizer’s discretion. -### 2.10.1 Policy +### Policies +#### MS.TEAMS.10.1v1 +Record an event SHOULD be set to Organizer can record. +- _Rationale:_ TODO +- _Last modified:_ July 2023 -- Record an event SHOULD be set to Organizer can record. - -### 2.10.2 Resources +### Resources - [Live Event Recording Policies \| Microsoft Docs](https://docs.microsoft.com/en-us/microsoftteams/teams-live-events/live-events-recording-policies) -### 2.10.3 License Requirements +### License Requirements - N/A -### 2.10.4 Implementation +### Implementation 1. Sign in to the **[Microsoft Teams admin center](https://admin.teams.microsoft.com).** @@ -571,7 +574,7 @@ Docs](https://docs.microsoft.com/en-us/microsoftteams/teams-live-events/live-eve 5. Click **Save**. -## 2.11 Data Loss Prevention Solutions SHALL Be Enabled +## 11. Data Loss Prevention Data loss prevention (DLP) helps prevent both accidental leakage of sensitive information as well as intentional exfiltration of data. DLP @@ -589,24 +592,37 @@ Minimum Viable Secure Configuration Baseline*. The DLP solution selected by an agency should offer services comparable to those offered by Microsoft. -### 2.11.1 Policy +### Policies + +#### MS.TEAMS.11.1v1 +A DLP solution SHALL be enabled. +- _Rationale:_ TODO +- _Last modified:_ July 2023 -- A DLP solution SHALL be enabled. +#### MS.TEAMS.11.2v1 +Agencies SHOULD use either the native DLP solution offered by Microsoft or a DLP solution that offers comparable services. +- _Rationale:_ TODO +- _Last modified:_ July 2023 -- Agencies SHOULD use either the native DLP solution offered by Microsoft -or a DLP solution that offers comparable services. +#### MS.TEAMS.11.3v1 +Agencies SHOULD use either the native DLP solution offered by Microsoft or a DLP solution that offers comparable services. +- _Rationale:_ TODO +- _Last modified:_ July 2023 -- The DLP solution SHALL protect Personally Identifiable Information (PII) +#### MS.TEAMS.11.4v1 +The DLP solution SHALL protect Personally Identifiable Information (PII) and sensitive information, as defined by the agency. At a minimum, the sharing of credit card numbers, taxpayer Identification Numbers (TIN), and Social Security Numbers (SSN) via email SHALL be restricted. +- _Rationale:_ TODO +- _Last modified:_ July 2023 -### 2.11.2 Resources +### Resources - The “Data Loss Prevention SHALL Be Enabled” section of the *Defender for Office 365 Minimum Viable Secure Configuration Baseline*. -## 2.12 Attachments SHOULD Be Scanned for Malware +## 12. Attachment Scanning Though any product that fills the requirements outlined in this baseline control may be used, for guidance on implementing malware scanning using @@ -614,19 +630,24 @@ Microsoft Defender, see the “Data Loss Prevention SHALL Be Enabled” section of the *Defender for Office 365 Minimum Viable Secure Configuration Baseline*. -### 2.12.1 Policy +### Policies -- Attachments included with Teams messages SHOULD be scanned for malware. +#### MS.TEAMS.12.1v1 +Attachments included with Teams messages SHOULD be scanned for malware. +- _Rationale:_ TODO +- _Last modified:_ July 2023 -- Users SHOULD be prevented from opening or downloading files detected as -malware. +#### MS.TEAMS.12.2v1 +Users SHOULD be prevented from opening or downloading files detected as malware. +- _Rationale:_ TODO +- _Last modified:_ July 2023 -### 2.12.2 Resources +### Resources - The “Data Loss Prevention SHALL Be Enabled” section of the *Defender for Office 365 Minimum Viable Secure Configuration Baseline.* -## 2.13 Link Protection SHOULD Be Enabled +## 13. Link Protection Microsoft Defender protects users from malicious links included in Teams messages by prepending @@ -652,15 +673,24 @@ in the “Safe Links Policies SHALL Be Enabled” and “Safe Links in Global Settings SHALL be Configured” sections of the *Defender for Office 365 Minimum Viable Secure Configuration Baseline.* -### 2.13.1 Policy +### Policies -- URL comparison with a block-list SHOULD be enabled. +#### MS.TEAMS.13.1v1 +URL comparison with a block-list SHOULD be enabled. +- _Rationale:_ TODO +- _Last modified:_ July 2023 -- Direct download links SHOULD be scanned for malware. +#### MS.TEAMS.13.2v1 +Direct download links SHOULD be scanned for malware. +- _Rationale:_ TODO +- _Last modified:_ July 2023 -- User click tracking SHOULD be enabled. +#### MS.TEAMS.13.3v1 +User click tracking SHOULD be enabled. +- _Rationale:_ TODO +- _Last modified:_ July 2023 -### 2.13.2 Resources +### Resources - The “Safe Links Policies SHALL Be Enabled” section of the *Defender for Office 365 Minimum Viable Secure Configuration Baseline.* From 49b95c79640547f00c76d294487c9b7961c8e2b5 Mon Sep 17 00:00:00 2001 From: Richard Crutchfield Date: Thu, 25 May 2023 16:02:36 -0400 Subject: [PATCH 02/33] Initial drop of secure baseline automation (#336) * initial teams drop * Add markdown check * Fix spelling * Check action * Test Action * Check version * Fix Markdown test * Add path *.md * Update anchor func * Update AAD * WIP * WIP * WIP * WIP * WIP * Structural baseline updates (cleaned up) (#334) * Update aad.md all updates * Update defender.md all updates * Update exchange.md all updates * Rename exchange.md to exo.md * Update onedrive.md * Update powerbi.md all updates * Update powerplatform.md all updates * Update sharepoint.md all updates * Update teams.md all updates * Update baselines/defender.md good catch! Co-authored-by: Addam Schroll <108814318+schrolla@users.noreply.github.com> * Update baselines/powerbi.md Co-authored-by: Addam Schroll <108814318+schrolla@users.noreply.github.com> * Update baselines/powerbi.md Co-authored-by: Addam Schroll <108814318+schrolla@users.noreply.github.com> * Update baselines/aad.md Co-authored-by: Addam Schroll <108814318+schrolla@users.noreply.github.com> * Update aad.md referenced old policy number * Update powerbi.md --------- Co-authored-by: Addam Schroll <108814318+schrolla@users.noreply.github.com> * WIP * Structural baseline updates (cleaned up) (#334) * Update aad.md all updates * Update defender.md all updates * Update exchange.md all updates * Rename exchange.md to exo.md * Update onedrive.md * Update powerbi.md all updates * Update powerplatform.md all updates * Update sharepoint.md all updates * Update teams.md all updates * Update baselines/defender.md good catch! Co-authored-by: Addam Schroll <108814318+schrolla@users.noreply.github.com> * Update baselines/powerbi.md Co-authored-by: Addam Schroll <108814318+schrolla@users.noreply.github.com> * Update baselines/powerbi.md Co-authored-by: Addam Schroll <108814318+schrolla@users.noreply.github.com> * Update baselines/aad.md Co-authored-by: Addam Schroll <108814318+schrolla@users.noreply.github.com> * Update aad.md referenced old policy number * Update powerbi.md --------- Co-authored-by: Addam Schroll <108814318+schrolla@users.noreply.github.com> * initial teams drop * Update AAD * WIP * WIP * WIP * WIP * WIP * Structural baseline updates (cleaned up) (#334) * Update aad.md all updates * Update defender.md all updates * Update exchange.md all updates * Rename exchange.md to exo.md * Update onedrive.md * Update powerbi.md all updates * Update powerplatform.md all updates * Update sharepoint.md all updates * Update teams.md all updates * Update baselines/defender.md good catch! Co-authored-by: Addam Schroll <108814318+schrolla@users.noreply.github.com> * Update baselines/powerbi.md Co-authored-by: Addam Schroll <108814318+schrolla@users.noreply.github.com> * Update baselines/powerbi.md Co-authored-by: Addam Schroll <108814318+schrolla@users.noreply.github.com> * Update baselines/aad.md Co-authored-by: Addam Schroll <108814318+schrolla@users.noreply.github.com> * Update aad.md referenced old policy number * Update powerbi.md --------- Co-authored-by: Addam Schroll <108814318+schrolla@users.noreply.github.com> * initial teams drop * Update AAD * WIP * Structural baseline updates (cleaned up) (#334) * Update aad.md all updates * Update defender.md all updates * Update exchange.md all updates * Rename exchange.md to exo.md * Update onedrive.md * Update powerbi.md all updates * Update powerplatform.md all updates * Update sharepoint.md all updates * Update teams.md all updates * Update baselines/defender.md good catch! Co-authored-by: Addam Schroll <108814318+schrolla@users.noreply.github.com> * Update baselines/powerbi.md Co-authored-by: Addam Schroll <108814318+schrolla@users.noreply.github.com> * Update baselines/powerbi.md Co-authored-by: Addam Schroll <108814318+schrolla@users.noreply.github.com> * Update baselines/aad.md Co-authored-by: Addam Schroll <108814318+schrolla@users.noreply.github.com> * Update aad.md referenced old policy number * Update powerbi.md --------- Co-authored-by: Addam Schroll <108814318+schrolla@users.noreply.github.com> * Fix UT errors * Default baseline for testing * Updates based on review comments * Call Import-SecureBaseline once * Update for review comments * Review updates * Add help comment * remove unused import * Fix OPA check issues * fix opa tests action * Update action to test * Action update * Sum PS/Bug as Errors * Update darkmode colors * Fix UT after Rebase * Fix UT * Fix error log * Update UT for NewReport * Update link color --------- Co-authored-by: Andrew Huynh <113476170+ahuynhMITRE@users.noreply.github.com> Co-authored-by: Addam Schroll <108814318+schrolla@users.noreply.github.com> Co-authored-by: Sloane4 --- .github/workflows/run_markdown_check.yaml | 32 + .github/workflows/run_opa_tests.yaml | 4 +- .../Modules/CreateReport/BaselineTitles.json | 86 - .../Modules/CreateReport/CreateReport.psm1 | 207 +- .../Modules/CreateReport/scripts/main.js | 20 +- .../CreateReport/styles/ParentReportStyle.css | 9 +- .../Modules/CreateReport/styles/main.css | 97 +- .../ScubaGear/Modules/Orchestrator.psm1 | 7 +- .../ScubaGear/Modules/RunRego/RunRego.psm1 | 6 +- Rego/AADConfig.rego | 300 +- Rego/DefenderConfig.rego | 373 +- Rego/EXOConfig.rego | 294 +- Rego/OneDriveConfig.rego | 118 +- Rego/PowerPlatformConfig.rego | 134 +- Rego/SharepointConfig.rego | 74 +- Rego/TeamsConfig.rego | 246 +- Rego/Utils/ReportUtils.rego | 62 + .../CreateReportStubs/TestResults.json | 4781 ++++++++--------- .../Import-SecureBaseline.Tests.ps1 | 69 + .../CreateReport/New-MarkdownAnchor.Tests.ps1 | 40 + .../CreateReport/New-Report.Tests.ps1 | 116 +- .../Invoke-ReportCreation.Tests.ps1 | 5 +- ...eTests.ps1 => ScubaConfigDelete.Tests.ps1} | 0 Testing/Unit/Rego/AAD/AADConfig2_05_test.rego | 35 - Testing/Unit/Rego/AAD/AADConfig2_08_test.rego | 19 - ...g2_01_test.rego => AADConfig_01_test.rego} | 156 +- ...g2_02_test.rego => AADConfig_02_test.rego} | 143 +- ...g2_03_test.rego => AADConfig_03_test.rego} | 135 +- ...g2_04_test.rego => AADConfig_04_test.rego} | 154 +- Testing/Unit/Rego/AAD/AADConfig_05_test.rego | 29 + ...g2_06_test.rego => AADConfig_06_test.rego} | 15 +- ...g2_07_test.rego => AADConfig_07_test.rego} | 35 +- Testing/Unit/Rego/AAD/AADConfig_08_test.rego | 18 + ...g2_09_test.rego => AADConfig_09_test.rego} | 125 +- ...g2_10_test.rego => AADConfig_10_test.rego} | 120 +- ...g2_11_test.rego => AADConfig_11_test.rego} | 15 +- ...g2_12_test.rego => AADConfig_12_test.rego} | 19 +- ...g2_13_test.rego => AADConfig_13_test.rego} | 35 +- ...g2_14_test.rego => AADConfig_14_test.rego} | 27 +- ...g2_15_test.rego => AADConfig_15_test.rego} | 10 +- ...g2_16_test.rego => AADConfig_16_test.rego} | 45 +- ...g2_17_test.rego => AADConfig_17_test.rego} | 30 +- ...g2_18_test.rego => AADConfig_18_test.rego} | 51 +- .../Defender/DefenderConfig2_01_test.rego | 119 - .../Defender/DefenderConfig2_02_test.rego | 1028 ---- .../Defender/DefenderConfig2_03_test.rego | 198 - .../Defender/DefenderConfig2_04_test.rego | 70 - .../Defender/DefenderConfig2_05_test.rego | 1377 ----- .../Defender/DefenderConfig2_06_test.rego | 1278 ----- .../Defender/DefenderConfig2_07_test.rego | 1412 ----- .../Defender/DefenderConfig2_08_test.rego | 466 -- .../Defender/DefenderConfig2_09_test.rego | 233 - .../Defender/DefenderConfig2_10_test.rego | 74 - .../Rego/Defender/DefenderConfig_01_test.rego | 113 + .../Rego/Defender/DefenderConfig_02_test.rego | 1031 ++++ .../Rego/Defender/DefenderConfig_03_test.rego | 199 + .../Rego/Defender/DefenderConfig_04_test.rego | 71 + .../Rego/Defender/DefenderConfig_05_test.rego | 1378 +++++ .../Rego/Defender/DefenderConfig_06_test.rego | 1279 +++++ .../Rego/Defender/DefenderConfig_07_test.rego | 1413 +++++ .../Rego/Defender/DefenderConfig_08_test.rego | 467 ++ .../Rego/Defender/DefenderConfig_09_test.rego | 234 + .../Rego/Defender/DefenderConfig_10_test.rego | 70 + Testing/Unit/Rego/EXO/EXOConfig2_09_test.rego | 51 - Testing/Unit/Rego/EXO/EXOConfig2_11_test.rego | 51 - Testing/Unit/Rego/EXO/EXOConfig2_14_test.rego | 51 - ...g2_01_test.rego => EXOConfig_01_test.rego} | 24 +- ...g2_02_test.rego => EXOConfig_02_test.rego} | 49 +- ...g2_03_test.rego => EXOConfig_03_test.rego} | 45 +- ...g2_04_test.rego => EXOConfig_04_test.rego} | 60 +- ...g2_05_test.rego => EXOConfig_05_test.rego} | 10 +- ...g2_06_test.rego => EXOConfig_06_test.rego} | 22 +- ...g2_07_test.rego => EXOConfig_07_test.rego} | 35 +- ...g2_08_test.rego => EXOConfig_08_test.rego} | 11 +- Testing/Unit/Rego/EXO/EXOConfig_09_test.rego | 47 + ...g2_15_test.rego => EXOConfig_10_test.rego} | 15 +- Testing/Unit/Rego/EXO/EXOConfig_11_test.rego | 48 + ...g2_12_test.rego => EXOConfig_12_test.rego} | 30 +- ...g2_13_test.rego => EXOConfig_13_test.rego} | 10 +- Testing/Unit/Rego/EXO/EXOConfig_14_test.rego | 48 + ...g2_17_test.rego => EXOConfig_15_test.rego} | 15 +- ...g2_16_test.rego => EXOConfig_16_test.rego} | 10 +- ...g2_10_test.rego => EXOConfig_17_test.rego} | 15 +- .../OneDrive/OneDriveConfig2_05_test.rego | 44 - .../OneDrive/OneDriveConfig2_06_test.rego | 19 - .../OneDrive/OneDriveConfig2_07_test.rego | 19 - ..._test.rego => OneDriveConfig_01_test.rego} | 19 +- ..._test.rego => OneDriveConfig_02_test.rego} | 40 +- ..._test.rego => OneDriveConfig_03_test.rego} | 44 +- ..._test.rego => OneDriveConfig_04_test.rego} | 25 +- .../Rego/OneDrive/OneDriveConfig_05_test.rego | 42 + .../Rego/OneDrive/OneDriveConfig_06_test.rego | 18 + .../Rego/OneDrive/OneDriveConfig_07_test.rego | 18 + .../PowerPlatformConfig2_01_test.rego | 77 - .../PowerPlatformConfig2_03_test.rego | 60 - .../PowerPlatformConfig2_04_test.rego | 19 - .../PowerPlatformConfig_01_test.rego | 75 + ....rego => PowerPlatformConfig_02_test.rego} | 50 +- .../PowerPlatformConfig_03_test.rego | 57 + .../PowerPlatformConfig_04_test.rego | 18 + .../Sharepoint/SharepointConfig2_03_test.rego | 19 - ...est.rego => SharepointConfig_01_test.rego} | 10 +- ...est.rego => SharepointConfig_02_test.rego} | 17 +- .../Sharepoint/SharepointConfig_03_test.rego | 18 + ...est.rego => SharepointConfig_04_test.rego} | 60 +- ...est.rego => SharepointConfig_05_test.rego} | 4 +- .../Unit/Rego/Teams/TeamsConfig2_11_test.rego | 51 - ..._01_test.rego => TeamsConfig_01_test.rego} | 37 +- ..._02_test.rego => TeamsConfig_02_test.rego} | 27 +- ..._03_test.rego => TeamsConfig_03_test.rego} | 40 +- ..._04_test.rego => TeamsConfig_04_test.rego} | 40 +- ..._05_test.rego => TeamsConfig_05_test.rego} | 60 +- ..._06_test.rego => TeamsConfig_06_test.rego} | 20 +- ..._07_test.rego => TeamsConfig_07_test.rego} | 94 +- ..._08_test.rego => TeamsConfig_08_test.rego} | 83 +- ..._09_test.rego => TeamsConfig_09_test.rego} | 35 +- ..._10_test.rego => TeamsConfig_10_test.rego} | 15 +- ..._13_test.rego => TeamsConfig_11_test.rego} | 15 +- ..._12_test.rego => TeamsConfig_12_test.rego} | 10 +- .../Unit/Rego/Teams/TeamsConfig_13_test.rego | 48 + baselines/aad.md | 2 +- baselines/exo.md | 2 +- baselines/teams.md | 2 +- 123 files changed, 11067 insertions(+), 11739 deletions(-) create mode 100644 .github/workflows/run_markdown_check.yaml delete mode 100644 PowerShell/ScubaGear/Modules/CreateReport/BaselineTitles.json create mode 100644 Rego/Utils/ReportUtils.rego create mode 100644 Testing/Unit/PowerShell/CreateReport/Import-SecureBaseline.Tests.ps1 create mode 100644 Testing/Unit/PowerShell/CreateReport/New-MarkdownAnchor.Tests.ps1 rename Testing/Unit/PowerShell/ScubaConfig/{ScubaConfigDeleteTests.ps1 => ScubaConfigDelete.Tests.ps1} (100%) delete mode 100644 Testing/Unit/Rego/AAD/AADConfig2_05_test.rego delete mode 100644 Testing/Unit/Rego/AAD/AADConfig2_08_test.rego rename Testing/Unit/Rego/AAD/{AADConfig2_01_test.rego => AADConfig_01_test.rego} (86%) rename Testing/Unit/Rego/AAD/{AADConfig2_02_test.rego => AADConfig_02_test.rego} (86%) rename Testing/Unit/Rego/AAD/{AADConfig2_03_test.rego => AADConfig_03_test.rego} (87%) rename Testing/Unit/Rego/AAD/{AADConfig2_04_test.rego => AADConfig_04_test.rego} (82%) create mode 100644 Testing/Unit/Rego/AAD/AADConfig_05_test.rego rename Testing/Unit/Rego/AAD/{AADConfig2_06_test.rego => AADConfig_06_test.rego} (73%) rename Testing/Unit/Rego/AAD/{AADConfig2_07_test.rego => AADConfig_07_test.rego} (68%) create mode 100644 Testing/Unit/Rego/AAD/AADConfig_08_test.rego rename Testing/Unit/Rego/AAD/{AADConfig2_09_test.rego => AADConfig_09_test.rego} (84%) rename Testing/Unit/Rego/AAD/{AADConfig2_10_test.rego => AADConfig_10_test.rego} (85%) rename Testing/Unit/Rego/AAD/{AADConfig2_11_test.rego => AADConfig_11_test.rego} (71%) rename Testing/Unit/Rego/AAD/{AADConfig2_12_test.rego => AADConfig_12_test.rego} (63%) rename Testing/Unit/Rego/AAD/{AADConfig2_13_test.rego => AADConfig_13_test.rego} (83%) rename Testing/Unit/Rego/AAD/{AADConfig2_14_test.rego => AADConfig_14_test.rego} (77%) rename Testing/Unit/Rego/AAD/{AADConfig2_15_test.rego => AADConfig_15_test.rego} (82%) rename Testing/Unit/Rego/AAD/{AADConfig2_16_test.rego => AADConfig_16_test.rego} (83%) rename Testing/Unit/Rego/AAD/{AADConfig2_17_test.rego => AADConfig_17_test.rego} (79%) rename Testing/Unit/Rego/AAD/{AADConfig2_18_test.rego => AADConfig_18_test.rego} (56%) delete mode 100644 Testing/Unit/Rego/Defender/DefenderConfig2_01_test.rego delete mode 100644 Testing/Unit/Rego/Defender/DefenderConfig2_02_test.rego delete mode 100644 Testing/Unit/Rego/Defender/DefenderConfig2_03_test.rego delete mode 100644 Testing/Unit/Rego/Defender/DefenderConfig2_04_test.rego delete mode 100644 Testing/Unit/Rego/Defender/DefenderConfig2_05_test.rego delete mode 100644 Testing/Unit/Rego/Defender/DefenderConfig2_06_test.rego delete mode 100644 Testing/Unit/Rego/Defender/DefenderConfig2_07_test.rego delete mode 100644 Testing/Unit/Rego/Defender/DefenderConfig2_08_test.rego delete mode 100644 Testing/Unit/Rego/Defender/DefenderConfig2_09_test.rego delete mode 100644 Testing/Unit/Rego/Defender/DefenderConfig2_10_test.rego create mode 100644 Testing/Unit/Rego/Defender/DefenderConfig_01_test.rego create mode 100644 Testing/Unit/Rego/Defender/DefenderConfig_02_test.rego create mode 100644 Testing/Unit/Rego/Defender/DefenderConfig_03_test.rego create mode 100644 Testing/Unit/Rego/Defender/DefenderConfig_04_test.rego create mode 100644 Testing/Unit/Rego/Defender/DefenderConfig_05_test.rego create mode 100644 Testing/Unit/Rego/Defender/DefenderConfig_06_test.rego create mode 100644 Testing/Unit/Rego/Defender/DefenderConfig_07_test.rego create mode 100644 Testing/Unit/Rego/Defender/DefenderConfig_08_test.rego create mode 100644 Testing/Unit/Rego/Defender/DefenderConfig_09_test.rego create mode 100644 Testing/Unit/Rego/Defender/DefenderConfig_10_test.rego delete mode 100644 Testing/Unit/Rego/EXO/EXOConfig2_09_test.rego delete mode 100644 Testing/Unit/Rego/EXO/EXOConfig2_11_test.rego delete mode 100644 Testing/Unit/Rego/EXO/EXOConfig2_14_test.rego rename Testing/Unit/Rego/EXO/{EXOConfig2_01_test.rego => EXOConfig_01_test.rego} (65%) rename Testing/Unit/Rego/EXO/{EXOConfig2_02_test.rego => EXOConfig_02_test.rego} (60%) rename Testing/Unit/Rego/EXO/{EXOConfig2_03_test.rego => EXOConfig_03_test.rego} (79%) rename Testing/Unit/Rego/EXO/{EXOConfig2_04_test.rego => EXOConfig_04_test.rego} (71%) rename Testing/Unit/Rego/EXO/{EXOConfig2_05_test.rego => EXOConfig_05_test.rego} (65%) rename Testing/Unit/Rego/EXO/{EXOConfig2_06_test.rego => EXOConfig_06_test.rego} (65%) rename Testing/Unit/Rego/EXO/{EXOConfig2_07_test.rego => EXOConfig_07_test.rego} (74%) rename Testing/Unit/Rego/EXO/{EXOConfig2_08_test.rego => EXOConfig_08_test.rego} (51%) create mode 100644 Testing/Unit/Rego/EXO/EXOConfig_09_test.rego rename Testing/Unit/Rego/EXO/{EXOConfig2_15_test.rego => EXOConfig_10_test.rego} (63%) create mode 100644 Testing/Unit/Rego/EXO/EXOConfig_11_test.rego rename Testing/Unit/Rego/EXO/{EXOConfig2_12_test.rego => EXOConfig_12_test.rego} (66%) rename Testing/Unit/Rego/EXO/{EXOConfig2_13_test.rego => EXOConfig_13_test.rego} (66%) create mode 100644 Testing/Unit/Rego/EXO/EXOConfig_14_test.rego rename Testing/Unit/Rego/EXO/{EXOConfig2_17_test.rego => EXOConfig_15_test.rego} (63%) rename Testing/Unit/Rego/EXO/{EXOConfig2_16_test.rego => EXOConfig_16_test.rego} (59%) rename Testing/Unit/Rego/EXO/{EXOConfig2_10_test.rego => EXOConfig_17_test.rego} (62%) delete mode 100644 Testing/Unit/Rego/OneDrive/OneDriveConfig2_05_test.rego delete mode 100644 Testing/Unit/Rego/OneDrive/OneDriveConfig2_06_test.rego delete mode 100644 Testing/Unit/Rego/OneDrive/OneDriveConfig2_07_test.rego rename Testing/Unit/Rego/OneDrive/{OneDriveConfig2_01_test.rego => OneDriveConfig_01_test.rego} (56%) rename Testing/Unit/Rego/OneDrive/{OneDriveConfig2_02_test.rego => OneDriveConfig_02_test.rego} (58%) rename Testing/Unit/Rego/OneDrive/{OneDriveConfig2_03_test.rego => OneDriveConfig_03_test.rego} (60%) rename Testing/Unit/Rego/OneDrive/{OneDriveConfig2_04_test.rego => OneDriveConfig_04_test.rego} (54%) create mode 100644 Testing/Unit/Rego/OneDrive/OneDriveConfig_05_test.rego create mode 100644 Testing/Unit/Rego/OneDrive/OneDriveConfig_06_test.rego create mode 100644 Testing/Unit/Rego/OneDrive/OneDriveConfig_07_test.rego delete mode 100644 Testing/Unit/Rego/PowerPlatform/PowerPlatformConfig2_01_test.rego delete mode 100644 Testing/Unit/Rego/PowerPlatform/PowerPlatformConfig2_03_test.rego delete mode 100644 Testing/Unit/Rego/PowerPlatform/PowerPlatformConfig2_04_test.rego create mode 100644 Testing/Unit/Rego/PowerPlatform/PowerPlatformConfig_01_test.rego rename Testing/Unit/Rego/PowerPlatform/{PowerPlatformConfig2_02_test.rego => PowerPlatformConfig_02_test.rego} (67%) create mode 100644 Testing/Unit/Rego/PowerPlatform/PowerPlatformConfig_03_test.rego create mode 100644 Testing/Unit/Rego/PowerPlatform/PowerPlatformConfig_04_test.rego delete mode 100644 Testing/Unit/Rego/Sharepoint/SharepointConfig2_03_test.rego rename Testing/Unit/Rego/Sharepoint/{SharepointConfig2_01_test.rego => SharepointConfig_01_test.rego} (53%) rename Testing/Unit/Rego/Sharepoint/{SharepointConfig2_02_test.rego => SharepointConfig_02_test.rego} (53%) create mode 100644 Testing/Unit/Rego/Sharepoint/SharepointConfig_03_test.rego rename Testing/Unit/Rego/Sharepoint/{SharepointConfig2_04_test.rego => SharepointConfig_04_test.rego} (81%) rename Testing/Unit/Rego/Sharepoint/{SharepointConfig2_05_test.rego => SharepointConfig_05_test.rego} (90%) delete mode 100644 Testing/Unit/Rego/Teams/TeamsConfig2_11_test.rego rename Testing/Unit/Rego/Teams/{TeamsConfig2_01_test.rego => TeamsConfig_01_test.rego} (56%) rename Testing/Unit/Rego/Teams/{TeamsConfig2_02_test.rego => TeamsConfig_02_test.rego} (63%) rename Testing/Unit/Rego/Teams/{TeamsConfig2_03_test.rego => TeamsConfig_03_test.rego} (65%) rename Testing/Unit/Rego/Teams/{TeamsConfig2_04_test.rego => TeamsConfig_04_test.rego} (82%) rename Testing/Unit/Rego/Teams/{TeamsConfig2_05_test.rego => TeamsConfig_05_test.rego} (69%) rename Testing/Unit/Rego/Teams/{TeamsConfig2_06_test.rego => TeamsConfig_06_test.rego} (68%) rename Testing/Unit/Rego/Teams/{TeamsConfig2_07_test.rego => TeamsConfig_07_test.rego} (73%) rename Testing/Unit/Rego/Teams/{TeamsConfig2_08_test.rego => TeamsConfig_08_test.rego} (62%) rename Testing/Unit/Rego/Teams/{TeamsConfig2_09_test.rego => TeamsConfig_09_test.rego} (64%) rename Testing/Unit/Rego/Teams/{TeamsConfig2_10_test.rego => TeamsConfig_10_test.rego} (66%) rename Testing/Unit/Rego/Teams/{TeamsConfig2_13_test.rego => TeamsConfig_11_test.rego} (63%) rename Testing/Unit/Rego/Teams/{TeamsConfig2_12_test.rego => TeamsConfig_12_test.rego} (61%) create mode 100644 Testing/Unit/Rego/Teams/TeamsConfig_13_test.rego diff --git a/.github/workflows/run_markdown_check.yaml b/.github/workflows/run_markdown_check.yaml new file mode 100644 index 0000000000..2870b90b11 --- /dev/null +++ b/.github/workflows/run_markdown_check.yaml @@ -0,0 +1,32 @@ +on: + workflow_dispatch: + pull_request: + types: [opened, reopened] + branches: + - "main" + pull_request_review: + types: [submitted] + push: + branches: + - "main" + - "*Baseline*" + paths: + - "baselines/*.md" + +name: Markdown Check + +jobs: + Run-Markdown-Check: + runs-on: windows-latest + defaults: + run: + shell: powershell + permissions: + contents: read + steps: + - name: Checkout repo code + uses: actions/checkout@v3 + - name: Execute markdown checks + run: | + $PSVersionTable + Invoke-Pester Testing\Unit\Pester\CreateReport -Output Detailed \ No newline at end of file diff --git a/.github/workflows/run_opa_tests.yaml b/.github/workflows/run_opa_tests.yaml index 77365ca28e..f35b83dd6e 100644 --- a/.github/workflows/run_opa_tests.yaml +++ b/.github/workflows/run_opa_tests.yaml @@ -6,10 +6,12 @@ on: push: paths: - "**.rego" + - "**/run_opa_tests.yaml" pull_request: types: [opened, reopened] branches: - "main" + - "emerald" #TODO: Remove after emerald release paths: - "**.rego" pull_request_review: @@ -31,4 +33,4 @@ jobs: run: opa check Rego Testing/Unit/Rego --strict - name: Run OPA Tests - run: opa test Rego/*.rego Testing/Unit/Rego/**/*.rego -v + run: opa test Rego/*.rego Rego/Utils/*.rego Testing/Unit/Rego/**/*.rego -v diff --git a/PowerShell/ScubaGear/Modules/CreateReport/BaselineTitles.json b/PowerShell/ScubaGear/Modules/CreateReport/BaselineTitles.json deleted file mode 100644 index 27da48990b..0000000000 --- a/PowerShell/ScubaGear/Modules/CreateReport/BaselineTitles.json +++ /dev/null @@ -1,86 +0,0 @@ -{ - "Teams": [ - {"Number": "Teams 2.1", "Title": "External Participants SHOULD NOT Be Enabled to Request Control of Shared Desktops or Windows in Meetings"}, - {"Number": "Teams 2.2", "Title": "Anonymous Users SHALL NOT Be Enabled to Start Meetings"}, - {"Number": "Teams 2.3", "Title": "Automatic Admittance to Meetings SHOULD Be Restricted"}, - {"Number": "Teams 2.4", "Title": "External User Access SHALL Be Restricted"}, - {"Number": "Teams 2.5", "Title": "Unmanaged User Access SHALL Be Restricted"}, - {"Number": "Teams 2.6", "Title": "Contact with Skype Users SHALL Be Blocked"}, - {"Number": "Teams 2.7", "Title": "Teams Email Integration SHALL Be Disabled"}, - {"Number": "Teams 2.8", "Title": "Only Approved Apps SHOULD Be Installed"}, - {"Number": "Teams 2.9", "Title": "Cloud Recording of Teams Meetings SHOULD Be Disabled for Unapproved Users"}, - {"Number": "Teams 2.10", "Title": "Only the Meeting Organizer SHOULD Be Able to Record Live Events"}, - {"Number": "Teams 2.11", "Title": "Data Loss Prevention Solutions SHALL Be Enabled"}, - {"Number": "Teams 2.12", "Title": "Attachments SHOULD Be Scanned for Malware"}, - {"Number": "Teams 2.13", "Title": "Link Protection SHOULD Be Enabled"}], - "EXO": [ - {"Number": "EXO 2.1", "Title": "Automatic Forwarding to External Domains SHALL Be Disabled"}, - {"Number": "EXO 2.2", "Title": "Sender Policy Framework SHALL Be Enabled"}, - {"Number": "EXO 2.3", "Title": "DomainKeys Identified Mail SHOULD Be Enabled"}, - {"Number": "EXO 2.4", "Title": "Domain-based Message Authentication, Reporting, and Conformance SHALL Be Enabled"}, - {"Number": "EXO 2.5", "Title": "Simple Mail Transfer Protocol Authentication SHALL Be Disabled"}, - {"Number": "EXO 2.6", "Title": "Calendar and Contact Sharing SHALL Be Restricted"}, - {"Number": "EXO 2.7", "Title": "External Sender Warnings SHALL Be Implemented"}, - {"Number": "EXO 2.8", "Title": "Data Loss Prevention Solutions SHALL Be Enabled"}, - {"Number": "EXO 2.9", "Title": "Emails SHALL Be Filtered by Attachment File Type"}, - {"Number": "EXO 2.10", "Title": "Emails SHALL Be Scanned for Malware"}, - {"Number": "EXO 2.11", "Title":"Phishing Protections SHOULD Be Enabled"}, - {"Number": "EXO 2.12", "Title": "IP Allow Lists SHOULD NOT be Implemented"}, - {"Number": "EXO 2.13", "Title": "Mailbox Auditing SHALL Be Enabled"}, - {"Number": "EXO 2.14", "Title": "Inbound Anti-Spam Protections SHALL Be Enabled"}, - {"Number": "EXO 2.15", "Title": "Link Protection SHOULD Be Enabled"}, - {"Number": "EXO 2.16", "Title": "Alerts SHALL Be Enabled"}, - {"Number": "EXO 2.17", "Title": "Audit Logging SHALL Be Enabled"}], - "Defender": [ - {"Number" : "Defender 2.1", "Title" : "Preset Security Profiles SHOULD NOT Be Used"}, - {"Number" : "Defender 2.2", "Title" : "Data Loss Prevention SHALL Be Enabled"}, - {"Number" : "Defender 2.3", "Title" : "Common Attachments Filter SHALL Be Enabled"}, - {"Number" : "Defender 2.4", "Title" : "Zero-hour Auto Purge for Malware SHOULD Be Enabled"}, - {"Number" : "Defender 2.5", "Title" : "Phishing Protections SHOULD Be Enabled"}, - {"Number" : "Defender 2.6", "Title" : "Inbound Anti-Spam Protections SHALL Be Enabled"}, - {"Number" : "Defender 2.7", "Title" : "Safe Link Policies SHOULD Be Enabled"}, - {"Number" : "Defender 2.8", "Title" : "Safe-Attachments SHALL Be Enabled"}, - {"Number" : "Defender 2.9", "Title" : "Alerts SHALL Be Enabled"}, - {"Number" : "Defender 2.10", "Title" : "Audit Logging SHALL Be Enabled"}], - "AAD": [ - {"Number" : "AAD 2.1", "Title" : "Legacy Authentication SHALL be Blocked" }, - {"Number" : "AAD 2.2", "Title" : "High Risk Users SHALL be Blocked"}, - {"Number" : "AAD 2.3", "Title" : "High Risk Sign-ins SHALL be Blocked"}, - {"Number" : "AAD 2.4", "Title" : "Phishing-Resistant Multifactor Authentication SHALL be required for all users"}, - {"Number" : "AAD 2.5", "Title": "Azure AD logs SHALL be collected"}, - {"Number" : "AAD 2.6", "Title": "Only administrators SHALL be allowed to register third-party applications"}, - {"Number" : "AAD 2.7", "Title": "Non-admin users SHALL be prevented from providing consent to third-party applications"}, - {"Number" : "AAD 2.8", "Title": "Passwords SHALL NOT expire"}, - {"Number" : "AAD 2.9", "Title": "Session Length SHALL be Limited"}, - {"Number" : "AAD 2.10", "Title": "Browser Sessions SHALL NOT be Persistent"}, - {"Number" : "AAD 2.11", "Title": "The Number of Users with the Highest Privilege Roles SHALL be limited"}, - {"Number" : "AAD 2.12", "Title": "Highly Privileged User Accounts SHALL be Cloud-Only"}, - {"Number" : "AAD 2.13", "Title": "Multifactor Authentication SHALL be required for Highly Privileged Roles"}, - {"Number" : "AAD 2.14", "Title": "Users Assigned to Highly Privileged Roles SHALL NOT Have Permanent Permissions"}, - {"Number" : "AAD 2.15", "Title": "Activation of Highly Privileged Roles SHOULD Require Approval"}, - {"Number" : "AAD 2.16", "Title": "Highly Privileged Role Assignment and Activation SHALL be Monitored"}, - {"Number" : "AAD 2.17", "Title": "Managed Devices SHOULD be Required for Authentication"}, - {"Number" : "AAD 2.18", "Title": "Guest User Access SHOULD be Restricted"} - ], - "PowerPlatform": [ - {"Number" : "Power Platform 2.1", "Title" : "Creation of Power Platform Environments SHALL be restricted"}, - {"Number" : "Power Platform 2.2", "Title" : "Data Loss Prevention Policy for Power Platform environments SHALL be created"}, - {"Number" : "Power Platform 2.3", "Title" : "Tenant isolation SHALL be enabled to prevent cross tenant access of Power Platform environments"}, - {"Number" : "Power Platform 2.4", "Title" : "Content Security Policy SHALL be Enabled"}], - "OneDrive": [ - {"Number" : "OneDrive 2.1", "Title" : "Anyone Links SHOULD Be Turned Off"}, - {"Number" : "OneDrive 2.2", "Title" : "Expiration Date SHOULD Be Set for Anyone Links"}, - {"Number" : "OneDrive 2.3", "Title" : "Link Permissions SHOULD Be Set to Enabled Anyone Links to View"}, - {"Number" : "OneDrive 2.4", "Title" : "OneDrive Client SHALL be restricted to Windows for Agency-Defined Domain(s)"}, - {"Number" : "OneDrive 2.5", "Title" : "OneDrive Client SHALL be restricted to Sync with Mac for Agency-Defined Devices"}, - {"Number" : "OneDrive 2.6", "Title" : "OneDrive Client Sync SHALL Only Be Allowed Within the Local Domain"}, - {"Number" : "OneDrive 2.7", "Title" : "Legacy Authentication SHALL Be Blocked"} - ], - "SharePoint": [ - {"Number" : "SharePoint 2.1", "Title" : "File and folder links default sharing settings SHALL be set to \"Specific People (only the people the user specifies)\""}, - {"Number" : "SharePoint 2.2", "Title" : "External sharing SHOULD be set to \"New and Existing Guests\" and managed through approved domains and/or security groups per interagency collaboration needs"}, - {"Number" : "SharePoint 2.3", "Title" : "Sensitive SharePoint sites SHOULD adjust their default sharing settings to those best aligning to their sensitivity level"}, - {"Number" : "SharePoint 2.4", "Title" : "Expiration times for guest access to a site or OneDrive, and reauthentication expiration times for people who use a verification code, SHOULD be determined by mission needs / Agency policy or else defaulted to 30 days"}, - {"Number" : "SharePoint 2.5", "Title" : "Users SHALL be prevented from running custom scripts"} - ] -} diff --git a/PowerShell/ScubaGear/Modules/CreateReport/CreateReport.psm1 b/PowerShell/ScubaGear/Modules/CreateReport/CreateReport.psm1 index 7e41b366f8..d65b4dd815 100644 --- a/PowerShell/ScubaGear/Modules/CreateReport/CreateReport.psm1 +++ b/PowerShell/ScubaGear/Modules/CreateReport/CreateReport.psm1 @@ -48,12 +48,17 @@ function New-Report { [Parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] [switch] - $DarkMode + $DarkMode, + + [Parameter(Mandatory=$true)] + [ValidateNotNull()] + [object] + $SecureBaselines ) - $FileName = Join-Path -Path $PSScriptRoot -ChildPath "BaselineTitles.json" - $AllTitles = Get-Content $FileName | ConvertFrom-Json - $Titles = $AllTitles.$BaselineName + $ScubaGitHubUrl = "https://github.com/cisagov/ScubaGear" + + $ProductSecureBaseline = $SecureBaselines.$BaselineName $FileName = Join-Path -Path $OutPath -ChildPath "$($OutProviderFileName).json" $SettingsExport = Get-Content $FileName | ConvertFrom-Json @@ -82,52 +87,72 @@ function New-Report { "Date" = $SettingsExport.date; } - foreach ($Title in $Titles) { + foreach ($BaselineGroup in $ProductSecureBaseline) { $Fragment = @() - foreach ($test in $TestResults | Where-Object -Property Control -eq $Title.Number) { - $MissingCommands = @() - - if ($SettingsExport."$($BaselineName)_successful_commands" -or $SettingsExport."$($BaselineName)_unsuccessful_commands") { - # If neither of these keys are present, it means the provider for that baseline - # hasn't been updated to the updated error handling method. This check - # here ensures backwards compatibility until all providers are udpated. - $MissingCommands = $test.Commandlet | Where-Object {$SettingsExport."$($BaselineName)_successful_commands" -notcontains $_} - } - if ($MissingCommands.Count -gt 0) { - $Result = "Error" - $ReportSummary.Errors += 1 - $MissingString = $MissingCommands -Join ", " - $test.ReportDetails = "This test depends on the following command(s) which did not execute successfully: $($MissingString). See terminal output for more details." - } - elseif ($test.RequirementMet) { - $Result = "Pass" - $ReportSummary.Passes += 1 - } - elseif ($test.Criticality -eq "Should") { - $Result = "Warning" - $ReportSummary.Warnings += 1 - } - elseif ($test.Criticality.EndsWith('3rd Party') -or $test.Criticality.EndsWith('Not-Implemented')) { - $Result = "N/A" - $ReportSummary.Manual += 1 + foreach ($Control in $BaselineGroup.Controls){ + + $Test = $TestResults | Where-Object -Property PolicyId -eq $Control.Id + + if ($null -ne $Test){ + $MissingCommands = @() + + if ($SettingsExport."$($BaselineName)_successful_commands" -or $SettingsExport."$($BaselineName)_unsuccessful_commands") { + # If neither of these keys are present, it means the provider for that baseline + # hasn't been updated to the updated error handling method. This check + # here ensures backwards compatibility until all providers are udpated. + $MissingCommands = $Test.Commandlet | Where-Object {$SettingsExport."$($BaselineName)_successful_commands" -notcontains $_} + } + + if ($MissingCommands.Count -gt 0) { + $Result = "Error" + $ReportSummary.Errors += 1 + $MissingString = $MissingCommands -Join ", " + $Test.ReportDetails = "This test depends on the following command(s) which did not execute successfully: $($MissingString). See terminal output for more details." + } + elseif ($Test.RequirementMet) { + $Result = "Pass" + $ReportSummary.Passes += 1 + } + elseif ($Test.Criticality -eq "Should") { + $Result = "Warning" + $ReportSummary.Warnings += 1 + } + elseif ($Test.Criticality.EndsWith('3rd Party') -or $test.Criticality.EndsWith('Not-Implemented')) { + $Result = "N/A" + $ReportSummary.Manual += 1 + } + else { + $Result = "Fail" + $ReportSummary.Failures += 1 + } + + $Fragment += [pscustomobject]@{ + "Control ID"=$Control.Id + "Requirement"=$Control.Value + "Result"= if ($Control.Deleted) {"-"} else {$Result} + "Criticality"=if ($Control.Deleted) {"-"} else {$Test.Criticality} + "Details"=if ($Control.Deleted) {"-"} else {$Test.ReportDetails} + } } else { - $Result = "Fail" - $ReportSummary.Failures += 1 + $ReportSummary.Errors += 1 + $Fragment += [pscustomobject]@{ + "Control ID"=$Control.Id + "Requirement"=$Control.Value + "Result"= "Error - Test results missing" + "Criticality"= "-" + "Details"= "Report issue on GitHub" + } + Write-Error("ERROR: No test results found for Control Id $($Control.Id)") } - - $Fragment += [pscustomobject]@{ - "Requirement"=$test.Requirement; - "Result"=$Result; - "Criticality"=$test.Criticality; - "Details"=$test.ReportDetails} } - $Number = $Title.Number - $Name = $Title.Title - $Fragments += $Fragment | ConvertTo-Html -PreContent "

$Number $Name

" -Fragment - + $Number = $BaselineName.ToUpper() + '-' + $BaselineGroup.GroupNumber + $Name = $BaselineGroup.GroupName + $GroupAnchor = New-MarkdownAnchor -GroupNumber $BaselineGroup.GroupNumber -GroupName $BaselineGroup.GroupName + $MarkdownLink = "$Name" + $Fragments += $Fragment | ConvertTo-Html -PreContent "

$Number $MarkdownLink

" -Fragment } $Title = "$($FullName) Baseline Report" @@ -177,6 +202,100 @@ function New-Report { $ReportSummary } +function Import-SecureBaseline{ + <# + .Description + This function parses the secure baseline via each product markdown document to align policy with the + software baseline. + .Functionality + Internal + #> + [CmdletBinding()] + param ( + [Parameter(Mandatory = $false)] + [ValidateScript({Test-Path -PathType Container $_})] + [string] + $BaselinePath = (Join-Path -Path $PSScriptRoot -ChildPath "..\..\..\..\baselines\") + ) + + $ProductNames = Get-ChildItem $BaselinePath -Filter "*.md" | ForEach-Object {$_.Name.SubString(0, $_.Name.Length - 3)} + $Output = @{} + + foreach ($Product in $ProductNames) { + $Output[$Product] = @() + $ProductPath = Join-Path -Path $BaselinePath -ChildPath "$Product.md" + $MdLines = Get-Content -Path $ProductPath + + # Select-String line numbers aren't 0-indexed, hence the "-1" on the next line + $LineNumbers = Select-String "^## [0-9]+\." "$($BaselinePath)$($Product).md" | ForEach-Object {$_."LineNumber"-1} + $Groups = $LineNumbers | ForEach-Object {$MdLines[$_]} + + foreach ($GroupName in $Groups) { + $Group = @{} + $Group.GroupNumber = $GroupName.Split(".")[0].SubString(3) # 3 to remove the "## " + $Group.GroupName = $GroupName.Split(".")[1].Trim() # 1 to remove the leading space + $Group.Controls = @() + + $IdRegex = "#### MS\.[$($Product.ToUpper())]+\.$($Group.GroupNumber)\." + # Select-String line numbers aren't 0-indexed, hence the "-1" on the next line + $LineNumbers = Select-String $IdRegex "$($BaselinePath)$($Product).md" | ForEach-Object {$_."LineNumber"-1} + + foreach ($LineNumber in $LineNumbers) { + # This assumes that the value is on the immediate next line after the ID and ends in a period. + $LineAdvance = 1; + $Value = ([string]$MdLines[$LineNumber+$LineAdvance]).Trim() + + while ($Value.Substring($Value.Length-1,1) -ne "."){ + $LineAdvance++ + $Value += ' ' + ([string]$MdLines[$LineNumber+$LineAdvance]).Trim() + } + + $Value = [System.Net.WebUtility]::HtmlEncode($Value) + $Id = [string]$MdLines[$LineNumber].Substring(5) + + if ($Id.EndsWith("X")){ + $Deleted = $true + $Id = $Id -Replace ".$" + $Value = "[DELETED] " + $Value + } + else { + $Deleted = $false + } + + $Group.Controls += @{"Id"=$Id; "Value"=$Value; "Deleted"=$Deleted} + } + + $Output[$Product] += $Group + } + } + + $Output +} + +function New-MarkdownAnchor{ + param ( + [Parameter(Mandatory = $true)] + [ValidateNotNullOrEmpty()] + [string] + $GroupNumber, + [Parameter(Mandatory = $true)] + [ValidateNotNullOrEmpty()] + [string] + $GroupName + ) + [Int32]$OutNumber = $null + + if ($true -eq [Int32]::TryParse($GroupNumber, [ref]$OutNumber)){ + $MangledName = $GroupName.ToLower().Trim().Replace(' ', '-') + return "#$($GroupNumber.Trim())-$MangledName" + } + else { + $InvalidGroupNumber = New-Object System.ArgumentException "$GroupNumber is not valid" + throw $InvalidGroupNumber + } +} + Export-ModuleMember -Function @( - 'New-Report' + 'New-Report', + 'Import-SecureBaseline' ) diff --git a/PowerShell/ScubaGear/Modules/CreateReport/scripts/main.js b/PowerShell/ScubaGear/Modules/CreateReport/scripts/main.js index f0b4929910..546012becc 100644 --- a/PowerShell/ScubaGear/Modules/CreateReport/scripts/main.js +++ b/PowerShell/ScubaGear/Modules/CreateReport/scripts/main.js @@ -3,11 +3,19 @@ */ const colorRows = () => { let rows = document.querySelectorAll('tr'); - const statusCol = 1; - const criticalityCol = 2; + const requirementCol = 1; + const statusCol = 2; + const criticalityCol = 3; for (let i = 0; i < rows.length; i++) { try { - if (rows[i].children[statusCol].innerHTML === "Fail") { + if (rows[i].children[requirementCol].innerHTML.startsWith("[DELETED]")) { + rows[i].style.color = "var(--test-deleted-color)"; + rows[i].style.background = "var(--test-other)"; + } + else if (rows[i].children[statusCol].innerHTML.startsWith("Bug")){ + rows[i].style.background = "var(--test-bug-color)"; + } + else if (rows[i].children[statusCol].innerHTML === "Fail") { rows[i].style.background = "var(--test-fail)"; } else if (rows[i].children[statusCol].innerHTML === "Warning") { @@ -24,8 +32,8 @@ const colorRows = () => { } else if (rows[i].children[statusCol].innerHTML.includes("Error")) { rows[i].style.background = "var(--test-fail)"; - rows[i].querySelectorAll('td')[1].style.borderColor = "var(--border-color)"; - rows[i].querySelectorAll('td')[1].style.color = "#d10000"; + rows[i].querySelectorAll('td')[statusCol].style.borderColor = "var(--border-color)"; + rows[i].querySelectorAll('td')[statusCol].style.color = "var(--test-error-color)"; } } catch (error) { @@ -103,7 +111,7 @@ const fillCAPTable = () => { } else if (capColNames[i] === "Conditions") { th.setAttribute("class", "conditions"); - } + } th.innerHTML = capColNames[i]; header.appendChild(th); } diff --git a/PowerShell/ScubaGear/Modules/CreateReport/styles/ParentReportStyle.css b/PowerShell/ScubaGear/Modules/CreateReport/styles/ParentReportStyle.css index 3b88cc0f57..b99033f775 100644 --- a/PowerShell/ScubaGear/Modules/CreateReport/styles/ParentReportStyle.css +++ b/PowerShell/ScubaGear/Modules/CreateReport/styles/ParentReportStyle.css @@ -20,7 +20,7 @@ footer { a.individual_reports:link { font-family: Arial, Helvetica, sans-serif; - color: var(--header-color); + color: var(--unvisited-link-color); text-decoration: underline; } @@ -39,7 +39,7 @@ a.individual_reports:active { font-family: Arial, Helvetica, sans-serif; color: var(--link-color); text-decoration: none; -} +} table.tenantdata tr:first-child { color: var(--text-color); @@ -49,8 +49,7 @@ table.tenantdata tr:first-child { .warning { background-color: var(--test-warning); } .pass { background-color: var(--test-pass); } .manual { background-color: var(--test-other); } - .error { - background-color: var(--test-fail); - color: #d10000; + background-color: var(--test-fail); + color: var(--test-error-color); } \ No newline at end of file diff --git a/PowerShell/ScubaGear/Modules/CreateReport/styles/main.css b/PowerShell/ScubaGear/Modules/CreateReport/styles/main.css index c1a96e7fe3..d07c52bb6c 100644 --- a/PowerShell/ScubaGear/Modules/CreateReport/styles/main.css +++ b/PowerShell/ScubaGear/Modules/CreateReport/styles/main.css @@ -2,15 +2,20 @@ --background-primary: white; --background-secondary: #b9bec2; --test-pass: #d5ebd5; - --test-fail: #deb8b8; + --test-fail: #E5C7C7; --test-warning: #fff7d6; --test-other: #ebebf2; + --test-deleted-bg: #b2beb5; + --test-deleted-color: #6f7478; + --test-bug-color: #e80b0b; + --test-error-color: #DD4803; --cap-even: #0052882d; --cap-hover: #00528850; --header-color: #005288; --note-color: #ee4e04; --header-bottom: black; --link-color: #85B065; + --unvisited-link-color: #0092CC; --text-color: black; --border-color: black; --toggle-height: 25px; @@ -19,21 +24,22 @@ } html[data-theme='dark'] { - --background-primary: #1f1b24; + --background-primary: #10171D; --background-secondary: #121212; - --test-pass: #1d3b1d; - --test-fail: #501414; - --test-warning: #5a3b00; + --test-pass: #1C361C; + --test-fail: #381919; + --test-warning: #524100; --test-other: #414141; --cap-even: #0052882d; --cap-hover: #007ccf50; + --test-error-color: #FD885D; --header-color: #b7c8d2; --note-color: #ee4e04; --header-bottom: rgb(221, 221, 221); --link-color: #85B065; + --unvisited-link-color: #0092CC; --text-color: #bdbdbd; --border-color: #7b7b7b; - } body { @@ -45,7 +51,7 @@ body { table { margin: auto; - font-size: 12px; + font-size: 13px; font-family: Arial, Helvetica, sans-serif; border-collapse: collapse; width: 1000px; @@ -232,17 +238,17 @@ th.conditions { width: var(--toggle-width); height: var(--toggle-height); left: 50px; - } - - /* Hide default HTML checkbox */ - .switch input { +} + +/* Hide default HTML checkbox */ +.switch input { opacity: 0; width: 0; height: 0; - } - - /* The slider */ - .slider { +} + +/* The slider */ +.slider { position: absolute; cursor: pointer; top: 0; @@ -252,9 +258,9 @@ th.conditions { background-color: #b9bec2; -webkit-transition: .4s; transition: .4s; - } - - .slider:before { +} + +.slider:before { position: absolute; content: ""; height: var(--toggle-radius); @@ -264,26 +270,49 @@ th.conditions { background-color: white; -webkit-transition: .4s; transition: .4s; - } - - input:checked + .slider { +} + +input:checked + .slider { background-color: #005288ad; - } - - input:focus + .slider { +} + +input:focus + .slider { box-shadow: 0 0 1px #005288ad; - } - - input:checked + .slider:before { +} + +input:checked + .slider:before { -webkit-transform: translateX(var(--toggle-radius)); -ms-transform: translateX(var(--toggle-radius)); transform: translateX(var(--toggle-radius)); - } - - .slider.round { +} + +.slider.round { border-radius: var(--toggle-height); - } - - .slider.round:before { +} + +.slider.round:before { border-radius: 50%; - } \ No newline at end of file +} + +a.control_group:link { + font-family: Arial, Helvetica, sans-serif; + color: var(--unvisited-link-color); + text-decoration: underline; +} + +a.control_group:visited { + font-family: Arial, Helvetica, sans-serif; + color: var(--link-color); +} + +a.control_group:hover { + font-family: Arial, Helvetica, sans-serif; + color: var(--link-color); + text-decoration: none; +} + +a.control_group:active { + font-family: Arial, Helvetica, sans-serif; + color: var(--link-color); + text-decoration: none; +} \ No newline at end of file diff --git a/PowerShell/ScubaGear/Modules/Orchestrator.psm1 b/PowerShell/ScubaGear/Modules/Orchestrator.psm1 index 90147c32c9..8732885277 100644 --- a/PowerShell/ScubaGear/Modules/Orchestrator.psm1 +++ b/PowerShell/ScubaGear/Modules/Orchestrator.psm1 @@ -751,6 +751,8 @@ function Invoke-ReportCreation { $Images = Join-Path -Path $ReporterPath -ChildPath "images" -ErrorAction 'Stop' Copy-Item -Path $Images -Destination $IndividualReportPath -Force -Recurse -ErrorAction 'Stop' + $SecureBaselines = Import-SecureBaseline + foreach ($Product in $ProductNames) { $BaselineName = $ArgToProd[$Product] $N += 1 @@ -775,6 +777,7 @@ function Invoke-ReportCreation { 'OutProviderFileName' = $OutProviderFileName; 'OutRegoFileName' = $OutRegoFileName; 'DarkMode' = $DarkMode; + 'SecureBaselines' = $SecureBaselines } $Report = New-Report @CreateReportParams @@ -804,8 +807,8 @@ function Invoke-ReportCreation { } if ($Report.Errors -gt 0) { - $Noun = Pluralize -SingularNoun "check" -PluralNoun "errors" -Count $Report.Manual - $ErrorSummary = "
$($Report.Errors) PowerShell $($Noun)
" + $Noun = Pluralize -SingularNoun "error" -PluralNoun "errors" -Count $Report.Errors + $ErrorSummary = "
$($Report.Errors) $($Noun)
" } $Fragment += [pscustomobject]@{ diff --git a/PowerShell/ScubaGear/Modules/RunRego/RunRego.psm1 b/PowerShell/ScubaGear/Modules/RunRego/RunRego.psm1 index 9eb03a7af7..d81d46c921 100644 --- a/PowerShell/ScubaGear/Modules/RunRego/RunRego.psm1 +++ b/PowerShell/ScubaGear/Modules/RunRego/RunRego.psm1 @@ -38,7 +38,11 @@ function Invoke-Rego { # Permissions: chmod 755 ./opa $Cmd = Join-Path -Path $OPAPath -ChildPath "opa" -ErrorAction 'Stop' } - $CmdArgs = @("eval", "-i", $InputFile, "-d", $RegoFile, "data.$PackageName.tests", "-f", "values") + + # Load Utils + $RegoFileObject = Get-Item $RegoFile + $ScubaUtils = Join-Path -Path $RegoFileObject.DirectoryName -ChildPath "Utils" + $CmdArgs = @("eval", "data.$PackageName.tests", "-i", $InputFile, "-d", $RegoFile, "-d", $ScubaUtils, "-f", "values") $TestResults = $(& $Cmd @CmdArgs) | Out-String -ErrorAction 'Stop' | ConvertFrom-Json -ErrorAction 'Stop' $TestResults } diff --git a/Rego/AADConfig.rego b/Rego/AADConfig.rego index b9c2b0ea15..1a99f4dd80 100644 --- a/Rego/AADConfig.rego +++ b/Rego/AADConfig.rego @@ -1,17 +1,15 @@ package aad import future.keywords +import data.report.utils.NotCheckedDetails +import data.report.utils.Format +import data.report.utils.ReportDetailsBoolean ################ # The report formatting functions below are generic and used throughout the policies # ################ -Format(Array) = format_int(count(Array), 10) Description(String1, String2, String3) = trim(concat(" ", [String1, String2, String3]), " ") -ReportDetailsBoolean(Status) = "Requirement met" if {Status == true} - -ReportDetailsBoolean(Status) = "Requirement not met" if {Status == false} - ReportDetailsArray(Array, String) = Description(Format(Array), String, "") # Set to the maximum number of array items to be @@ -124,12 +122,8 @@ GroupExclusionsFullyExempt(Policy, PolicyID) := true if { count({ y | y := input.scuba_config.Aad[PolicyID].CapExclusions.Groups }) == 0 } -################ -# Baseline 2.1 # -################ - # -# Baseline 2.1: Policy 1 +# MS.AAD.1.1v1 #-- default Policy2_1_1ConditionsMatch(_) := false @@ -155,8 +149,7 @@ Policies2_1[Cap.DisplayName] { } tests[{ - "Requirement" : "Legacy authentication SHALL be blocked", - "Control" : "AAD 2.1", + "PolicyId" : "MS.AAD.1.1v1", "Criticality" : "Shall", "Commandlet" : ["Get-MgIdentityConditionalAccessPolicy"], "ActualValue" : Policies2_1, @@ -167,13 +160,8 @@ tests[{ true } -#-- -################ -# Baseline 2.2 # -################ - # -# Baseline 2.2: Policy 1 +# MS.AAD.2.1v1 #-- default Policy2_2_1ConditionsMatch(_) := false @@ -198,8 +186,7 @@ Policies2_2_1[Cap.DisplayName] { } tests[{ - "Requirement" : "Users detected as high risk SHALL be blocked", - "Control" : "AAD 2.2", + "PolicyId" : "MS.AAD.2.1v1", "Criticality" : "Shall", "Commandlet" : ["Get-MgIdentityConditionalAccessPolicy"], "ActualValue" : Policies2_2_1, @@ -212,29 +199,25 @@ tests[{ #-- # -# Baseline 2.2: Policy 2 +# MS.AAD.2.2v1 #-- # At this time we are unable to test for X because of Y tests[{ - "Requirement" : "A notification SHOULD be sent to the administrator when high-risk users are detected", - "Control" : "AAD 2.2", + "PolicyId": PolicyId, "Criticality" : "Should/Not-Implemented", "Commandlet" : [], "ActualValue" : [], - "ReportDetails" : "Currently cannot be checked automatically. See Azure Active Directory Secure Configuration Baseline policy 2.2 for instructions on manual check", + "ReportDetails" : NotCheckedDetails(PolicyId), "RequirementMet" : false }] { + PolicyId := "MS.AAD.2.2v1" true } #-- -################ -# Baseline 2.3 # -################ - # -# Baseline 2.3: Policy 1 +# MS.AAD.3.1v1 #-- default Policy2_3_1ConditionsMatch(_) := false @@ -259,8 +242,7 @@ Policies2_3[Cap.DisplayName] { } tests[{ - "Requirement" : "Sign-ins detected as high risk SHALL be blocked", - "Control" : "AAD 2.3", + "PolicyId": "MS.AAD.3.1v1", "Criticality" : "Shall", "Commandlet" : ["Get-MgIdentityConditionalAccessPolicy"], "ActualValue" : Policies2_3, @@ -273,12 +255,8 @@ tests[{ #-- -################ -# Baseline 2.4 # -################ - # -# Baseline 2.4: Policy 1 +# MS.AAD.4.1v1 #-- default Policy2_4_1ConditionsMatch(_) := false Policy2_4_1ConditionsMatch(Policy) := true if { @@ -301,8 +279,7 @@ Policies2_4_1[Cap.DisplayName] { } tests[{ - "Requirement" : "MFA SHALL be required for all users", - "Control" : "AAD 2.4", + "PolicyId" : "MS.AAD.4.1v1", "Criticality" : "Shall", "Commandlet" : ["Get-MgIdentityConditionalAccessPolicy"], "ActualValue" : Policies2_4_1, @@ -315,103 +292,127 @@ tests[{ #-- # -# Baseline 2.4: Policy 2 +# MS.AAD.4.2v1 #-- # At this time we are unable to fully test for MFA due to conflicting and multiple ways to configure authentication methods # Awaiting API changes and feature updates from Microsoft for automated checking tests[{ - "Requirement" : "Phishing-resistant MFA SHALL be used for all users", - "Control" : "AAD 2.4", + "PolicyId" : PolicyId, "Criticality" : "Shall/Not-Implemented", "Commandlet" : [], "ActualValue" : [], - "ReportDetails" : "Currently cannot be checked automatically. See Azure Active Directory Secure Configuration Baseline policy 2.4 for instructions on manual check", + "ReportDetails" : NotCheckedDetails(PolicyId), "RequirementMet" : false }] { + PolicyId := "MS.AAD.4.2v1" true } #-- # -# Baseline 2.4: Policy 3 +# MS.AAD.4.3v1 #-- # At this time we are unable to test for all users due to conflicting and multiple ways to configure authentication methods # Awaiting API changes and feature updates from Microsoft for automated checking tests[{ - "Requirement" : "If phishing-resistant MFA cannot be used, an MFA method from the list [see AAD baseline 2.4] SHALL be used in the interim", - "Control" : "AAD 2.4", + "PolicyId" : PolicyId, "Criticality" : "Shall/Not-Implemented", "Commandlet" : [], "ActualValue" : [], - "ReportDetails" : "Currently cannot be checked automatically. See Azure Active Directory Secure Configuration Baseline policy 2.4 for instructions on manual check", + "ReportDetails" : NotCheckedDetails(PolicyId), "RequirementMet" : false }] { + PolicyId := "MS.AAD.4.3v1" true } #-- # -# Baseline 2.4: Policy 4 +# MS.AAD.4.4v1 #-- # At this time we are unable to test for SMS/Voice settings due to lack of API to validate # Awaiting API changes and feature updates from Microsoft for automated checking tests[{ - "Requirement" : "SMS or Voice as the MFA method SHALL NOT be used", - "Control" : "AAD 2.4", + "PolicyId" : PolicyId, "Criticality" : "Shall/Not-Implemented", "Commandlet" : [], "ActualValue" : [], - "ReportDetails" : "Currently cannot be checked automatically. See Azure Active Directory Secure Configuration Baseline policy 2.4 for instructions on manual check", + "ReportDetails" : NotCheckedDetails(PolicyId), "RequirementMet" : false }] { + PolicyId := "MS.AAD.4.4v1" true } #-- -################ -# Baseline 2.5 # -################ - # -# Baseline 2.5: Policy 1 +# MS.AAD.5.1v1 #-- # At this time we are unable to test for log collection until we integrate Azure Powershell capabilities tests[{ - "Requirement" : "The following critical logs SHALL be sent at a minimum: AuditLogs, SignInLogs, RiskyUsers, UserRiskEvents, NonInteractiveUserSignInLogs, ServicePrincipalSignInLogs, ADFSSignInLogs, RiskyServicePrincipals, ServicePrincipalRiskEvents", - "Control" : "AAD 2.5", + "PolicyId" : PolicyId, "Criticality" : "Shall/Not-Implemented", "Commandlet" : [], "ActualValue" : [], - "ReportDetails" : "Currently cannot be checked automatically. See Azure Active Directory Secure Configuration Baseline policy 2.5 for instructions on manual check", + "ReportDetails" : NotCheckedDetails(PolicyId), + "RequirementMet" : false +}] { + PolicyId := "MS.AAD.5.1v1" + true +} +#-- + +# +# MS.AAD.5.2v1 +#-- +tests[{ + "PolicyId": PolicyId, + "Criticality" : "Should/Not-Implemented", + "Commandlet" : [], + "ActualValue" : [], + "ReportDetails" : NotCheckedDetails(PolicyId), "RequirementMet" : false }] { + PolicyId := "MS.AAD.5.2v1" true } #-- # -# Baseline 2.5: Policy 2 +# MS.AAD.5.3v1 +#-- +tests[{ + "PolicyId": PolicyId, + "Criticality" : "Should/Not-Implemented", + "Commandlet" : [], + "ActualValue" : [], + "ReportDetails" : NotCheckedDetails(PolicyId), + "RequirementMet" : false +}] { + PolicyId := "MS.AAD.5.3v1" + true +} +#-- + +# +# MS.AAD.5.4v1 #-- # At this time we are unable to test for X because of Y tests[{ - "Requirement" : "The logs SHALL be sent to the agency's SOC for monitoring", - "Control" : "AAD 2.5", + "PolicyId" : PolicyId, "Criticality" : "Shall/Not-Implemented", "Commandlet" : [], "ActualValue" : [], - "ReportDetails" : "Currently cannot be checked automatically. See Azure Active Directory Secure Configuration Baseline policy 2.5 for instructions on manual check", + "ReportDetails" : NotCheckedDetails(PolicyId), "RequirementMet" : false }] { + PolicyId := "MS.AAD.5.4v1" true } #-- -################ -# Baseline 2.6 # -################ - AuthPoliciesBad_2_6[Policy.Id] { Policy = input.authorization_policies[_] Policy.DefaultUserRolePermissions.AllowedToCreateApps == true @@ -425,11 +426,10 @@ AllAuthPoliciesAllowedCreate[{ } # -# Baseline 2.6: Policy 1 +# MS.AAD.6.1v1 #-- tests[{ - "Requirement" : "Only administrators SHALL be allowed to register third-party applications", - "Control" : "AAD 2.6", + "PolicyId" : "MS.AAD.6.1v1", "Criticality" : "Shall", "Commandlet" : ["Get-MgPolicyAuthorizationPolicy"], "ActualValue" : {"all_allowed_create_values": AllAuthPoliciesAllowedCreate}, @@ -442,13 +442,8 @@ tests[{ } #-- - -################ -# Baseline 2.7 # -################ - # -# Baseline 2.7: Policy 1 +# MS.AAD.7.1v1 #-- BadDefaultGrantPolicies[Policy.Id] { Policy = input.authorization_policies[_] @@ -463,8 +458,7 @@ AllDefaultGrantPolicies[{ } tests[{ - "Requirement" : "Only administrators SHALL be allowed to consent to third-party applications", - "Control" : "AAD 2.7", + "PolicyId" : "MS.AAD.7.1v1", "Criticality" : "Shall", "Commandlet" : ["Get-MgPolicyAuthorizationPolicy"], "ActualValue" : {"all_grant_policy_values": AllDefaultGrantPolicies}, @@ -478,7 +472,7 @@ tests[{ #-- # -# Baseline 2.7: Policy 2 +# MS.AAD.7.2v1 #-- BadConsentPolicies[Policy.Id] { Policy := input.admin_consent_policies[_] @@ -494,8 +488,7 @@ AllConsentPolicies[{ tests[{ - "Requirement" : "An admin consent workflow SHALL be configured", - "Control" : "AAD 2.7", + "PolicyId" : "MS.AAD.7.2v1", "Criticality" : "Shall", "Commandlet" : ["Get-MgPolicyAdminConsentRequestPolicy"], "ActualValue" : {"all_consent_policies": AllConsentPolicies}, @@ -508,7 +501,7 @@ tests[{ #-- # -# Baseline 2.7: Policy 3 +# MS.AAD.7.3v1 #-- AllConsentSettings[{ "SettingsGroup": SettingGroup.DisplayName, @@ -539,8 +532,7 @@ BadConsentSettings[{ } tests[{ - "Requirement" : "Group owners SHALL NOT be allowed to consent to third-party applications", - "Control" : "AAD 2.7", + "PolicyId" : "MS.AAD.7.3v1", "Criticality" : "Shall", "Commandlet" : ["Get-MgDirectorySetting"], "ActualValue" : AllConsentSettings, @@ -552,35 +544,25 @@ tests[{ } #-- - -################ -# Baseline 2.8 # -################ - # -# Baseline 2.8: Policy 1 +# MS.AAD.8.1v1 #-- # At this time we are unable to test for X because of Y tests[{ - "Requirement" : "User passwords SHALL NOT expire", - "Control" : "AAD 2.8", + "PolicyId" : PolicyId, "Criticality" : "Shall/Not-Implemented", "Commandlet" : [], "ActualValue" : [], - "ReportDetails" : "Currently cannot be checked automatically. See Azure Active Directory Secure Configuration Baseline policy 2.8 for instructions on manual check", + "ReportDetails" : NotCheckedDetails(PolicyId), "RequirementMet" : false }] { + PolicyId := "MS.AAD.8.1v1" true } #-- - -################ -# Baseline 2.9 # -################ - # -# Baseline 2.9: Policy 1 +# MS.AAD.9.1v1 #-- default Policy2_9_1ConditionsMatch(_) := false Policy2_9_1ConditionsMatch(Policy) := true if { @@ -605,8 +587,7 @@ Policies2_9[Cap.DisplayName] { } tests[{ - "Requirement" : "Sign-in frequency SHALL be configured to 12 hours", - "Control" : "AAD 2.9", + "PolicyId" : "MS.AAD.9.1v1", "Criticality" : "Shall", "Commandlet" : ["Get-MgIdentityConditionalAccessPolicy"], "ActualValue" : Policies2_9, @@ -618,13 +599,8 @@ tests[{ } #-- - -################# -# Baseline 2.10 # -################# - # -# Baseline 2.10: Policy 1 +# MS.AAD.10.1v1 #-- default Policy2_10_1ConditionsMatch(_) := false Policy2_10_1ConditionsMatch(Policy) := true if { @@ -648,8 +624,7 @@ Policies2_10[Cap.DisplayName] { } tests[{ - "Requirement" : "Browser sessions SHALL not be persistent", - "Control" : "AAD 2.10", + "PolicyId" : "MS.AAD.10.1v1", "Criticality" : "Shall", "Commandlet" : ["Get-MgIdentityConditionalAccessPolicy"], "ActualValue" : Policies2_10, @@ -661,13 +636,8 @@ tests[{ } #-- - -################# -# Baseline 2.11 # -################# - # -# Baseline 2.11: Policy 1 +# MS.AAD.11.1v1 #-- GlobalAdmins[User.DisplayName] { some id @@ -676,8 +646,7 @@ GlobalAdmins[User.DisplayName] { } tests[{ - "Requirement" : "A minimum of two users and a maximum of four users SHALL be provisioned with the Global Administrator role", - "Control" : "AAD 2.11", + "PolicyId" : "MS.AAD.11.1v1", "Criticality" : "Shall", "Commandlet" : ["Get-MgSubscribedSku", "Get-PrivilegedUser"], "ActualValue" : GlobalAdmins, @@ -690,13 +659,8 @@ tests[{ } #-- - -################# -# Baseline 2.12 # -################# - # -# Baseline 2.12: Policy 1 +# MS.AAD.12.1v1 #-- FederatedAdmins[User.DisplayName] { some id @@ -705,8 +669,7 @@ FederatedAdmins[User.DisplayName] { } tests[{ - "Requirement" : "Users that need to be assigned to highly privileged Azure AD roles SHALL be provisioned cloud-only accounts that are separate from the on-premises directory or other federated identity providers", - "Control" : "AAD 2.12", + "PolicyId" : "MS.AAD.12.1v1", "Criticality" : "Shall", "Commandlet" : ["Get-MgSubscribedSku", "Get-PrivilegedUser"], "ActualValue" : AdminNames, @@ -719,12 +682,8 @@ tests[{ } #-- -################# -# Baseline 2.13 # -################# - # -# Baseline 2.13: Policy 1 +# MS.AAD.13.1v1 #-- Policies2_13[Cap.DisplayName] { Cap := input.conditional_access_policies[_] @@ -744,8 +703,7 @@ Policies2_13[Cap.DisplayName] { } tests[{ - "Requirement" : "MFA SHALL be required for user access to highly privileged roles", - "Control" : "AAD 2.13", + "PolicyId" : "MS.AAD.13.1v1", "Criticality" : "Shall", "Commandlet" : ["Get-MgSubscribedSku", "Get-PrivilegedRole", "Get-MgIdentityConditionalAccessPolicy"], "ActualValue" : Policies2_13, @@ -758,7 +716,7 @@ tests[{ ################# -# Helper functions for policies 2.14, 2.15, 2.16 +# Helper functions for policies ################# # DoPIMRoleRulesExist will return true when the JSON privileged_roles.Rules element exists and false when it does not. @@ -783,12 +741,8 @@ DoPIMRoleAssignmentsExist { default check_if_role_assignments_exist := false check_if_role_assignments_exist := DoPIMRoleAssignmentsExist -################# -# Baseline 2.14 # -################# - # -# Baseline 2.14: Policy 1 +# MS.AAD.14.1v1 #-- RolesWithoutLimitedExpirationPeriod[Role.DisplayName] { Role := input.privileged_roles[_] @@ -811,8 +765,7 @@ RolesWithoutLimitedExpirationPeriod[Role.DisplayName] { } tests[{ - "Requirement" : "Permanent active role assignments SHALL NOT be allowed for highly privileged roles. Active assignments SHALL have an expiration period.", - "Control" : "AAD 2.14", + "PolicyId" : "MS.AAD.14.1v1", "Criticality" : "Shall", "Commandlet" : ["Get-MgSubscribedSku", "Get-PrivilegedRole"], "ActualValue" : RolesWithoutLimitedExpirationPeriod, @@ -826,7 +779,7 @@ tests[{ #-- # -# Baseline 2.14: Policy 2 +# MS.AAD.14.2v1 #-- RolesAssignedOutsidePim[Role.DisplayName] { Role := input.privileged_roles[_] @@ -836,8 +789,7 @@ RolesAssignedOutsidePim[Role.DisplayName] { } tests[{ - "Requirement" : "Provisioning of users to highly privileged roles SHALL NOT occur outside of a PAM system, such as the Azure AD PIM service, because this bypasses the controls the PAM system provides", - "Control" : "AAD 2.14", + "PolicyId" : "MS.AAD.14.2v1", "Criticality" : "Shall", "Commandlet" : ["Get-MgSubscribedSku", "Get-PrivilegedRole"], "ActualValue" : RolesAssignedOutsidePim, @@ -851,12 +803,8 @@ tests[{ #-- -################# -# Baseline 2.15 # -################# - # -# Baseline 2.15: Policy 1 +# MS.AAD.15.1v1 #-- RolesWithoutApprovalRequired[RoleName] { Role := input.privileged_roles[_] @@ -868,8 +816,7 @@ RolesWithoutApprovalRequired[RoleName] { } tests[{ - "Requirement" : "Activation of highly privileged roles SHOULD require approval", - "Control" : "AAD 2.15", + "PolicyId" : "MS.AAD.15.1v1", "Criticality" : "Should", "Commandlet" : ["Get-MgSubscribedSku", "Get-PrivilegedRole"], "ActualValue" : RolesWithoutApprovalRequired, @@ -882,13 +829,8 @@ tests[{ } #-- - -################# -# Baseline 2.16 # -################# - # -# Baseline 2.16: Policy 1 +# MS.AAD.16.1v1 #-- RolesWithoutActiveAssignmentAlerts[RoleName] { Role := input.privileged_roles[_] @@ -909,8 +851,7 @@ RolesWithoutEligibleAssignmentAlerts[RoleName] { } tests[{ - "Requirement" : "Eligible and Active highly privileged role assignments SHALL trigger an alert", - "Control" : "AAD 2.16", + "PolicyId" : "MS.AAD.16.1v1", "Criticality" : "Shall", "Commandlet" : ["Get-MgSubscribedSku", "Get-PrivilegedRole"], "ActualValue" : RolesWithoutAssignmentAlerts, @@ -925,7 +866,7 @@ tests[{ #-- # -# Baseline 2.16: Policy 2 +# MS.AAD.16.2v1 #-- AdminsWithoutActivationAlert[RoleName] { Role := input.privileged_roles[_] @@ -938,8 +879,7 @@ AdminsWithoutActivationAlert[RoleName] { } tests[{ - "Requirement" : "User activation of the Global Administrator role SHALL trigger an alert", - "Control" : "AAD 2.16", + "PolicyId" : "MS.AAD.16.2v1", "Criticality" : "Shall", "Commandlet" : ["Get-MgSubscribedSku", "Get-PrivilegedRole"], "ActualValue" : AdminsWithoutActivationAlert, @@ -953,11 +893,10 @@ tests[{ #-- # -# Baseline 2.16: Policy 3 +# MS.AAD.16.3v1 #-- tests[{ - "Requirement" : "User activation of other highly privileged roles SHOULD trigger an alert", - "Control" : "AAD 2.16", + "PolicyId" : "MS.AAD.16.3v1", "Criticality" : "Should", "Commandlet" : ["Get-MgSubscribedSku", "Get-PrivilegedRole"], "ActualValue" : NonGlobalAdminsWithoutActivationAlert, @@ -971,13 +910,8 @@ tests[{ } #-- - -################# -# Baseline 2.17 # -################# - # -# Baseline 2.17: Policy 1 +# MS.AAD.17.1v1 #-- Policies2_17[Cap.DisplayName] { Cap := input.conditional_access_policies[_] @@ -992,8 +926,7 @@ Policies2_17[Cap.DisplayName] { } tests[{ - "Requirement" : "Managed devices SHOULD be required for authentication", - "Control" : "AAD 2.17", + "PolicyId" : "MS.AAD.17.1v1", "Criticality" : "Should", "Commandlet" : ["Get-MgIdentityConditionalAccessPolicy"], "ActualValue" : Policies2_17, @@ -1005,15 +938,9 @@ tests[{ } #-- - -################# -# Baseline 2.18 # -################# - # -# Baseline 2.18: Policy 1 +# MS.AAD.18.1v1 #-- - AuthPoliciesBadAllowInvites[Policy.Id] { Policy = input.authorization_policies[_] Policy.AllowInvitesFrom != "adminsAndGuestInviters" @@ -1031,8 +958,7 @@ AllAuthPoliciesAllowInvites[{ } tests[{ - "Requirement" : "Only users with the Guest Inviter role SHOULD be able to invite guest users", - "Control" : "AAD 2.18", + "PolicyId" : "MS.AAD.18.1v1", "Criticality" : "Should", "Commandlet" : ["Get-MgPolicyAuthorizationPolicy"], "ActualValue" : {"all_allow_invite_values": AllAuthPoliciesAllowInvites}, @@ -1046,24 +972,24 @@ tests[{ #-- # -# Baseline 2.18: Policy 2 +# MS.AAD.18.2v1 #-- # At this time we are unable to test for X because of Y tests[{ - "Requirement" : "Guest invites SHOULD only be allowed to specific external domains that have been authorized by the agency for legitimate business purposes", - "Control" : "AAD 2.18", + "PolicyId" : PolicyId, "Criticality" : "Should/Not-Implemented", "Commandlet" : [], "ActualValue" : [], - "ReportDetails" : "Currently cannot be checked automatically. See Azure Active Directory Secure Configuration Baseline policy 2.18 for instructions on manual check", + "ReportDetails" : NotCheckedDetails(PolicyId), "RequirementMet" : false }] { + PolicyId := "MS.AAD.18.2v1" true } #-- # -# Baseline 2.18: Policy 3 +# MS.AAD.18.3v1 #-- # must hardcode the ID. See # https://docs.microsoft.com/en-us/azure/active-directory/enterprise-users/users-restrict-guest-permissions @@ -1091,10 +1017,8 @@ RoleIdByPolicy[concat("", ["\"", Level, "\"", " (", Policy.Id, ")"])] { Level := LevelAsString(Policy.GuestUserRoleId) } - tests[{ - "Requirement" : "Guest users SHOULD have limited access to Azure AD directory objects", - "Control" : "AAD 2.18", + "PolicyId" : "MS.AAD.18.3v1", "Criticality" : "Should", "Commandlet" : ["Get-MgPolicyAuthorizationPolicy"], "ActualValue" : {"all_roleid_values" : AllAuthPoliciesRoleIds}, diff --git a/Rego/DefenderConfig.rego b/Rego/DefenderConfig.rego index 621de67d71..69b2b51e3a 100644 --- a/Rego/DefenderConfig.rego +++ b/Rego/DefenderConfig.rego @@ -1,34 +1,31 @@ package defender import future.keywords +import data.report.utils.NotCheckedDetails +import data.report.utils.ReportDetailsBoolean ## Report details menu # +# NOTE: Use report.utils package for common report formatting functions. +# # If you simply want a boolean "Requirement met" / "Requirement not met" -# just call ReportDetails(Status) and leave it at that. +# just call ReportDetailsBoolean(Status) and leave it at that. # # If you want to customize the error message, wrap the ReportDetails call # inside CustomizeError, like so: -# CustomizeError(ReportDetails(Status), "Custom error message") +# CustomizeError(ReportDetailsBoolean(Status), "Custom error message") # # If you want to customize the error message with details about an array, # generate the custom error message using GenerateArrayString, for example: -# CustomizeError(ReportDetails(Status), GenerateArrayString(BadPolicies, "bad policies found:")) +# CustomizeError(ReportDetailsBoolean(Status), GenerateArrayString(BadPolicies, "bad policies found:")) # # If the setting in question requires a defender license, # wrap the details string inside ApplyLicenseWarning, like so: -# ApplyLicenseWarning(ReportDetails(Status)) +# ApplyLicenseWarning(ReportDetailsBoolean(Status)) # # These functions can be nested. For example: -# ApplyLicenseWarning(CustomizeError(ReportDetails(Status), "Custom error message")) +# ApplyLicenseWarning(CustomizeError(ReportDetailsBoolean(Status), "Custom error message")) # ## -ReportDetails(Status) := "Requirement met" if { - Status == true -} - -ReportDetails(Status) := "Requirement not met" if { - Status == false -} GenerateArrayString(Array, CustomString) := Output if { # Example usage and output: @@ -42,13 +39,13 @@ GenerateArrayString(Array, CustomString) := Output if { CustomizeError(Message, CustomString) := Message if { # If the message reports success, don't apply the custom # error message - Message == ReportDetails(true) + Message == ReportDetailsBoolean(true) } CustomizeError(Message, CustomString) := CustomString if { # If the message does not report success, apply the custom # error message - Message != ReportDetails(true) + Message != ReportDetailsBoolean(true) } ApplyLicenseWarning(Message) := Message if { @@ -57,19 +54,15 @@ ApplyLicenseWarning(Message) := Message if { input.defender_license == true } -ApplyLicenseWarning(Message) := concat("", [ReportDetails(false), LicenseWarning]) if { +ApplyLicenseWarning(Message) := concat("", [ReportDetailsBoolean(false), LicenseWarning]) if { # If a defender license is not present, assume failure and # replace the message with the warning input.defender_license == false LicenseWarning := " **NOTE: Either you do not have sufficient permissions or your tenant does not have a license for Microsoft Defender for Office 365 Plan 1, which is required for this feature.**" } -################ -# Baseline 2.1 # -################ - # -# Baseline 2.1: Policy 1 +# MS.DEFENDER.1.1v1 #-- StandardPresetSecurityPolicy[Rules.State] { Rules := input.protection_policy_rules[_] @@ -77,12 +70,12 @@ StandardPresetSecurityPolicy[Rules.State] { } tests[{ - "Requirement" : "Standard Preset security profiles SHOULD NOT be used", - "Control" : "Defender 2.1", + #TODO: Multiple mappings + "PolicyId" : "MS.DEFENDER.1.1v1", "Criticality" : "Should", "Commandlet" : ["Get-EOPProtectionPolicyRule"], "ActualValue" : Policy, - "ReportDetails" : CustomizeError(ReportDetails(Status), ErrorMessage), + "ReportDetails" : CustomizeError(ReportDetailsBoolean(Status), ErrorMessage), "RequirementMet" : Status }] { Policy := StandardPresetSecurityPolicy @@ -92,7 +85,7 @@ tests[{ } #-- -# +# TODO: Resolve Policy Id # Baseline 2.1: Policy 2 #-- StrictPresetSecurityPolicy[Rules.State] { @@ -106,7 +99,7 @@ tests[{ "Criticality" : "Should", "Commandlet" : ["Get-EOPProtectionPolicyRule"], "ActualValue" : Policy, - "ReportDetails" : CustomizeError(ReportDetails(Status), ErrorMessage), + "ReportDetails" : CustomizeError(ReportDetailsBoolean(Status), ErrorMessage), "RequirementMet" : Status }] { Policy := StrictPresetSecurityPolicy @@ -116,11 +109,6 @@ tests[{ } #-- - -################ -# Baseline 2.2 # -################ - # Determine the set of rules that pertain to SSNs, ITINs, or credit card numbers. # Used in multiple bullet points below SensitiveRules[{ @@ -146,7 +134,7 @@ SensitiveRules[{ } # -# Baseline 2.2: Policy 1 +# MS.DEFENDER.2.1v1 #-- # Step 1: Ensure that there is coverage for SSNs, ITINs, and credit cards SSNRules[Rule.Name] { @@ -165,12 +153,13 @@ CardRules[Rule.Name] { } tests[{ - "Requirement" : "A custom policy SHALL be configured to protect PII and sensitive information, as defined by the agency: U.S. Social Security Number (SSN)", - "Control" : "Defender 2.2", + #TODO: Appears this policy is broken into 3 parts in code and only 1 in baseline + #"Requirement" : "A custom policy SHALL be configured to protect PII and sensitive information, as defined by the agency: U.S. Social Security Number (SSN)", + "PolicyId" : "MS.DEFENDER.2.1v1", "Criticality" : "Shall", "Commandlet" : ["Get-DlpComplianceRule"], "ActualValue" : Rules, - "ReportDetails" : CustomizeError(ReportDetails(Status), ErrorMessage), + "ReportDetails" : CustomizeError(ReportDetailsBoolean(Status), ErrorMessage), "RequirementMet" : Status }] { Rules := SSNRules @@ -184,7 +173,7 @@ tests[{ "Criticality" : "Shall", "Commandlet" : ["Get-DlpComplianceRule"], "ActualValue" : Rules, - "ReportDetails" : CustomizeError(ReportDetails(Status), ErrorMessage), + "ReportDetails" : CustomizeError(ReportDetailsBoolean(Status), ErrorMessage), "RequirementMet" : Status }] { Rules := ITINRules @@ -198,7 +187,7 @@ tests[{ "Criticality" : "Shall", "Commandlet" : ["Get-DlpComplianceRule"], "ActualValue" : Rules, - "ReportDetails" : CustomizeError(ReportDetails(Status), ErrorMessage), + "ReportDetails" : CustomizeError(ReportDetailsBoolean(Status), ErrorMessage), "RequirementMet" : Status }] { Rules := CardRules @@ -260,12 +249,13 @@ TeamsPolicies[{ } tests[{ - "Requirement" : "The custom policy SHOULD be applied in Exchange", - "Control" : "Defender 2.2", + #TODO: Appears this policy is broken into 4 parts in code and only 1 in baseline + #"Requirement" : "The custom policy SHOULD be applied in Exchange", + "PolicyId" : "MS.DEFENDER.2.2v1", "Criticality" : "Should", "Commandlet" : ["Get-DLPCompliancePolicy"], "ActualValue" : Policies, - "ReportDetails" : CustomizeError(ReportDetails(Status), ErrorMessage), + "ReportDetails" : CustomizeError(ReportDetailsBoolean(Status), ErrorMessage), "RequirementMet" : Status }] { Policies := ExchangePolicies @@ -279,7 +269,7 @@ tests[{ "Criticality" : "Should", "Commandlet" : ["Get-DLPCompliancePolicy"], "ActualValue" : Policies, - "ReportDetails" : CustomizeError(ReportDetails(Status), ErrorMessage), + "ReportDetails" : CustomizeError(ReportDetailsBoolean(Status), ErrorMessage), "RequirementMet" : Status }] { Policies := SharePointPolicies @@ -293,7 +283,7 @@ tests[{ "Criticality" : "Should", "Commandlet" : ["Get-DLPCompliancePolicy"], "ActualValue" : Policies, - "ReportDetails" : CustomizeError(ReportDetails(Status), ErrorMessage), + "ReportDetails" : CustomizeError(ReportDetailsBoolean(Status), ErrorMessage), "RequirementMet" : Status }] { Policies := OneDrivePolicies @@ -307,7 +297,7 @@ tests[{ "Criticality" : "Should", "Commandlet" : ["Get-DLPCompliancePolicy"], "ActualValue" : Policies, - "ReportDetails" : CustomizeError(ReportDetails(Status), ErrorMessage), + "ReportDetails" : CustomizeError(ReportDetailsBoolean(Status), ErrorMessage), "RequirementMet" : Status }] { Policies := TeamsPolicies @@ -339,12 +329,11 @@ SensitiveRulesNotBlocking[Rule.Name] { } tests[{ - "Requirement" : "The action for the DLP policy SHOULD be set to block sharing sensitive information with everyone when DLP conditions are met", - "Control" : "Defender 2.2", + "PolicyId" : "MS.DEFENDER.2.3v1", "Criticality" : "Should", "Commandlet" : ["Get-DlpComplianceRule"], "ActualValue" : Rules, - "ReportDetails" : CustomizeError(ReportDetails(Status), GenerateArrayString(Rules, ErrorMessage)), + "ReportDetails" : CustomizeError(ReportDetailsBoolean(Status), GenerateArrayString(Rules, ErrorMessage)), "RequirementMet" : Status }] { Rules := SensitiveRulesNotBlocking @@ -363,12 +352,11 @@ SensitiveRulesNotNotifying[Rule.Name] { } tests[{ - "Requirement" : "Notifications to inform users and help educate them on the proper use of sensitive information SHOULD be enabled", - "Control" : "Defender 2.2", + "PolicyId" : "MS.DEFENDER.2.4v1", "Criticality" : "Should", "Commandlet" : ["Get-DlpComplianceRule"], "ActualValue" : Rules, - "ReportDetails" : CustomizeError(ReportDetails(Status), GenerateArrayString(Rules, ErrorMessage)), + "ReportDetails" : CustomizeError(ReportDetailsBoolean(Status), GenerateArrayString(Rules, ErrorMessage)), "RequirementMet" : Status }] { Rules := SensitiveRulesNotNotifying @@ -382,14 +370,14 @@ tests[{ #-- # At this time we are unable to test for X because of Y tests[{ - "Requirement" : "A list of apps that are not allowed to access files protected by DLP policy SHOULD be defined", - "Control" : "Defender 2.2", + "PolicyId" : PolicyId, "Criticality" : "Should/Not-Implemented", "Commandlet" : [], "ActualValue" : [], - "ReportDetails" : "Currently cannot be checked automatically. See Defender Secure Configuration Baseline policy 2.2 for instructions on manual check", + "ReportDetails" : NotCheckedDetails(PolicyId), "RequirementMet" : false }] { + PolicyId := "MS.DEFENDER.2.5v1" true } #-- @@ -399,14 +387,14 @@ tests[{ #-- # At this time we are unable to test for X because of Y tests[{ - "Requirement" : "A list of browsers that are not allowed to access files protected by DLP policy SHOULD be defined", - "Control" : "Defender 2.2", + "PolicyId" : PolicyId, "Criticality" : "Should/Not-Implemented", "Commandlet" : [], "ActualValue" : [], - "ReportDetails" : "Currently cannot be checked automatically. See Defender Secure Configuration Baseline policy 2.2 for instructions on manual check", + "ReportDetails" : NotCheckedDetails(PolicyId), "RequirementMet" : false }] { + PolicyId := "MS.DEFENDER.2.6v1" true } #-- @@ -425,12 +413,11 @@ MalwarePoliciesWithoutFileFilter[Policy.Name] { } tests[{ - "Requirement" : "The common attachments filter SHALL be enabled in the default anti-malware policy and in all existing policies", - "Control" : "Defender 2.3", + "PolicyId" : "MS.DEFENDER.3.1v1", "Criticality" : "Shall", "Commandlet" : ["Get-MalwareFilterPolicy"], "ActualValue" : Policies, - "ReportDetails" : CustomizeError(ReportDetails(Status), GenerateArrayString(Policies, ErrorMessage)), + "ReportDetails" : CustomizeError(ReportDetailsBoolean(Status), GenerateArrayString(Policies, ErrorMessage)), "RequirementMet" : Status }] { Policies := MalwarePoliciesWithoutFileFilter @@ -450,12 +437,13 @@ MalwarePoliciesBlockingEXE[Policy.Name] { } tests[{ - "Requirement" : "Disallowed file types SHALL be determined and set. At a minimum, click-to-run files SHOULD be blocked: exe files", - "Control" : "Defender 2.3", + #TODO: Appears this policy is broken into 3 parts in code and only 1 in baseline + #"Requirement" : "Disallowed file types SHALL be determined and set. At a minimum, click-to-run files SHOULD be blocked: exe files", + "PolicyId" : "MS.DEFENDER.3.2v1", "Criticality" : "Should", "Commandlet" : ["Get-MalwareFilterPolicy"], "ActualValue" : Policies, - "ReportDetails" : CustomizeError(ReportDetails(Status), ErrorMessage), + "ReportDetails" : CustomizeError(ReportDetailsBoolean(Status), ErrorMessage), "RequirementMet" : Status }] { Policies := MalwarePoliciesBlockingEXE @@ -476,7 +464,7 @@ tests[{ "Criticality" : "Should", "Commandlet" : ["Get-MalwareFilterPolicy"], "ActualValue" : Policies, - "ReportDetails" : CustomizeError(ReportDetails(Status), ErrorMessage), + "ReportDetails" : CustomizeError(ReportDetailsBoolean(Status), ErrorMessage), "RequirementMet" : Status }] { Policies := MalwarePoliciesBlockingCMD @@ -497,7 +485,7 @@ tests[{ "Criticality" : "Should", "Commandlet" : ["Get-MalwareFilterPolicy"], "ActualValue" : Policies, - "ReportDetails" : CustomizeError(ReportDetails(Status), ErrorMessage), + "ReportDetails" : CustomizeError(ReportDetailsBoolean(Status), ErrorMessage), "RequirementMet" : Status }] { Policies := MalwarePoliciesBlockingVBE @@ -520,12 +508,11 @@ MalwarePoliciesWithoutZAP[Policy.Name] { } tests[{ - "Requirement" : "Zero-hour Auto Purge (ZAP) for malware SHOULD be enabled in the default anti-malware policy and in all existing custom policies", - "Control" : "Defender 2.4", + "PolicyId" : "MS.DEFENDER.4.1v1", "Criticality" : "Should", "Commandlet" : ["Get-MalwareFilterPolicy"], "ActualValue" : Policies, - "ReportDetails" : CustomizeError(ReportDetails(Status), GenerateArrayString(Policies, ErrorMessage)), + "ReportDetails" : CustomizeError(ReportDetailsBoolean(Status), GenerateArrayString(Policies, ErrorMessage)), "RequirementMet" : Status }] { Policies := MalwarePoliciesWithoutZAP @@ -555,12 +542,11 @@ ProtectedUsersPolicies[{ # assert that at least one of the enabled policies includes protected users tests[{ - "Requirement" : "User impersonation protection SHOULD be enabled for key agency leaders", - "Control" : "Defender 2.5", + "PolicyId" : "MS.DEFENDER.5.1v1", "Criticality" : "Should", "Commandlet" : ["Get-AntiPhishPolicy"], "ActualValue" : Policies, - "ReportDetails" : CustomizeError(ReportDetails(Status), ErrorMessage), + "ReportDetails" : CustomizeError(ReportDetailsBoolean(Status), ErrorMessage), "RequirementMet" : Status }] { Policies := ProtectedUsersPolicies @@ -586,12 +572,11 @@ ProtectedOrgDomainsPolicies[{ # assert that at least one of the enabled policies includes # protection for the org's own domains tests[{ - "Requirement" : "Domain impersonation protection SHOULD be enabled for domains owned by the agency", - "Control" : "Defender 2.5", + "PolicyId" : "MS.DEFENDER.5.2v1", "Criticality" : "Should", "Commandlet" : ["Get-AntiPhishPolicy"], "ActualValue" : Policies, - "ReportDetails" : ReportDetails(Status), + "ReportDetails" : ReportDetailsBoolean(Status), "RequirementMet" : Status }] { Policies := ProtectedOrgDomainsPolicies @@ -616,12 +601,11 @@ ProtectedCustomDomainsPolicies[{ # assert that at least one of the enabled policies includes # protection for custom domains tests[{ - "Requirement" : "Domain impersonation protection SHOULD be added for frequent partners", - "Control" : "Defender 2.5", + "PolicyId" : "MS.DEFENDER.5.3v1", "Criticality" : "Should", "Commandlet" : ["Get-AntiPhishPolicy"], "ActualValue" : Policies, - "ReportDetails" : CustomizeError(ReportDetails(Status), ErrorMessage), + "ReportDetails" : CustomizeError(ReportDetailsBoolean(Status), ErrorMessage), "RequirementMet" : Status }] { Policies := ProtectedCustomDomainsPolicies @@ -646,12 +630,11 @@ IntelligenceProtectionPolicies[{ # assert that at least one of the enabled policies includes # intelligence protection tests[{ - "Requirement" : "Intelligence for impersonation protection SHALL be enabled", - "Control" : "Defender 2.5", + "PolicyId" : "MS.DEFENDER.5.5v1", "Criticality" : "Should", "Commandlet" : ["Get-AntiPhishPolicy"], "ActualValue" : Policies, - "ReportDetails" : ReportDetails(Status), + "ReportDetails" : ReportDetailsBoolean(Status), "RequirementMet" : Status }] { Policies := IntelligenceProtectionPolicies @@ -664,12 +647,13 @@ tests[{ #-- # Step 1: Default (SHALL) tests[{ - "Requirement" : "Message action SHALL be set to quarantine if the message is detected as impersonated: users default policy", - "Control" : "Defender 2.5", + #TODO: Multiple mappings + #"Requirement" : "Message action SHALL be set to quarantine if the message is detected as impersonated: users default policy", + "PolicyId" : "MS.DEFENDER.5.6v1", "Criticality" : "Shall", "Commandlet" : ["Get-AntiPhishPolicy"], "ActualValue" : Policy.TargetedUserProtectionAction, - "ReportDetails" : ReportDetails(Status), + "ReportDetails" : ReportDetailsBoolean(Status), "RequirementMet" : Status }] { Policy := input.anti_phish_policies[_] @@ -683,7 +667,7 @@ tests[{ "Criticality" : "Shall", "Commandlet" : ["Get-AntiPhishPolicy"], "ActualValue" : Policy.TargetedDomainProtectionAction, - "ReportDetails" : ReportDetails(Status), + "ReportDetails" : ReportDetailsBoolean(Status), "RequirementMet" : Status }] { Policy := input.anti_phish_policies[_] @@ -697,7 +681,7 @@ tests[{ "Criticality" : "Shall", "Commandlet" : ["Get-AntiPhishPolicy"], "ActualValue" : Policy.MailboxIntelligenceProtectionAction, - "ReportDetails" : ReportDetails(Status), + "ReportDetails" : ReportDetailsBoolean(Status), "RequirementMet" : Status }] { Policy := input.anti_phish_policies[_] @@ -721,7 +705,7 @@ tests[ { "Criticality" : "Should", "Commandlet" : ["Get-AntiPhishPolicy"], "ActualValue" : Policies, - "ReportDetails" : CustomizeError(ReportDetails(Status), GenerateArrayString(Policies, ErrorMessage)), + "ReportDetails" : CustomizeError(ReportDetailsBoolean(Status), GenerateArrayString(Policies, ErrorMessage)), "RequirementMet" : Status }] { Policies := AntiPhishTargetedUserNotQuarantine @@ -743,7 +727,7 @@ tests[ { "Criticality" : "Should", "Commandlet" : ["Get-AntiPhishPolicy"], "ActualValue" : Policies, - "ReportDetails" : CustomizeError(ReportDetails(Status), GenerateArrayString(Policies, ErrorMessage)), + "ReportDetails" : CustomizeError(ReportDetailsBoolean(Status), GenerateArrayString(Policies, ErrorMessage)), "RequirementMet" : Status }] { Policies := AntiPhishTargetedDomainNotQuarantine @@ -765,7 +749,7 @@ tests[ { "Criticality" : "Should", "Commandlet" : ["Get-AntiPhishPolicy"], "ActualValue" : Policies, - "ReportDetails" : CustomizeError(ReportDetails(Status), GenerateArrayString(Policies, ErrorMessage)), + "ReportDetails" : CustomizeError(ReportDetailsBoolean(Status), GenerateArrayString(Policies, ErrorMessage)), "RequirementMet" : Status }] { Policies := AntiPhishMailIntNotQuarantine @@ -781,12 +765,13 @@ tests[ { # represent this, we have two tests checking the default and the # nondefault. tests[ { - "Requirement" : "Mail classified as spoofed SHALL be quarantined: default policy", - "Control" : "Defender 2.5", + #TODO: Multiple Mappings + #"Requirement" : "Mail classified as spoofed SHALL be quarantined: default policy", + "PolicyId" : "MS.DEFENDER.5.7v1", "Criticality" : "Shall", "Commandlet" : ["Get-AntiPhishPolicy"], "ActualValue" : Policy.AuthenticationFailAction, - "ReportDetails" : ReportDetails(Status), + "ReportDetails" : ReportDetailsBoolean(Status), "RequirementMet" : Status }] { Policy := input.anti_phish_policies[_] @@ -810,7 +795,7 @@ tests[ { "Criticality" : "Should", "Commandlet" : ["Get-AntiPhishPolicy"], "ActualValue" : Policies, - "ReportDetails" : CustomizeError(ReportDetails(Status), GenerateArrayString(Policies, ErrorMessage)), + "ReportDetails" : CustomizeError(ReportDetailsBoolean(Status), GenerateArrayString(Policies, ErrorMessage)), "RequirementMet" : Status }] { ErrorMessage := "custom anti phish policy(ies) found where the action for spoofed emails is not set to quarantine:" @@ -824,12 +809,13 @@ tests[ { #-- # First contact default policy tests[ { - "Requirement" : "All safety tips SHALL be enabled: first contact default policy", - "Control" : "Defender 2.5", + #TODO: Multiple Mappings + #"Requirement" : "All safety tips SHALL be enabled: first contact default policy", + "PolicyId" : "MS.DEFENDER.5.8v1", "Criticality" : "Shall", "Commandlet" : ["Get-AntiPhishPolicy"], "ActualValue" : Policy.EnableFirstContactSafetyTips, - "ReportDetails" : ReportDetails(Status), + "ReportDetails" : ReportDetailsBoolean(Status), "RequirementMet" : Status }] { Policy := input.anti_phish_policies[_] @@ -852,7 +838,7 @@ tests[{ "Criticality" : "Should", "Commandlet" : ["Get-AntiPhishPolicy"], "ActualValue" : Policies, - "ReportDetails" : CustomizeError(ReportDetails(Status), GenerateArrayString(Policies, ErrorMessage)), + "ReportDetails" : CustomizeError(ReportDetailsBoolean(Status), GenerateArrayString(Policies, ErrorMessage)), "RequirementMet" : Status }] { ErrorMessage := "custom anti phish policy(ies) found where first contact safety tips are not enabled:" @@ -867,7 +853,7 @@ tests[{ "Criticality" : "Shall", "Commandlet" : ["Get-AntiPhishPolicy"], "ActualValue" : Policy.EnableSimilarUsersSafetyTips, - "ReportDetails" : ReportDetails(Status), + "ReportDetails" : ReportDetailsBoolean(Status), "RequirementMet" : Status }] { Policy := input.anti_phish_policies[_] @@ -890,7 +876,7 @@ tests[{ "Criticality" : "Should", "Commandlet" : ["Get-AntiPhishPolicy"], "ActualValue" : Policies, - "ReportDetails" : CustomizeError(ReportDetails(Status), GenerateArrayString(Policies, ErrorMessage)), + "ReportDetails" : CustomizeError(ReportDetailsBoolean(Status), GenerateArrayString(Policies, ErrorMessage)), "RequirementMet" : Status }] { ErrorMessage := "custom anti phish policy(ies) found where similar user safety tips are not enabled:" @@ -905,7 +891,7 @@ tests[{ "Criticality" : "Shall", "Commandlet" : ["Get-AntiPhishPolicy"], "ActualValue" : Policy.EnableSimilarDomainsSafetyTips, - "ReportDetails" : ReportDetails(Status), + "ReportDetails" : ReportDetailsBoolean(Status), "RequirementMet" : Status }] { Policy := input.anti_phish_policies[_] @@ -928,7 +914,7 @@ tests[{ "Criticality" : "Should", "Commandlet" : ["Get-AntiPhishPolicy"], "ActualValue" : Policies, - "ReportDetails" : CustomizeError(ReportDetails(Status), GenerateArrayString(Policies, ErrorMessage)), + "ReportDetails" : CustomizeError(ReportDetailsBoolean(Status), GenerateArrayString(Policies, ErrorMessage)), "RequirementMet" : Status }] { ErrorMessage := "custom anti phish policy(ies) found where similar domains safety tips are not enabled:" @@ -943,7 +929,7 @@ tests[{ "Criticality" : "Shall", "Commandlet" : ["Get-AntiPhishPolicy"], "ActualValue" : Policy.EnableUnusualCharactersSafetyTips, - "ReportDetails" : ReportDetails(Status), + "ReportDetails" : ReportDetailsBoolean(Status), "RequirementMet" : Status }] { Policy := input.anti_phish_policies[_] @@ -966,7 +952,7 @@ tests[{ "Criticality" : "Should", "Commandlet" : ["Get-AntiPhishPolicy"], "ActualValue" : Policies, - "ReportDetails" : CustomizeError(ReportDetails(Status), GenerateArrayString(Policies, ErrorMessage)), + "ReportDetails" : CustomizeError(ReportDetailsBoolean(Status), GenerateArrayString(Policies, ErrorMessage)), "RequirementMet" : Status }] { ErrorMessage := "custom anti phish policy(ies) found where unusual character safety tips are not enabled:" @@ -981,7 +967,7 @@ tests[{ "Criticality" : "Shall", "Commandlet" : ["Get-AntiPhishPolicy"], "ActualValue" : Policy.EnableViaTag, - "ReportDetails" : ReportDetails(Status), + "ReportDetails" : ReportDetailsBoolean(Status), "RequirementMet" : Status }] { Policy := input.anti_phish_policies[_] @@ -1004,7 +990,7 @@ tests[{ "Criticality" : "Should", "Commandlet" : ["Get-AntiPhishPolicy"], "ActualValue" : Policies, - "ReportDetails" : CustomizeError(ReportDetails(Status), GenerateArrayString(Policies, ErrorMessage)), + "ReportDetails" : CustomizeError(ReportDetailsBoolean(Status), GenerateArrayString(Policies, ErrorMessage)), "RequirementMet" : Status }] { ErrorMessage := "custom anti phish policy(ies) found where via tag is not enabled:" @@ -1019,7 +1005,7 @@ tests[{ "Criticality" : "Shall", "Commandlet" : ["Get-AntiPhishPolicy"], "ActualValue" : Policy.EnableUnauthenticatedSender, - "ReportDetails" : ReportDetails(Status), + "ReportDetails" : ReportDetailsBoolean(Status), "RequirementMet" : Status }] { Policy := input.anti_phish_policies[_] @@ -1042,7 +1028,7 @@ tests[{ "Criticality" : "Should", "Commandlet" : ["Get-AntiPhishPolicy"], "ActualValue" : Policies, - "ReportDetails" : CustomizeError(ReportDetails(Status), GenerateArrayString(Policies, ErrorMessage)), + "ReportDetails" : CustomizeError(ReportDetailsBoolean(Status), GenerateArrayString(Policies, ErrorMessage)), "RequirementMet" : Status }] { ErrorMessage := "custom anti phish policy(ies) found where '?' for unauthenticated sender is not enabled:" @@ -1061,12 +1047,13 @@ tests[{ # Baseline 2.6: Policy 1 #-- tests[{ - "Requirement" : "The bulk complaint level (BCL) threshold SHOULD be set to six or lower: default policy", - "Control" : "Defender 2.6", + #TODO: Multiple mappings + #"Requirement" : "The bulk complaint level (BCL) threshold SHOULD be set to six or lower: default policy", + "PolicyId" : "MS.DEFENDER.6.1v1", "Criticality" : "Should", "Commandlet" : ["Get-HostedContentFilterPolicy"], "ActualValue" : Policy.BulkThreshold, - "ReportDetails" : ReportDetails(Status), + "ReportDetails" : ReportDetailsBoolean(Status), "RequirementMet" : Status }] { Policy := input.hosted_content_filter_policies[_] # Refactor @@ -1086,7 +1073,7 @@ tests[{ "Criticality" : "Should", "Commandlet" : ["Get-HostedContentFilterPolicy"], "ActualValue" : Policies, - "ReportDetails" : CustomizeError(ReportDetails(Status), GenerateArrayString(Policies, ErrorMessage)), + "ReportDetails" : CustomizeError(ReportDetailsBoolean(Status), GenerateArrayString(Policies, ErrorMessage)), "RequirementMet" : Status }] { ErrorMessage := "custom anti-spam policy(ies) found where bulk complaint level threshold is set to 7 or more:" @@ -1100,12 +1087,13 @@ tests[{ #-- # Step 1: The default policy (SHALL) tests[{ - "Requirement" : "Spam SHALL be moved to either the junk email folder or the quarantine folder: default policy", - "Control" : "Defender 2.6", + #TODO: Multiple Mappings + #"Requirement" : "Spam SHALL be moved to either the junk email folder or the quarantine folder: default policy", + "PolicyId" : "MS.DEFENDER.6.2v1", "Criticality" : "Shall", "Commandlet" : ["Get-HostedContentFilterPolicy"], "ActualValue" : Policy.SpamAction, - "ReportDetails" : ReportDetails(Status), + "ReportDetails" : ReportDetailsBoolean(Status), "RequirementMet" : Status }] { Policy := input.hosted_content_filter_policies[_] @@ -1119,7 +1107,7 @@ tests[{ "Criticality" : "Shall", "Commandlet" : ["Get-HostedContentFilterPolicy"], "ActualValue" : Policy.HighConfidenceSpamAction, - "ReportDetails" : ReportDetails(Status), + "ReportDetails" : ReportDetailsBoolean(Status), "RequirementMet" : Status }] { Policy := input.hosted_content_filter_policies[_] @@ -1140,7 +1128,7 @@ tests[{ "Criticality" : "Should", "Commandlet" : ["Get-HostedContentFilterPolicy"], "ActualValue" : Policies, - "ReportDetails" : CustomizeError(ReportDetails(Status), GenerateArrayString(Policies, ErrorMessage)), + "ReportDetails" : CustomizeError(ReportDetailsBoolean(Status), GenerateArrayString(Policies, ErrorMessage)), "RequirementMet" : Status }] { ErrorMessage := "custom anti-spam policy(ies) found where spam is not being sent to the Quarantine folder or the Junk Mail Folder:" @@ -1160,7 +1148,7 @@ tests[{ "Criticality" : "Should", "Commandlet" : ["Get-HostedContentFilterPolicy"], "ActualValue" : Policies, - "ReportDetails" : CustomizeError(ReportDetails(Status), GenerateArrayString(Policies, ErrorMessage)), + "ReportDetails" : CustomizeError(ReportDetailsBoolean(Status), GenerateArrayString(Policies, ErrorMessage)), "RequirementMet" : Status }] { ErrorMessage := "custom anti-spam policy(ies) found where high confidence spam is not being sent to the Quarantine folder or the Junk Mail Folder:" @@ -1174,12 +1162,13 @@ tests[{ #-- # Step 1: The default policy (SHALL) tests[{ - "Requirement" : "Phishing SHALL be quarantined: default policy", - "Control" : "Defender 2.6", + #TODO: Multiple mappings + #"Requirement" : "Phishing SHALL be quarantined: default policy", + "PolicyId" : "MS.DEFENDER.6.3v1", "Criticality" : "Shall", "Commandlet" : ["Get-HostedContentFilterPolicy"], "ActualValue" : Policy.PhishSpamAction, - "ReportDetails" : ReportDetails(Status), + "ReportDetails" : ReportDetailsBoolean(Status), "RequirementMet" : Status }] { Policy := input.hosted_content_filter_policies[_] @@ -1193,7 +1182,7 @@ tests[{ "Criticality" : "Shall", "Commandlet" : ["Get-HostedContentFilterPolicy"], "ActualValue" : Policy.HighConfidencePhishAction, - "ReportDetails" : ReportDetails(Status), + "ReportDetails" : ReportDetailsBoolean(Status), "RequirementMet" : Status }] { Policy := input.hosted_content_filter_policies[_] @@ -1215,7 +1204,7 @@ tests[{ "Criticality" : "Should", "Commandlet" : ["Get-HostedContentFilterPolicy"], "ActualValue" : Policies, - "ReportDetails" : CustomizeError(ReportDetails(Status), GenerateArrayString(Policies, ErrorMessage)), + "ReportDetails" : CustomizeError(ReportDetailsBoolean(Status), GenerateArrayString(Policies, ErrorMessage)), "RequirementMet" : Status }] { ErrorMessage := "custom anti-spam policy(ies) found where phishing isn't moved to the quarantine folder:" @@ -1235,7 +1224,7 @@ tests[{ "Criticality" : "Should", "Commandlet" : ["Get-HostedContentFilterPolicy"], "ActualValue" : Policies, - "ReportDetails" : CustomizeError(ReportDetails(Status), GenerateArrayString(Policies, ErrorMessage)), + "ReportDetails" : CustomizeError(ReportDetailsBoolean(Status), GenerateArrayString(Policies, ErrorMessage)), "RequirementMet" : Status }] { ErrorMessage := "custom anti-spam policy(ies) found where high-confidence phishing isn't moved to quarantine folder:" @@ -1247,12 +1236,13 @@ tests[{ # Baseline 2.6: Policy 4 #-- tests[{ - "Requirement" : "Bulk email SHOULD be moved to either the junk email folder or the quarantine folder: default policy", - "Control" : "Defender 2.6", + #TODO: Multiple mappings + #"Requirement" : "Bulk email SHOULD be moved to either the junk email folder or the quarantine folder: default policy", + "PolicyId" : "MS.DEFENDER.6.4v1", "Criticality" : "Should", "Commandlet" : ["Get-HostedContentFilterPolicy"], "ActualValue" : Policy.BulkSpamAction, - "ReportDetails" : ReportDetails(Status), + "ReportDetails" : ReportDetailsBoolean(Status), "RequirementMet" : Status }] { Policy := input.hosted_content_filter_policies[_] @@ -1272,7 +1262,7 @@ tests[{ "Criticality" : "Should", "Commandlet" : ["Get-HostedContentFilterPolicy"], "ActualValue" : Policies, - "ReportDetails" : CustomizeError(ReportDetails(Status), GenerateArrayString(Policies, ErrorMessage)), + "ReportDetails" : CustomizeError(ReportDetailsBoolean(Status), GenerateArrayString(Policies, ErrorMessage)), "RequirementMet" : Status }] { ErrorMessage := "custom anti-spam policy(ies) found where bulk spam action is not Quarantine or Move to Junk Email Folder" @@ -1285,12 +1275,13 @@ tests[{ # Baseline 2.6: Policy 5 #-- tests[{ - "Requirement" : "Spam in quarantine SHOULD be retained for at least 30 days: default policy", - "Control" : "Defender 2.6", + #TODO: Multiple Mappings + #"Requirement" : "Spam in quarantine SHOULD be retained for at least 30 days: default policy", + "PolicyId" : "MS.DEFENDER.6.5v1", "Criticality" : "Should", "Commandlet" : ["Get-HostedContentFilterPolicy"], "ActualValue" : Policy.QuarantineRetentionPeriod, - "ReportDetails" : ReportDetails(Status), + "ReportDetails" : ReportDetailsBoolean(Status), "RequirementMet" : Status }] { Policy := input.hosted_content_filter_policies[_] @@ -1310,7 +1301,7 @@ tests[{ "Criticality" : "Should", "Commandlet" : ["Get-HostedContentFilterPolicy"], "ActualValue" : Policies, - "ReportDetails" : CustomizeError(ReportDetails(Status), GenerateArrayString(Policies, ErrorMessage)), + "ReportDetails" : CustomizeError(ReportDetailsBoolean(Status), GenerateArrayString(Policies, ErrorMessage)), "RequirementMet" : Status }] { ErrorMessage := "custom anti-spam policy(ies) found where spam in quarantine isn't retained for 30 days:" @@ -1323,12 +1314,13 @@ tests[{ # Baseline 2.6: Policy 6 #-- tests[{ - "Requirement" : "Spam safety tips SHOULD be turned on: default policy", - "Control" : "Defender 2.6", + #TODO: Multiple mappings + #"Requirement" : "Spam safety tips SHOULD be turned on: default policy", + "PolicyId" : "MS.DEFENDER.6.6v1", "Criticality" : "Should", "Commandlet" : ["Get-HostedContentFilterPolicy"], "ActualValue" : Policy.InlineSafetyTipsEnabled, - "ReportDetails" : ReportDetails(Status), + "ReportDetails" : ReportDetailsBoolean(Status), "RequirementMet" : Status }] { Policy := input.hosted_content_filter_policies[_] @@ -1348,7 +1340,7 @@ tests[{ "Criticality" : "Should", "Commandlet" : ["Get-HostedContentFilterPolicy"], "ActualValue" : Policies, - "ReportDetails" : CustomizeError(ReportDetails(Status), GenerateArrayString(Policies, ErrorMessage)), + "ReportDetails" : CustomizeError(ReportDetailsBoolean(Status), GenerateArrayString(Policies, ErrorMessage)), "RequirementMet" : Status }] { ErrorMessage := "custom anti-spam policy(ies) found where spam safety tips is disabled:" @@ -1362,12 +1354,13 @@ tests[{ #-- # Step 1: The default policy (SHALL) tests[{ - "Requirement" : "Zero-hour auto purge (ZAP) SHALL be enabled: default policy", - "Control" : "Defender 2.6", + #TODO: Multiple mappings + #"Requirement" : "Zero-hour auto purge (ZAP) SHALL be enabled: default policy", + "PolicyId" : "MS.DEFENDER.6.7v1", "Criticality" : "Shall", "Commandlet" : ["Get-HostedContentFilterPolicy"], "ActualValue" : Policy.ZapEnabled, - "ReportDetails" : ReportDetails(Status), + "ReportDetails" : ReportDetailsBoolean(Status), "RequirementMet" : Status }] { Policy := input.hosted_content_filter_policies[_] @@ -1381,7 +1374,7 @@ tests[{ "Criticality" : "Shall", "Commandlet" : ["Get-HostedContentFilterPolicy"], "ActualValue" : Policy.SpamZapEnabled, - "ReportDetails" : ReportDetails(Status), + "ReportDetails" : ReportDetailsBoolean(Status), "RequirementMet" : Status }] { Policy := input.hosted_content_filter_policies[_] @@ -1395,7 +1388,7 @@ tests[{ "Criticality" : "Shall", "Commandlet" : ["Get-HostedContentFilterPolicy"], "ActualValue" : Policy.PhishZapEnabled, - "ReportDetails" : ReportDetails(Status), + "ReportDetails" : ReportDetailsBoolean(Status), "RequirementMet" : Status }] { Policy := input.hosted_content_filter_policies[_] @@ -1416,7 +1409,7 @@ tests[{ "Criticality" : "Should", "Commandlet" : ["Get-HostedContentFilterPolicy"], "ActualValue" : Policies, - "ReportDetails" : CustomizeError(ReportDetails(Status), GenerateArrayString(Policies, ErrorMessage)), + "ReportDetails" : CustomizeError(ReportDetailsBoolean(Status), GenerateArrayString(Policies, ErrorMessage)), "RequirementMet" : Status }] { ErrorMessage := "custom anti-spam policies found where Zero-hour auto purge is disabled:" @@ -1436,7 +1429,7 @@ tests[{ "Criticality" : "Should", "Commandlet" : ["Get-HostedContentFilterPolicy"], "ActualValue" : Policies, - "ReportDetails" : CustomizeError(ReportDetails(Status), GenerateArrayString(Policies, ErrorMessage)), + "ReportDetails" : CustomizeError(ReportDetailsBoolean(Status), GenerateArrayString(Policies, ErrorMessage)), "RequirementMet" : Status }] { ErrorMessage := "custom anti-spam policies found where Zero-hour auto purge for spam is disabled:" @@ -1456,7 +1449,7 @@ tests[{ "Criticality" : "Should", "Commandlet" : ["Get-HostedContentFilterPolicy"], "ActualValue" : Policies, - "ReportDetails" : CustomizeError(ReportDetails(Status), GenerateArrayString(Policies, ErrorMessage)), + "ReportDetails" : CustomizeError(ReportDetailsBoolean(Status), GenerateArrayString(Policies, ErrorMessage)), "RequirementMet" : Status }] { ErrorMessage := "custom anti-spam policy(ies) found where Zero-hour auto purge for phishing is disabled:" @@ -1474,12 +1467,13 @@ AllowedSenderDomainsNotEmpty [Policy.Identity] { count(Policy.AllowedSenderDomains) > 0 } tests[{ - "Requirement" : "Allowed senders MAY be added but allowed domains SHALL NOT be added: default policy", - "Control" : "Defender 2.6", + #TODO: Multiple mappings + #"Requirement" : "Allowed senders MAY be added but allowed domains SHALL NOT be added: default policy", + "PolicyId" : "MS.DEFENDER.6.8v1", "Criticality" : "Shall", "Commandlet" : ["Get-HostedContentFilterPolicy"], "ActualValue" : Policies, - "ReportDetails" : CustomizeError(ReportDetails(Status), GenerateArrayString(Policies, ErrorMessage)), + "ReportDetails" : CustomizeError(ReportDetailsBoolean(Status), GenerateArrayString(Policies, ErrorMessage)), "RequirementMet" : Status }] { ErrorMessage := "custom anti-spam policy(ies) found where there is at least one allowed sender domain:" @@ -1498,7 +1492,7 @@ tests[{ "Criticality" : "Should", "Commandlet" : ["Get-HostedContentFilterPolicy"], "ActualValue" : Policies, - "ReportDetails" : CustomizeError(ReportDetails(Status), GenerateArrayString(Policies, ErrorMessage)), + "ReportDetails" : CustomizeError(ReportDetailsBoolean(Status), GenerateArrayString(Policies, ErrorMessage)), "RequirementMet" : Status }] { ErrorMessage := "custom policy(ies) found where there is at least one allowed sender domain:" @@ -1527,12 +1521,11 @@ AllDomainsSafeLinksPolicies[{ } tests[{ - "Requirement" : "The Safe Links Policy SHALL include all agency domains-and by extension-all users", - "Control" : "Defender 2.7", + "PolicyId" : "MS.DEFENDER.7.1v1", "Criticality" : "Shall", "Commandlet" : ["Get-SafeLinksRule", "Get-AcceptedDomain"], "ActualValue" : AllDomainsSafeLinksPolicies, - "ReportDetails" : ApplyLicenseWarning(CustomizeError(ReportDetails(Status), ErrorMessage)), + "ReportDetails" : ApplyLicenseWarning(CustomizeError(ReportDetailsBoolean(Status), ErrorMessage)), "RequirementMet" : Status }] { DomainNames := {Name.DomainName | Name = input.all_domains[_]} @@ -1554,12 +1547,11 @@ EnableSafeLinksForEmailCorrect[Policy.Identity] { } tests[{ - "Requirement" : "URL rewriting and malicious link click checking SHALL be enabled", - "Control" : "Defender 2.7", + "PolicyId" : "MS.DEFENDER.7.2v1", "Criticality" : "Shall", "Commandlet" : ["Get-SafeLinksPolicy", "Get-SafeLinksRule"], "ActualValue" : Policies, - "ReportDetails" : ApplyLicenseWarning(ReportDetails(Status)), + "ReportDetails" : ApplyLicenseWarning(ReportDetailsBoolean(Status)), "RequirementMet" : Status }] { Policies := EnableSafeLinksForEmailCorrect @@ -1580,12 +1572,11 @@ EnableSafeLinksForTeamsCorrect[Policy.Identity] { } tests[{ - "Requirement" : "Malicious link click checking SHALL be enabled with Microsoft Teams", - "Control" : "Defender 2.7", + "PolicyId" : "MS.DEFENDER.7.3v1", "Criticality" : "Shall", "Commandlet" : ["Get-SafeLinksPolicy", "Get-SafeLinksRule"], "ActualValue" : Policies, - "ReportDetails" : ApplyLicenseWarning(ReportDetails(Status)), + "ReportDetails" : ApplyLicenseWarning(ReportDetailsBoolean(Status)), "RequirementMet" : Status }] { Policies := EnableSafeLinksForTeamsCorrect @@ -1606,12 +1597,11 @@ ScanUrlsCorrect[Policy.Identity] { } tests[{ - "Requirement" : "Real-time suspicious URL and file-link scanning SHALL be enabled", - "Control" : "Defender 2.7", + "PolicyId" : "MS.DEFENDER.7.4v1", "Criticality" : "Shall", "Commandlet" : ["Get-SafeLinksPolicy", "Get-SafeLinksRule"], "ActualValue" : Policies, - "ReportDetails" : ApplyLicenseWarning(ReportDetails(Status)), + "ReportDetails" : ApplyLicenseWarning(ReportDetailsBoolean(Status)), "RequirementMet" : Status }] { Policies := ScanUrlsCorrect @@ -1632,12 +1622,11 @@ DeliverMessageAfterScanCorrect[Policy.Identity] { } tests[{ - "Requirement" : "URLs SHALL be scanned completely before message delivery", - "Control" : "Defender 2.7", + "PolicyId" : "MS.DEFENDER.7.5v1", "Criticality" : "Shall", "Commandlet" : ["Get-SafeLinksPolicy", "Get-SafeLinksRule"], "ActualValue" : Policies, - "ReportDetails" : ApplyLicenseWarning(ReportDetails(Status)), + "ReportDetails" : ApplyLicenseWarning(ReportDetailsBoolean(Status)), "RequirementMet" : Status }] { Policies := DeliverMessageAfterScanCorrect @@ -1658,12 +1647,11 @@ EnableForInternalSendersCorrect[Policy.Identity] { } tests[{ - "Requirement" : "Internal agency email messages SHALL have safe links enabled", - "Control" : "Defender 2.7", + "PolicyId" : "MS.DEFENDER.7.6v1", "Criticality" : "Shall", "Commandlet" : ["Get-SafeLinksPolicy", "Get-SafeLinksRule"], "ActualValue" : Policies, - "ReportDetails" : ApplyLicenseWarning(ReportDetails(Status)), + "ReportDetails" : ApplyLicenseWarning(ReportDetailsBoolean(Status)), "RequirementMet" : Status }] { Policies := EnableForInternalSendersCorrect @@ -1684,12 +1672,11 @@ TrackClicksCorrect[Policy.Identity] { } tests[{ - "Requirement" : "User click tracking SHALL be enabled", - "Control" : "Defender 2.7", + "PolicyId" : "MS.DEFENDER.7.7v1", "Criticality" : "Shall", "Commandlet" : ["Get-SafeLinksPolicy", "Get-SafeLinksRule"], "ActualValue" : Policies, - "ReportDetails" : ApplyLicenseWarning(ReportDetails(Status)), + "ReportDetails" : ApplyLicenseWarning(ReportDetailsBoolean(Status)), "RequirementMet" : Status }] { Policies := TrackClicksCorrect @@ -1709,12 +1696,11 @@ EnableSafeLinksForOfficeCorrect[Policy.Identity] { } tests[{ - "Requirement" : "Safe Links in Office 365 apps SHALL be turned on", - "Control" : "Defender 2.7", + "PolicyId" : "MS.DEFENDER.7.8v1", "Criticality" : "Shall", "Commandlet" : ["Get-SafeLinksPolicy", "Get-SafeLinksRule"], "ActualValue" : Policies, - "ReportDetails" : ApplyLicenseWarning(ReportDetails(Status)), + "ReportDetails" : ApplyLicenseWarning(ReportDetailsBoolean(Status)), "RequirementMet" : Status }] { Policies := EnableSafeLinksForOfficeCorrect @@ -1734,12 +1720,11 @@ AllowClickThroughCorrect[Policy.Identity] { } tests[{ - "Requirement" : "Users SHALL NOT be enabled to click through to the original URL", - "Control" : "Defender 2.7", + "PolicyId" : "MS.DEFENDER.7.9v1", "Criticality" : "Shall", "Commandlet" : ["Get-SafeLinksPolicy", "Get-SafeLinksRule"], "ActualValue" : Policies, - "ReportDetails" : ApplyLicenseWarning(ReportDetails(Status)), + "ReportDetails" : ApplyLicenseWarning(ReportDetailsBoolean(Status)), "RequirementMet" : Status }] { Policies := AllowClickThroughCorrect @@ -1767,12 +1752,11 @@ AllDomainsSafeAttachmentRules[{ } tests[{ - "Requirement" : "At least one Safe Attachments Policy SHALL include all agency domains-and by extension-all users", - "Control" : "Defender 2.8", + "PolicyId" : "MS.DEFENDER.8.1v1", "Criticality" : "Shall", "Commandlet" : ["Get-SafeAttachmentRule", "Get-AcceptedDomain"], "ActualValue" : AllDomainsSafeAttachmentRules, - "ReportDetails" : ApplyLicenseWarning(CustomizeError(ReportDetails(Status), ErrorMessage)), + "ReportDetails" : ApplyLicenseWarning(CustomizeError(ReportDetailsBoolean(Status), ErrorMessage)), "RequirementMet" : Status }] { DomainNames := {Name.DomainName | Name = input.all_domains[_]} @@ -1801,12 +1785,11 @@ BlockMalwarePolicies[{ } tests[{ - "Requirement" : "The action for malware in email attachments SHALL be set to block", - "Control" : "Defender 2.8", + "PolicyId" : "MS.DEFENDER.8.2v1", "Criticality" : "Shall", "Commandlet" : ["Get-SafeAttachmentPolicy", "Get-SafeAttachmentRule", "Get-AcceptedDomain"], "ActualValue" : Policies, - "ReportDetails" : ApplyLicenseWarning(CustomizeError(ReportDetails(Status), ErrorMessage)), + "ReportDetails" : ApplyLicenseWarning(CustomizeError(ReportDetailsBoolean(Status), ErrorMessage)), "RequirementMet" : Status }] { Policies := BlockMalwarePolicies @@ -1828,12 +1811,11 @@ RedirectionPolicies[{ } tests[{ - "Requirement" : "Redirect emails with detected attachments to an agency-specified email SHOULD be enabled", - "Control" : "Defender 2.8", + "PolicyId" : "MS.DEFENDER.8.3v1", "Criticality" : "Should", "Commandlet" : ["Get-SafeAttachmentPolicy", "Get-SafeAttachmentRule", "Get-AcceptedDomain"], "ActualValue" : Policies, - "ReportDetails" : ApplyLicenseWarning(CustomizeError(ReportDetails(Status), ErrorMessage)), + "ReportDetails" : ApplyLicenseWarning(CustomizeError(ReportDetailsBoolean(Status), ErrorMessage)), "RequirementMet" : Status }] { Policies := RedirectionPolicies @@ -1854,12 +1836,11 @@ ATPPolicies[{ } tests[{ - "Requirement" : "Safe attachments SHOULD be enabled for SharePoint, OneDrive, and Microsoft Teams", - "Control" : "Defender 2.8", + "PolicyId" : "MS.DEFENDER.8.4v1", "Criticality" : "Should", "Commandlet" : ["Get-AtpPolicyForO365"], "ActualValue" : Policies, - "ReportDetails" : ApplyLicenseWarning(ReportDetails(Status)), + "ReportDetails" : ApplyLicenseWarning(ReportDetailsBoolean(Status)), "RequirementMet" : Status }] { Policies := ATPPolicies @@ -1894,12 +1875,11 @@ EnabledAlerts[Alert.Name] { } tests[{ - "Requirement" : "At a minimum, the alerts required by the Exchange Online Minimum Viable Secure Configuration Baseline SHALL be enabled", - "Control" : "Defender 2.9", + "PolicyId" : "MS.DEFENDER.9.1v1", "Criticality" : "Shall", "Commandlet" : ["Get-ProtectionAlert"], "ActualValue" : MissingAlerts, - "ReportDetails" : CustomizeError(ReportDetails(Status), GenerateArrayString(MissingAlerts, ErrorMessage)), + "ReportDetails" : CustomizeError(ReportDetailsBoolean(Status), GenerateArrayString(MissingAlerts, ErrorMessage)), "RequirementMet" : Status }] { MissingAlerts := RequiredAlerts - EnabledAlerts @@ -1913,14 +1893,14 @@ tests[{ #-- # SIEM incorporation cannot be checked programmatically tests[{ - "Requirement" : "The alerts SHOULD be sent to a monitored address or incorporated into a SIEM", - "Control" : "Defender 2.9", + "PolicyId" : PolicyId, "Criticality" : "Should/Not-Implemented", "Commandlet" : [], "ActualValue" : [], - "ReportDetails" : "Currently cannot be checked automatically. See Defender Secure Configuration Baseline policy 2.9 for instructions on manual check", + "ReportDetails" : NotCheckedDetails(PolicyId), "RequirementMet" : false }] { + PolicyId := "MS.DEFENDER.9.2v1" true } #-- @@ -1942,12 +1922,11 @@ CorrectLogConfigs[{ # Baseline 2.10: Policy 1 #-- tests[{ - "Requirement" : "Unified audit logging SHALL be enabled", - "Control" : "Defender 2.10", + "PolicyId" : "MS.DEFENDER.10.1v1", "Criticality" : "Shall", "Commandlet" : ["Get-AdminAuditLogConfig"], "ActualValue" : CorrectLogConfigs, - "ReportDetails" : ReportDetails(Status), + "ReportDetails" : ReportDetailsBoolean(Status), "RequirementMet" : Status }] { Status := count(CorrectLogConfigs) >= 1 @@ -1961,14 +1940,14 @@ tests[{ # Would require looping through all users. See discussion in GitHub # issue #200. tests[{ - "Requirement" : "Advanced audit SHALL be enabled", - "Control" : "Defender 2.10", + "PolicyId" : PolicyId, "Criticality" : "Shall/Not-Implemented", "Commandlet" : [], "ActualValue" : [], - "ReportDetails" : "Currently cannot be checked automatically. See Defender Secure Configuration Baseline policy 2.10 for instructions on manual check", + "ReportDetails" : NotCheckedDetails(PolicyId), "RequirementMet" : false }] { + PolicyId := "MS.DEFENDER.10.2v1" true } #-- @@ -1980,14 +1959,14 @@ tests[{ # It is not required to maintain these logs in the M365 cloud environment; doing so would require an additional add-on SKU. # This requirement can be met by offloading the logs out of the cloud environment. tests[{ - "Requirement" : "Audit logs SHALL be maintained for at least the minimum duration dictated by OMB M-21-31", - "Control" : "Defender 2.10", + "PolicyId" : PolicyId, "Criticality" : "Shall/Not-Implemented", "Commandlet" : [], "ActualValue" : [], - "ReportDetails" : "Currently cannot be checked automatically. See Defender Secure Configuration Baseline policy 2.10 for instructions on manual check", + "ReportDetails" : NotCheckedDetails(PolicyId), "RequirementMet" : false }] { + PolicyId := "MS.DEFENDER.10.3v1" true } #-- diff --git a/Rego/EXOConfig.rego b/Rego/EXOConfig.rego index a2b5a0dd57..c1655d224e 100644 --- a/Rego/EXOConfig.rego +++ b/Rego/EXOConfig.rego @@ -1,13 +1,10 @@ package exo import future.keywords - -Format(Array) = format_int(count(Array), 10) - -Description(String1, String2, String3) = trim(concat(" ", [String1, concat(" ", [String2, String3])]), " ") - -ReportDetailsBoolean(Status) = "Requirement met" if {Status == true} - -ReportDetailsBoolean(Status) = "Requirement not met" if {Status == false} +import data.report.utils.NotCheckedDetails +import data.report.utils.Format +import data.report.utils.ReportDetailsBoolean +import data.report.utils.Description +import data.report.utils.ReportDetailsString ReportDetailsArray(Status, Array1, Array2) = Detail if { Status == true @@ -21,16 +18,6 @@ ReportDetailsArray(Status, Array1, Array2) = Detail if { Detail := Description(Fraction, "agency domain(s) found in violation:", String) } -ReportDetailsString(Status, String) = Detail if { - Status == true - Detail := "Requirement met" -} - -ReportDetailsString(Status, String) = Detail if { - Status == false - Detail := String -} - AllDomains := {Domain.domain | Domain = input.spf_records[_]} CustomDomains[Domain.domain] { @@ -39,12 +26,8 @@ CustomDomains[Domain.domain] { } -################ -# Baseline 2.1 # -################ - # -# Baseline 2.1: Policy 1 +# MS.EXO.1.1v1 #-- RemoteDomainsAllowingForwarding[Domain.DomainName] { Domain := input.remote_domains[_] @@ -52,8 +35,7 @@ RemoteDomainsAllowingForwarding[Domain.DomainName] { } tests[{ - "Requirement" : "Automatic forwarding to external domains SHALL be disabled", - "Control" : "EXO 2.1", + "PolicyId" : "MS.EXO.1.1v1", "Criticality" : "Shall", "Commandlet" : ["Get-RemoteDomain"], "ActualValue" : Domains, @@ -66,30 +48,25 @@ tests[{ } #-- - -################ -# Baseline 2.2 # -################ - # -# Baseline 2.2: Policy 1 +# MS.EXO.2.1v1 #-- # At this time we are unable to test for X because of Y tests[{ - "Requirement" : "A list of approved IP addresses for sending mail SHALL be maintained", - "Control" : "EXO 2.2", + "PolicyId" : PolicyId, "Criticality" : "Shall/Not-Implemented", "Commandlet" : [], "ActualValue" : [], - "ReportDetails" : "Currently cannot be checked automatically. See Exchange Online Secure Configuration Baseline policy 2.# for instructions on manual check", + "ReportDetails" : NotCheckedDetails(PolicyId), "RequirementMet" : false }] { + PolicyId := "MS.EXO.2.1v1" true } #-- # -# Baseline 2.2: Policy 2 +# MS.EXO.2.2v1 #-- DomainsWithoutSpf[DNSResponse.domain] { DNSResponse := input.spf_records[_] @@ -98,8 +75,7 @@ DomainsWithoutSpf[DNSResponse.domain] { } tests[{ - "Requirement" : "An SPF policy(s) that designates only these addresses as approved senders SHALL be published", - "Control" : "EXO 2.2", + "PolicyId" : "MS.EXO.2.2v1", "Criticality" : "Shall", "Commandlet" : ["Get-ScubaSpfRecords", "Get-AcceptedDomain"], "ActualValue" : Domains, @@ -111,13 +87,8 @@ tests[{ } #-- - -################ -# Baseline 2.3 # -################ - # -# Baseline 2.3: Policy 1 +# MS.EXO.3.1v1 #-- DomainsWithDkim[DkimConfig.Domain] { DkimConfig := input.dkim_config[_] @@ -129,8 +100,7 @@ DomainsWithDkim[DkimConfig.Domain] { } tests[{ - "Requirement" : "DKIM SHOULD be enabled for any custom domain", - "Control" : "EXO 2.3", + "PolicyId" : "MS.EXO.3.1v1", "Criticality" : "Should", "Commandlet" : ["Get-DkimSigningConfig", "Get-ScubaDkimRecords", "Get-AcceptedDomain"], "ActualValue" : [input.dkim_records, input.dkim_config], @@ -142,13 +112,8 @@ tests[{ } #-- - -################ -# Baseline 2.4 # -################ - # -# Baseline 2.4: Policy 1 +# MS.EXO.4.1v1 #-- DomainsWithoutDmarc[DmarcRecord.domain] { DmarcRecord := input.dmarc_records[_] @@ -157,8 +122,7 @@ DomainsWithoutDmarc[DmarcRecord.domain] { } tests[{ - "Requirement" : "A DMARC policy SHALL be published for every second-level domain", - "Control" : "EXO 2.4", + "PolicyId" : "MS.EXO.4.1v1", "Criticality" : "Shall", "Commandlet" : ["Get-ScubaDmarcRecords", "Get-AcceptedDomain"], "ActualValue" : input.dmarc_records, @@ -171,7 +135,7 @@ tests[{ #-- # -# Baseline 2.4: Policy 2 +# MS.EXO.4.2v1 #-- DomainsWithoutPreject[DmarcRecord.domain] { DmarcRecord := input.dmarc_records[_] @@ -180,8 +144,7 @@ DomainsWithoutPreject[DmarcRecord.domain] { } tests[{ - "Requirement" : "The DMARC message rejection option SHALL be \"p=reject\"", - "Control" : "EXO 2.4", + "PolicyId" : "MS.EXO.4.2v1", "Criticality" : "Shall", "Commandlet" : ["Get-ScubaDmarcRecords", "Get-AcceptedDomain"], "ActualValue" : input.dmarc_records, @@ -194,7 +157,7 @@ tests[{ #-- # -# Baseline 2.4: Policy 3 +# MS.EXO.4.3v1 #-- DomainsWithoutDHSContact[DmarcRecord.domain] { DmarcRecord := input.dmarc_records[_] @@ -203,8 +166,7 @@ DomainsWithoutDHSContact[DmarcRecord.domain] { } tests[{ - "Requirement" : "The DMARC point of contact for aggregate reports SHALL include reports@dmarc.cyber.dhs.gov", - "Control" : "EXO 2.4", + "PolicyId" : "MS.EXO.4.3v1", "Criticality" : "Shall", "Commandlet" : ["Get-ScubaDmarcRecords", "Get-AcceptedDomain"], "ActualValue" : input.dmarc_records, @@ -217,7 +179,7 @@ tests[{ #-- # -# Baseline 2.4: Policy 4 +# MS.EXO.4.4v1 #-- DomainsWithoutAgencyContact[DmarcRecord.domain] { DmarcRecord := input.dmarc_records[_] @@ -226,8 +188,7 @@ DomainsWithoutAgencyContact[DmarcRecord.domain] { } tests[{ - "Requirement" : "An agency point of contact SHOULD be included for aggregate and/or failure reports", - "Control" : "EXO 2.4", + "PolicyId" : "MS.EXO.4.4v1", "Criticality" : "Should", "Commandlet" : ["Get-ScubaDmarcRecords", "Get-AcceptedDomain"], "ActualValue" : input.dmarc_records, @@ -239,13 +200,8 @@ tests[{ } #-- - -################ -# Baseline 2.5 # -################ - # -# Baseline 2.5: Policy 1 +# MS.EXO.5.1v1 #-- SmtpClientAuthEnabled[TransportConfig.Name] { @@ -254,8 +210,7 @@ SmtpClientAuthEnabled[TransportConfig.Name] { } tests[{ - "Requirement" : "SMTP AUTH SHALL be disabled in Exchange Online", - "Control" : "EXO 2.5", + "PolicyId" : "MS.EXO.5.1v1", "Criticality" : "Shall", "Commandlet" : ["Get-TransportConfig"], "ActualValue" : input.transport_config, @@ -266,15 +221,10 @@ tests[{ } #-- - -################ -# Baseline 2.6 # -################ - # Are both the tests supposed to be the same? # -# Baseline 2.6: Policy 1 +# MS.EXO.6.1v1 #-- SharingPolicyAllowedSharing[SharingPolicy.Name] { @@ -285,8 +235,7 @@ SharingPolicyAllowedSharing[SharingPolicy.Name] { tests[{ - "Requirement" : "Contact folders SHALL NOT be shared with all domains, although they MAY be shared with specific domains", - "Control" : "EXO 2.6", + "PolicyId" : "MS.EXO.6.1v1", "Criticality" : "Shall", "Commandlet" : ["Get-SharingPolicy"], "ActualValue" : input.sharing_policy, @@ -300,12 +249,11 @@ tests[{ #-- # -# Baseline 2.6: Policy 2 +# MS.EXO.6.2v1 #-- tests[{ - "Requirement" : "Calendar details SHALL NOT be shared with all domains, although they MAY be shared with specific domains", - "Control" : "EXO 2.6", + "PolicyId" : "MS.EXO.6.2v1", "Criticality" : "Shall", "Commandlet" : ["Get-SharingPolicy"], "ActualValue" : input.sharing_policy, @@ -317,16 +265,11 @@ tests[{ } #-- - -################ -# Baseline 2.7 # -################ # -# Baseline 2.7: Policy 1 +# MS.EXO.7.1v1 #-- tests[{ - "Requirement" : "External sender warnings SHALL be implemented", - "Control" : "EXO 2.7", + "PolicyId" : "MS.EXO.7.1v1", "Criticality" : "Shall", "Commandlet" : ["Get-TransportRule"], "ActualValue" : [Rule.FromScope | Rule = Rules[_]], @@ -341,18 +284,12 @@ tests[{ } #-- - -################ -# Baseline 2.8 # -################ - # -# Baseline 2.8: Policy 1 +# MS.EXO.8.1v1 #-- # At this time we are unable to test because settings are configured in M365 Defender or using a third-party app tests[{ - "Requirement" : "A DLP solution SHALL be used. The selected DLP solution SHOULD offer services comparable to the native DLP solution offered by Microsoft", - "Control" : "EXO 2.8", + "PolicyId" : "MS.EXO.8.1v1", "Criticality" : "Shall/3rd Party", "Commandlet" : [], "ActualValue" : [], @@ -364,12 +301,11 @@ tests[{ #-- # -# Baseline 2.8: Policy 2 +# MS.EXO.8.2v1 #-- # At this time we are unable to test because settings are configured in M365 Defender or using a third-party app tests[{ - "Requirement" : "The DLP solution SHALL protect PII and sensitive information, as defined by the agency. At a minimum, the sharing of credit card numbers, Taxpayer Identification Numbers (TIN), and Social Security Numbers (SSN) via email SHALL be restricted", - "Control" : "EXO 2.8", + "PolicyId" : "MS.EXO.8.2v1", "Criticality" : "Shall/3rd Party", "Commandlet" : [], "ActualValue" : [], @@ -380,18 +316,12 @@ tests[{ } #-- - -################ -# Baseline 2.9 # -################ - # -# Baseline 2.9: Policy 1 +# MS.EXO.9.1v1 #-- # At this time we are unable to test because settings are configured in M365 Defender or using a third-party app tests[{ - "Requirement" : "Emails SHALL be filtered by the file types of included attachments. The selected filtering solution SHOULD offer services comparable to Microsoft Defender's Common Attachment Filter", - "Control" : "EXO 2.9", + "PolicyId" : "MS.EXO.9.1v1", "Criticality" : "Shall/3rd Party", "Commandlet" : [], "ActualValue" : [], @@ -403,12 +333,11 @@ tests[{ #-- # -# Baseline 2.9: Policy 2 +# MS.EXO.9.2v1 #-- # At this time we are unable to test because settings are configured in M365 Defender or using a third-party app tests[{ - "Requirement" : "The attachment filter SHOULD attempt to determine the true file type and assess the file extension", - "Control" : "EXO 2.9", + "PolicyId" : "MS.EXO.9.2v1", "Criticality" : "Should/3rd Party", "Commandlet" : [], "ActualValue" : [], @@ -420,12 +349,11 @@ tests[{ #-- # -# Baseline 2.9: Policy 3 +# MS.EXO.9.3v1 #-- # At this time we are unable to test because settings are configured in M365 Defender or using a third-party app tests[{ - "Requirement" : "Disallowed file types SHALL be determined and set. At a minimum, click-to-run files SHOULD be blocked (e.g., .exe, .cmd, and .vbe)", - "Control" : "EXO 2.9", + "PolicyId" : "MS.EXO.9.3v1", "Criticality" : "Shall/3rd Party", "Commandlet" : [], "ActualValue" : [], @@ -436,18 +364,12 @@ tests[{ } #-- - -################# -# Baseline 2.10 # -################# - # -# Baseline 2.10: Policy 1 +# MS.EXO.10.1v1 #-- # At this time we are unable to test because settings are configured in M365 Defender or using a third-party app tests[{ - "Requirement" : "Emails SHALL be scanned for malware", - "Control" : "EXO 2.10", + "PolicyId" : "MS.EXO.10.1v1", "Criticality" : "Shall/3rd Party", "Commandlet" : [], "ActualValue" : [], @@ -459,12 +381,11 @@ tests[{ #-- # -# Baseline 2.10: Policy 2 +# MS.EXO.10.2v1 #-- # At this time we are unable to test because settings are configured in M365 Defender or using a third-party app tests[{ - "Requirement" : "Emails identified as containing malware SHALL be quarantined or dropped", - "Control" : "EXO 2.10", + "PolicyId" : "MS.EXO.10.2v1", "Criticality" : "Shall/3rd Party", "Commandlet" : [], "ActualValue" : [], @@ -476,12 +397,11 @@ tests[{ #-- # -# Baseline 2.10: Policy 3 +# MS.EXO.10.3v1 #-- # At this time we are unable to test because settings are configured in M365 Defender or using a third-party app tests[{ - "Requirement" : "Email scanning SHOULD be capable of reviewing emails after delivery", - "Control" : "EXO 2.10", + "PolicyId" : "MS.EXO.10.3v1", "Criticality" : "Should/3rd Party", "Commandlet" : [], "ActualValue" : [], @@ -492,18 +412,12 @@ tests[{ } #-- - -################# -# Baseline 2.11 # -################# - # -# Baseline 2.11: Policy 1 +# MS.EXO.11.1v1 #-- # At this time we are unable to test because settings are configured in M365 Defender or using a third-party app tests[{ - "Requirement" : "Impersonation protection checks SHOULD be used", - "Control" : "EXO 2.11", + "PolicyId" : "MS.EXO.11.1v1", "Criticality" : "Should/3rd Party", "Commandlet" : [], "ActualValue" : [], @@ -515,12 +429,11 @@ tests[{ #-- # -# Baseline 2.11: Policy 2 +# MS.EXO.11.2v1 #-- # At this time we are unable to test because settings are configured in M365 Defender or using a third-party app tests[{ - "Requirement" : "User warnings, comparable to the user safety tips included with EOP, SHOULD be displayed", - "Control" : "EXO 2.11", + "PolicyId" : "MS.EXO.11.2v1", "Criticality" : "Should/3rd Party", "Commandlet" : [], "ActualValue" : [], @@ -532,12 +445,11 @@ tests[{ #-- # -# Baseline 2.11: Policy 3 +# MS.EXO.11.3v1 #-- # At this time we are unable to test because settings are configured in M365 Defender or using a third-party app tests[{ - "Requirement" : "The phishing protection solution SHOULD include an AI-based phishing detection tool comparable to EOP Mailbox Intelligence", - "Control" : "EXO 2.11", + "PolicyId" : "MS.EXO.11.3v1", "Criticality" : "Should/3rd Party", "Commandlet" : [], "ActualValue" : [], @@ -548,13 +460,8 @@ tests[{ } #-- - -################# -# Baseline 2.12 # -################# - # -# Baseline 2.12: Policy 1 +# MS.EXO.12.1v1 #-- ConnFiltersWithIPAllowList[ConnFilter.Name] { @@ -563,8 +470,7 @@ ConnFiltersWithIPAllowList[ConnFilter.Name] { } tests[{ - "Requirement" : "IP allow lists SHOULD NOT be created", - "Control" : "EXO 2.12", + "PolicyId" : "MS.EXO.12.1v1", "Criticality" : "Should", "Commandlet" : ["Get-HostedConnectionFilterPolicy"], "ActualValue" : input.conn_filter, @@ -577,7 +483,7 @@ tests[{ #-- # -# Baseline 2.12: Policy 2 +# MS.EXO.12.2v1 #-- ConnFiltersWithSafeList[ConnFilter.Name] { @@ -586,8 +492,7 @@ ConnFiltersWithSafeList[ConnFilter.Name] { } tests[{ - "Requirement" : "Safe lists SHOULD NOT be enabled", - "Control" : "EXO 2.12", + "PolicyId" : "MS.EXO.12.2v1", "Criticality" : "Should", "Commandlet" : ["Get-HostedConnectionFilterPolicy"], "ActualValue" : input.conn_filter, @@ -598,13 +503,8 @@ tests[{ } #-- - -################# -# Baseline 2.13 # -################# - # -# Baseline 2.13: Policy 1 +# MS.EXO.13.1v1 #-- AuditEnabled[OrgConfig.Name] { OrgConfig := input.org_config[_] @@ -612,8 +512,7 @@ AuditEnabled[OrgConfig.Name] { } tests[{ - "Requirement" : "Mailbox auditing SHALL be enabled", - "Control" : "EXO 2.13", + "PolicyId" : "MS.EXO.13.1v1", "Criticality" : "Shall", "Commandlet" : ["Get-OrganizationConfig"], "ActualValue" : input.org_config, @@ -624,18 +523,12 @@ tests[{ } #-- - -################# -# Baseline 2.14 # -################# - # -# Baseline 2.14: Policy 1 +# MS.EXO.14.1v1 #-- # At this time we are unable to test because settings are configured in M365 Defender or using a third-party app tests[{ - "Requirement" : "A spam filter SHALL be enabled. The filtering solution selected SHOULD offer services comparable to the native spam filtering offered by Microsoft", - "Control" : "EXO 2.14", + "PolicyId" : "MS.EXO.14.1v1", "Criticality" : "Shall/3rd Party", "Commandlet" : [], "ActualValue" : [], @@ -647,12 +540,11 @@ tests[{ #-- # -# Baseline 2.14: Policy 2 +# MS.EXO.14.2v1 #-- # At this time we are unable to test because settings are configured in M365 Defender or using a third-party app tests[{ - "Requirement" : "Spam and high confidence spam SHALL be moved to either the junk email folder or the quarantine folder", - "Control" : "EXO 2.14", + "PolicyId" : "MS.EXO.14.2v1", "Criticality" : "Shall/3rd Party", "Commandlet" : [], "ActualValue" : [], @@ -664,12 +556,11 @@ tests[{ #-- # -# Baseline 2.14: Policy 3 +# MS.EXO.14.3v1 #-- # At this time we are unable to test because settings are configured in M365 Defender or using a third-party app tests[{ - "Requirement" : "Allowed senders MAY be added, but allowed domains SHALL NOT be added", - "Control" : "EXO 2.14", + "PolicyId" : "MS.EXO.14.3v1", "Criticality" : "Shall/3rd Party", "Commandlet" : [], "ActualValue" : [], @@ -680,18 +571,12 @@ tests[{ } #-- - -################# -# Baseline 2.15 # -################# - # -# Baseline 2.15: Policy 1 +# MS.EXO.15.1v1 #-- # At this time we are unable to test because settings are configured in M365 Defender or using a third-party app tests[{ - "Requirement" : "URL comparison with a block-list SHOULD be enabled", - "Control" : "EXO 2.15", + "PolicyId" : "MS.EXO.15.1v1", "Criticality" : "Should/3rd Party", "Commandlet" : [], "ActualValue" : [], @@ -703,12 +588,11 @@ tests[{ #-- # -# Baseline 2.15: Policy 2 +# MS.EXO.15.2v1 #-- # At this time we are unable to test because settings are configured in M365 Defender or using a third-party app tests[{ - "Requirement" : "Direct download links SHOULD be scanned for malware", - "Control" : "EXO 2.15", + "PolicyId" : "MS.EXO.15.2v1", "Criticality" : "Should/3rd Party", "Commandlet" : [], "ActualValue" : [], @@ -720,12 +604,11 @@ tests[{ #-- # -# Baseline 2.15: Policy 3 +# MS.EXO.15.3v1 #-- # At this time we are unable to test because settings are configured in M365 Defender or using a third-party app tests[{ - "Requirement" : "User click tracking SHOULD be enabled", - "Control" : "EXO 2.15", + "PolicyId" : "MS.EXO.15.3v1", "Criticality" : "Should/3rd Party", "Commandlet" : [], "ActualValue" : [], @@ -736,18 +619,12 @@ tests[{ } #-- - -################# -# Baseline 2.16 # -################# - # -# Baseline 2.16: Policy 1 +# MS.EXO.16.1v1 #-- # At this time we are unable to test because settings are configured in M365 Defender or using a third-party app tests[{ - "Requirement" : "At a minimum, the following alerts SHALL be enabled...[see Exchange Online secure baseline for list]", - "Control" : "EXO 2.16", + "PolicyId" : "MS.EXO.16.1v1", "Criticality" : "Shall/3rd Party", "Commandlet" : [], "ActualValue" : [], @@ -759,12 +636,11 @@ tests[{ #-- # -# Baseline 2.16: Policy 2 +# MS.EXO.16.2v1 #-- # At this time we are unable to test because settings are configured in M365 Defender or using a third-party app tests[{ - "Requirement" : "The alerts SHOULD be sent to a monitored address or incorporated into a SIEM", - "Control" : "EXO 2.16", + "PolicyId" : "MS.EXO.16.2v1", "Criticality" : "Should/3rd Party", "Commandlet" : [], "ActualValue" : [], @@ -775,18 +651,12 @@ tests[{ } #-- - -################# -# Baseline 2.17 # -################# - # -# Baseline 2.17: Policy 1 +# MS.EXO.17.1v1 #-- # At this time we are unable to test because settings are configured in M365 Defender or using a third-party app tests[{ - "Requirement" : "Unified audit logging SHALL be enabled", - "Control" : "EXO 2.17", + "PolicyId" : "MS.EXO.17.1v1", "Criticality" : "Shall/3rd Party", "Commandlet" : [], "ActualValue" : [], @@ -798,12 +668,11 @@ tests[{ #-- # -# Baseline 2.17: Policy 2 +# MS.EXO.17.2v1 #-- # At this time we are unable to test because settings are configured in M365 Defender or using a third-party app tests[{ - "Requirement" : "Advanced audit SHALL be enabled", - "Control" : "EXO 2.17", + "PolicyId" : "MS.EXO.17.2v1", "Criticality" : "Shall/3rd Party", "Commandlet" : [], "ActualValue" : [], @@ -815,12 +684,11 @@ tests[{ #-- # -# Baseline 2.17: Policy 3 +# MS.EXO.17.3v1 #-- # At this time we are unable to test because settings are configured in M365 Defender or using a third-party app tests[{ - "Requirement" : "Audit logs SHALL be maintained for at least the minimum duration dictated by OMB M-21-31", - "Control" : "EXO 2.17", + "PolicyId" : "MS.EXO.17.3v1", "Criticality" : "Shall/3rd Party", "Commandlet" : [], "ActualValue" : [], diff --git a/Rego/OneDriveConfig.rego b/Rego/OneDriveConfig.rego index 46511e2fdc..59172e940d 100644 --- a/Rego/OneDriveConfig.rego +++ b/Rego/OneDriveConfig.rego @@ -1,17 +1,11 @@ package onedrive import future.keywords +import data.report.utils.NotCheckedDetails +import data.report.utils.ReportDetailsBoolean -ReportDetailsBoolean(Status) = "Requirement met" if {Status == true} - -ReportDetailsBoolean(Status) = "Requirement not met" if {Status == false} - - -################ -# Baseline 2.1 # -################ - +#-- # -# Baseline 2.1: Policy 1 +# MS.ONEDRIVE.1.1v1 #-- AnyoneLinksPolicy[Policy]{ Policy := input.SPO_tenant_info[_] @@ -19,8 +13,7 @@ AnyoneLinksPolicy[Policy]{ } tests[{ - "Requirement" : "Anyone links SHOULD be disabled", - "Control" : "OneDrive 2.1", + "PolicyId" : "MS.ONEDRIVE.1.1v1", "Criticality" : "Should", "Commandlet" : ["Get-SPOTenant", "Get-PnPTenant"], "ActualValue" : Policies, @@ -34,25 +27,20 @@ tests[{ #-- tests[{ - "Requirement" : "Anyone links SHOULD be disabled", - "Control" : "OneDrive 2.1", + "PolicyId" : PolicyId, "Criticality" : "Should/Not-Implemented", "Commandlet" : [], "ActualValue" : [], - "ReportDetails" : "Currently cannot be checked automatically while using Service Principals. See Onedrive Secure Configuration Baseline policy 2.1 for instructions on manual check", + "ReportDetails" : NotCheckedDetails(PolicyId), "RequirementMet" : false }] { + PolicyId := "MS.ONEDRIVE.1.1v1" input.OneDrive_PnP_Flag } #-- - -################ -# Baseline 2.2 # -################ - # -# Baseline 2.2: Policy 1 +# MS.ONEDRIVE.2.1v1 #-- ReportDetails2_2(Policy) = Description if { Policy.OneDriveSharingCapability != 2 @@ -72,8 +60,7 @@ ReportDetails2_2(Policy) = Description if { } tests[{ - "Requirement" : "An expiration date SHOULD be set for Anyone links", - "Control" : "OneDrive 2.2", + "PolicyId" : "MS.ONEDRIVE.2.1v1", "Criticality" : "Should", "Commandlet" : ["Get-SPOTenant", "Get-PnPTenant"], "ActualValue" : [Policy.OneDriveSharingCapability, Policy.RequireAnonymousLinksExpireInDays], @@ -90,25 +77,36 @@ tests[{ } tests[{ - "Requirement" : "An expiration date SHOULD be set for Anyone links", - "Control" : "OneDrive 2.2", + "PolicyId" : PolicyId, "Criticality" : "Should/Not-Implemented", "Commandlet" : [], "ActualValue" : [], - "ReportDetails" : "Currently cannot be checked automatically while using Service Principals. See Onedrive Secure Configuration Baseline policy 2.2 for instructions on manual check", + "ReportDetails" : NotCheckedDetails(PolicyId), "RequirementMet" : false }] { + PolicyId := "MS.ONEDRIVE.2.1v1" input.OneDrive_PnP_Flag } #-- - -################ -# Baseline 2.3 # -################ +# +# MS.ONEDRIVE.2.2v1 +#-- +tests[{ + "PolicyId" : PolicyId, + "Criticality" : "Should/Not-Implemented", + "Commandlet" : [], + "ActualValue" : [], + "ReportDetails" : NotCheckedDetails(PolicyId), + "RequirementMet" : false +}] { + PolicyId := "MS.ONEDRIVE.2.2v1" + input.OneDrive_PnP_Flag +} +#-- # -# Baseline 2.3: Policy 1 +# MS.ONEDRIVE.3.1v1 #-- ReportDetails2_3(Policy) = Description if { Policy.OneDriveSharingCapability != 2 @@ -144,8 +142,7 @@ ReportDetails2_3(Policy) = Description if { } tests[{ - "Requirement" : "Anyone link permissions SHOULD be limited to View", - "Control" : "OneDrive 2.3", + "PolicyId" : "MS.ONEDRIVE.3.1v1", "Criticality" : "Should", "Commandlet" : ["Get-SPOTenant", "Get-PnPTenant"], "ActualValue" : [Policy.OneDriveSharingCapability, Policy.FileAnonymousLinkType, Policy.FolderAnonymousLinkType], @@ -162,25 +159,20 @@ tests[{ } tests[{ - "Requirement" : "Anyone link permissions SHOULD be limited to View", - "Control" : "OneDrive 2.3", + "PolicyId" : PolicyId, "Criticality" : "Should/Not-Implemented", "Commandlet" : [], "ActualValue" : [], - "ReportDetails" : "Currently cannot be checked automatically while using Service Principals. See Onedrive Secure Configuration Baseline policy 2.3 for instructions on manual check", + "ReportDetails" : NotCheckedDetails(PolicyId), "RequirementMet" : false }] { + PolicyId := "MS.ONEDRIVE.3.1v1" input.OneDrive_PnP_Flag } #-- - -################ -# Baseline 2.4 # -################ - # -# Baseline 2.4: Policy 1 +# MS.ONEDRIVE.4.1v1 #-- DefinedDomainsPolicy[Policy]{ Policy := input.Tenant_sync_info[_] @@ -188,8 +180,7 @@ DefinedDomainsPolicy[Policy]{ } tests[{ - "Requirement" : "OneDrive Client for Windows SHALL be restricted to agency-Defined Domain(s)", - "Control" : "OneDrive 2.4", + "PolicyId" : "MS.ONEDRIVE.4.1v1", "Criticality" : "Shall", "Commandlet" : ["Get-SPOTenant", "Get-PnPTenant"], "ActualValue" : Policies, @@ -201,13 +192,8 @@ tests[{ } #-- - -################ -# Baseline 2.5 # -################ - # -# Baseline 2.5: Policy 1 +# MS.ONEDRIVE.5.1v1 #-- ClientSyncPolicy[Policy]{ Policy := input.Tenant_sync_info[_] @@ -216,7 +202,7 @@ ClientSyncPolicy[Policy]{ tests[{ "Requirement" : "OneDrive Client Sync SHALL only be allowed only within the local domain", - "Control" : "OneDrive 2.5", + "PolicyId" : "MS.ONEDRIVE.5.1v1", "Criticality" : "Shall", "Commandlet" : ["Get-SPOTenantSyncClientRestriction", "Get-PnPTenantSyncClientRestriction"], "ActualValue" : Policies, @@ -228,46 +214,34 @@ tests[{ } #-- - -################ -# Baseline 2.6 # -################ - # -# Baseline 2.6: Policy 1 +# MS.ONEDRIVE.6.1v1 #-- -# At this time we are unable to test for X because of Y tests[{ - "Requirement" : "OneDrive Client Sync SHALL be restricted to the local domain", - "Control" : "OneDrive 2.6", + "PolicyId" : PolicyId, "Criticality" : "Shall/Not-Implemented", "Commandlet" : [], "ActualValue" : [], - "ReportDetails" : "Currently cannot be checked automatically. See Onedrive Secure Configuration Baseline policy 2.6 for instructions on manual check", + "ReportDetails" : NotCheckedDetails(PolicyId), "RequirementMet" : false }] { + PolicyId := "MS.ONEDRIVE.6.1v1" true } #-- - -################ -# Baseline 2.7 # -################ - # -# Baseline 2.7: Policy 1 +# MS.ONEDRIVE.7.1v1 #-- -# At this time we are unable to test for X because of Y tests[{ - "Requirement" : "Legacy Authentication SHALL be blocked", - "Control" : "OneDrive 2.7", + "PolicyId" : PolicyId, "Criticality" : "Shall/Not-Implemented", "Commandlet" : [], "ActualValue" : [], - "ReportDetails" : "Currently cannot be checked automatically. See Onedrive Secure Configuration Baseline policy 2.7 for instructions on manual check", + "ReportDetails" : NotCheckedDetails(PolicyId), "RequirementMet" : false }] { + PolicyId := "MS.ONEDRIVE.7.1v1" true } -#-- +#-- \ No newline at end of file diff --git a/Rego/PowerPlatformConfig.rego b/Rego/PowerPlatformConfig.rego index 82b00d63bf..d6f8b42bc2 100644 --- a/Rego/PowerPlatformConfig.rego +++ b/Rego/PowerPlatformConfig.rego @@ -1,14 +1,10 @@ package powerplatform import future.keywords - - -Format(Array) = format_int(count(Array), 10) - -Description(String1, String2, String3) = trim(concat(" ", [String1, concat(" ", [String2, String3])]), " ") - -ReportDetailsBoolean(Status) = "Requirement met" if {Status == true} - -ReportDetailsBoolean(Status) = "Requirement not met" if {Status == false} +import data.report.utils.NotCheckedDetails +import data.report.utils.Format +import data.report.utils.ReportDetailsBoolean +import data.report.utils.Description +import data.report.utils.ReportDetailsString ReportDetailsArray(Status, Array, String1) = Detail if { Status == true @@ -20,27 +16,13 @@ ReportDetailsArray(Status, Array, String1) = Detail if { String2 := concat(", ", Array) Detail := Description(Format(Array), String1, String2) } -ReportDetailsString(Status, String) = Detail if { - Status == true - Detail := "Requirement met" -} - -ReportDetailsString(Status, String) = Detail if { - Status == false - Detail := String -} - - -################ -# Baseline 2.1 # -################ # -# Baseline 2.1: Policy 1 +# MS.POWERPLATFORM.1.1v1 #-- tests[{ - "Requirement" : "The ability to create production and sandbox environments SHALL be restricted to admins", - "Control" : "Power Platform 2.1", + #"Requirement" : "The ability to create production and sandbox environments SHALL be restricted to admins", + "PolicyId" : "MS.POWERPLATFORM.1.1v1", "Criticality" : "Shall", "Commandlet" : ["Get-TenantSettings"], "ActualValue" : EnvironmentCreation.disableEnvironmentCreationByNonAdminUsers, @@ -52,11 +34,11 @@ tests[{ } #-- -# Baseline 2.1: Policy 1 PoSh Error +# MS.POWERPLATFORM.1.1v1 #-- tests[{ - "Requirement" : "The ability to create production and sandbox environments SHALL be restricted to admins", - "Control" : "Power Platform 2.1", + #"Requirement" : "The ability to create production and sandbox environments SHALL be restricted to admins", + "PolicyId" : "MS.POWERPLATFORM.1.1v1", "Criticality" : "Shall", "Commandlet" : ["Get-TenantSettings"], "ActualValue" : "PowerShell Error", @@ -67,7 +49,7 @@ tests[{ } #-- -# +# TODO: Resolve Policy Id # Baseline 2.1: Policy 2 #-- tests[{ @@ -84,7 +66,7 @@ tests[{ } #-- -# +# TODO: Resolve Policy Id # Baseline 2.1: Policy 2 PoSh Error #-- tests[{ @@ -100,13 +82,8 @@ tests[{ } #-- - -################ -# Baseline 2.2 # -################ - # -# Baseline 2.2: Policy 1 +# MS.POWERPLATFORM.2.1v1 #-- DefaultEnvPolicies[{"PolicyName" : Policy.displayName}]{ TenantId := input.tenant_id @@ -118,8 +95,7 @@ DefaultEnvPolicies[{"PolicyName" : Policy.displayName}]{ # Note: there is only one default environment per tenant and it cannot be deleted or backed up tests[{ - "Requirement" : "A DLP policy SHALL be created to restrict connector access in the default Power Platform environment", - "Control" : "Power Platform 2.2", + "PolicyId" : "MS.POWERPLATFORM.2.1v1", "Criticality" : "Shall", "Commandlet" : ["Get-DlpPolicy"], "ActualValue" : DefaultEnvPolicies, @@ -132,7 +108,7 @@ tests[{ #-- # -# Baseline 2.2: Policy 2 +# MS.POWERPLATFORM.2.2v1 #-- # gets the list of all tenant environments AllEnvironments [{ "EnvName" : EnvName }] { @@ -157,8 +133,7 @@ EnvWithoutPolicies [Env] { } tests[{ - "Requirement" : "Non-default environments SHOULD have at least one DLP policy that affects them", - "Control" : "Power Platform 2.2", + "PolicyId" : "MS.POWERPLATFORM.2.2v1", "Criticality" : "Should", "Commandlet" : ["Get-DlpPolicy"], "ActualValue" : EnvWithoutPolicies, @@ -173,11 +148,10 @@ tests[{ #-- # -# Baseline 2.2: Policy 2 No DLP Policies found +# MS.POWERPLATFORM.2.2v1 #-- tests[{ - "Requirement" : "Non-default environments SHOULD have at least one DLP policy that affects them", - "Control" : "Power Platform 2.2", + "PolicyId" : "MS.POWERPLATFORM.2.2v1", "Criticality" : "Should", "Commandlet" : ["Get-DlpPolicy"], "ActualValue" : "No DLP Policies found", @@ -190,11 +164,10 @@ tests[{ #-- # -# Baseline 2.2: Policy 2 PoSh Error +# MS.POWERPLATFORM.2.2v1 #-- tests[{ - "Requirement" : "Non-default environments SHOULD have at least one DLP policy that affects them", - "Control" : "Power Platform 2.2", + "PolicyId" : "MS.POWERPLATFORM.2.2v1", "Criticality" : "Should", "Commandlet" : ["Get-DlpPolicy"], "ActualValue" : "PowerShell Error", @@ -206,7 +179,7 @@ tests[{ #-- # -# Baseline 2.2: Policy 3 +# MS.POWERPLATFORM.2.3v1 #-- # gets the set of connectors that are allowed in the default environment # general and confidential groups refer to business and non-business @@ -253,8 +226,7 @@ AllowedInBaseline := { } tests[{ - "Requirement" : "All connectors except those listed...[see Power Platform secure configuration baseline for list]...SHOULD be added to the Blocked category in the default environment policy", - "Control" : "Power Platform 2.2", + "PolicyId" : "MS.POWERPLATFORM.2.3v1", "Criticality" : "Should", "Commandlet" : ["Get-DlpPolicy"], "ActualValue" : RogueConnectors, @@ -270,11 +242,10 @@ tests[{ #-- # -# Baseline 2.2: Policy 3 Error No DLP policies Found +# MS.POWERPLATFORM.2.3v1 #-- tests[{ - "Requirement" : "All connectors except those listed...[see Power Platform secure configuration baseline for list]...SHOULD be added to the Blocked category in the default environment policy", - "Control" : "Power Platform 2.2", + "PolicyId" : "MS.POWERPLATFORM.2.3v1", "Criticality" : "Should", "Commandlet" : ["Get-DlpPolicy"], "ActualValue" : "No DLP Policies found", @@ -287,11 +258,10 @@ tests[{ #-- # -# Baseline 2.2: Policy 3 PoSh Error +# MS.POWERPLATFORM.2.3v1 #-- tests[{ - "Requirement" : "All connectors except those listed...[see Power Platform secure configuration baseline for list]...SHOULD be added to the Blocked category in the default environment policy", - "Control" : "Power Platform 2.2", + "PolicyId" : "MS.POWERPLATFORM.2.3v1", "Criticality" : "Should", "Commandlet" : ["Get-DlpPolicy"], "ActualValue" : "PowerShell error", @@ -302,17 +272,11 @@ tests[{ } #-- - -################ -# Baseline 2.3 # -################ - # -# Baseline 2.3: Policy 1 +# MS.POWERPLATFORM.3.1v1 #-- tests[{ - "Requirement" : "Power Platform tenant isolation SHALL be enabled", - "Control" : "Power Platform 2.3", + "PolicyId" : "MS.POWERPLATFORM.3.1v1", "Criticality" : "Shall", "Commandlet" : ["Get-PowerAppTenantIsolationPolicy"], "ActualValue" : TenantIsolation.properties.isDisabled, @@ -325,11 +289,10 @@ tests[{ #-- # -# Baseline 2.3: Policy 1 PoSh Error +# MS.POWERPLATFORM.3.1v1 #-- tests[{ - "Requirement" : "Power Platform tenant isolation SHALL be enabled", - "Control" : "Power Platform 2.3", + "PolicyId" : "MS.POWERPLATFORM.3.1v1", "Criticality" : "Shall", "Commandlet" : ["Get-PowerAppTenantIsolationPolicy"], "ActualValue" : "PowerShell Error", @@ -341,40 +304,51 @@ tests[{ #-- # -# Baseline 2.3: Policy 2 +# MS.POWERPLATFORM.3.2v1 #-- # At this time we are unable to test for X because of Y tests[{ - "Requirement" : "An inbound/outbound connection allowlist SHOULD be configured", - "Control" : "Power Platform 2.3", + "PolicyId" : PolicyId, "Criticality" : "Should/Not-Implemented", "Commandlet" : [], "ActualValue" : [], - "ReportDetails" : "Currently cannot be checked automatically. See Power Platform Secure Configuration Baseline policy 2.3 for instructions on manual check", + "ReportDetails" : NotCheckedDetails(PolicyId), "RequirementMet" : false }] { + PolicyId := "MS.POWERPLATFORM.3.2v1" true } #-- - -################ -# Baseline 2.4 # -################ +# +# MS.POWERPLATFORM.3.3v1 +#-- +tests[{ + "PolicyId" : PolicyId, + "Criticality" : "Should/Not-Implemented", + "Commandlet" : [], + "ActualValue" : [], + "ReportDetails" : NotCheckedDetails(PolicyId), + "RequirementMet" : false +}] { + PolicyId := "MS.POWERPLATFORM.3.3v1" + true +} +#-- # -# Baseline 2.4: Policy 1 +# MS.POWERPLATFORM.4.1v1 #-- # At this time we are unable to test for X because of Y tests[{ - "Requirement" : "Content security policies for model-driven Power Apps SHALL be enabled", - "Control" : "Power Platform 2.4", + "PolicyId" : PolicyId, "Criticality" : "Shall/Not-Implemented", "Commandlet" : [], "ActualValue" : [], - "ReportDetails" : "Currently cannot be checked automatically. See Power Platform Secure Configuration Baseline policy 2.4 for instructions on manual check", + "ReportDetails" : NotCheckedDetails(PolicyId), "RequirementMet" : false }] { + PolicyId := "MS.POWERPLATFORM.4.1v1" true } #-- \ No newline at end of file diff --git a/Rego/SharepointConfig.rego b/Rego/SharepointConfig.rego index ce3ef93fbc..459b7b46e9 100644 --- a/Rego/SharepointConfig.rego +++ b/Rego/SharepointConfig.rego @@ -1,21 +1,13 @@ package sharepoint import future.keywords - -ReportDetailsBoolean(Status) = "Requirement met" if {Status == true} - -ReportDetailsBoolean(Status) = "Requirement not met" if {Status == false} - - -################ -# Baseline 2.1 # -################ +import data.report.utils.NotCheckedDetails +import data.report.utils.ReportDetailsBoolean # -# Baseline 2.1: Policy 1 +# MS.SHAREPOINT.1.1v1 #-- tests[{ - "Requirement" : "File and folder links default sharing setting SHALL be set to \"Specific People (Only the People the User Specifies)\"", - "Control" : "Sharepoint 2.1", + "PolicyId" : "MS.SHAREPOINT.1.1v1", "Criticality" : "Shall", "Commandlet" : ["Get-SPOTenant", "Get-PnPTenant"], "ActualValue" : Policy.DefaultSharingLinkType, @@ -26,18 +18,27 @@ tests[{ Status := Policy.DefaultSharingLinkType == 1 } #-- - - -################ -# Baseline 2.2 # -################ +# +# MS.SHAREPOINT.1.2v1 +#-- +tests[{ + "PolicyId" : PolicyId, + "Criticality" : "Shall/Not-Implemented", + "Commandlet" : [], + "ActualValue" : [], + "ReportDetails" : NotCheckedDetails(PolicyId), + "RequirementMet" : false +}] { + PolicyId := "MS.SHAREPOINT.1.2v1" + true +} +#-- # -# Baseline 2.2: Policy 1 +# MS.SHAREPOINT.1.3v1 #-- tests[{ - "Requirement" : "External sharing SHOULD be limited to approved domains and security groups per interagency collaboration needs", - "Control" : "Sharepoint 2.2", + "PolicyId" : "MS.SHAREPOINT.1.3v1", "Criticality" : "Should", "Commandlet" : ["Get-SPOTenant", "Get-PnPTenant"], "ActualValue" : Policy.SharingCapability, @@ -88,29 +89,24 @@ tests[{ ################ # -# Baseline 2.3: Policy 1 +# MS.SHAREPOINT.2.1v1 #-- # At this time we are unable to test for X because of Y tests[{ - "Requirement" : "Sharing settings for specific SharePoint sites SHOULD align to their sensitivity level", - "Control" : "Sharepoint 2.3", + "PolicyId" : PolicyId, "Criticality" : "Should/Not-Implemented", "Commandlet" : [], "ActualValue" : [], - "ReportDetails" : "Currently cannot be checked automatically. See Sharepoint Secure Configuration Baseline policy 2.3 for instructions on manual check", + "ReportDetails" : NotCheckedDetails(PolicyId), "RequirementMet" : false }] { + PolicyId := "MS.SHAREPOINT.2.1v1" true } #-- - -################ -# Baseline 2.4 # -################ - # -# Baseline 2.4: Policy 1 +# MS.SHAREPOINT.3.1v1 #-- ReportDetails2_4_1(Policy) = Description if { Policy.SharingCapability == 0 @@ -146,8 +142,7 @@ ReportDetails2_4_1(Policy) = Description if { } tests[{ - "Requirement" : "Expiration timer for 'Guest access to a site or OneDrive' should be set to 30 days", - "Control" : "Sharepoint 2.4", + "PolicyId" : "MS.SHAREPOINT.3.1v1", "Criticality" : "Should", "Commandlet" : ["Get-SPOTenant", "Get-PnPTenant"], "ActualValue" : [Policy.SharingCapability, Policy.ExternalUserExpirationRequired, Policy.ExternalUserExpireInDays], @@ -166,7 +161,7 @@ tests[{ } #-- -# +# TODO: Resolve Policy Id # Baseline 2.4: Policy 2 #-- ReportDetails2_4_2(Policy) = Description if { @@ -223,29 +218,26 @@ tests[{ } #-- - -################ -# Baseline 2.5 # -################ - -# +# TODO: Resolve Policy Id # Baseline 2.5: Policy 1 #-- # At this time we are unable to test for X because of Y tests[{ "Requirement" : "Users SHALL be prevented from running custom scripts on personal sites (OneDrive)", "Control" : "Sharepoint 2.5", + "PolicyId" : PolicyId, "Criticality" : "Shall/Not-Implemented", "Commandlet" : [], "ActualValue" : [], - "ReportDetails" : "Currently cannot be checked automatically. See Sharepoint Secure Configuration Baseline policy 2.5 for instructions on manual check", + "ReportDetails" : NotCheckedDetails(PolicyId), "RequirementMet" : false }] { + PolicyId := "MS.SHAREPOINT.TBD" true } #-- -# +# TODO: Resolve Policy Id # Baseline 2.5: Policy 2 #-- tests[{ diff --git a/Rego/TeamsConfig.rego b/Rego/TeamsConfig.rego index 649885e04e..c6a6f11f58 100644 --- a/Rego/TeamsConfig.rego +++ b/Rego/TeamsConfig.rego @@ -1,13 +1,18 @@ +################ +# Teams Baseline +################ + +# +# Reference: Secure Baseline file, teams.md +#-- +# This file implements controls/policies documented in the secure baseline. The tests.PolicyId +# (e.g., MS.TEAMS.1.1v1) aligns this files to the secure baseline control. package teams import future.keywords - -Format(Array) = format_int(count(Array), 10) - -Description(String1, String2, String3) = trim(concat(" ", [String1, concat(" ", [String2, String3])]), " ") - -ReportDetailsBoolean(Status) = "Requirement met" if {Status == true} - -ReportDetailsBoolean(Status) = "Requirement not met" if {Status == false} +import data.report.utils.NotCheckedDetails +import data.report.utils.Format +import data.report.utils.ReportDetailsBoolean +import data.report.utils.Description ReportDetailsArray(Status, Array, String1) = Detail if { Status == true @@ -20,23 +25,8 @@ ReportDetailsArray(Status, Array, String1) = Detail if { Detail := Description(Format(Array), String1, String2) } -ReportDetailsString(Status, String) = Detail if { - Status == true - Detail := "Requirement met" -} - -ReportDetailsString(Status, String) = Detail if { - Status == false - Detail := String -} - - -################ -# Baseline 2.1 # -################ - # -# Baseline 2.1: Policy 1 +# MS.TEAMS.1.1v1 #-- # The english translation of the following is: # Iterate through all meeting policies. For each, check if AllowExternalParticipantGiveRequestControl @@ -47,8 +37,7 @@ MeetingsAllowingExternalControl[Policy.Identity] { } tests[{ - "Requirement" : "External participants SHOULD NOT be enabled to request control of shared desktops or windows in the Global (Org-wide default) meeting policy or in custom meeting policies if any exist", - "Control" : "Teams 2.1", + "PolicyId" : "MS.TEAMS.1.1v1", "Criticality" : "Should", "Commandlet" : ["Get-CsTeamsMeetingPolicy"], "ActualValue" : Policies, @@ -61,13 +50,8 @@ tests[{ } #-- - -################ -# Baseline 2.2 # -################ - # -# Baseline 2.2: Policy 1 +# MS.TEAMS.2.1v1 #-- MeetingsAllowingAnonStart[Policy.Identity] { Policy := input.meeting_policies[_] @@ -75,8 +59,7 @@ MeetingsAllowingAnonStart[Policy.Identity] { } tests[{ - "Requirement" : "Anonymous users SHALL NOT be enabled to start meetings in the Global (Org-wide default) meeting policy or in custom meeting policies if any exist", - "Control" : "Teams 2.2", + "PolicyId" : "MS.TEAMS.2.1v1", "Criticality" : "Shall", "Commandlet" : ["Get-CsTeamsMeetingPolicy"], "ActualValue" : Policies, @@ -89,13 +72,8 @@ tests[{ } #-- - -################ -# Baseline 2.3 # -################ - # -# Baseline 2.3: Policy 1 +# MS.TEAMS.3.1v1 #-- ReportDetails2_3(Policy) = Description if { Policy.AutoAdmittedUsers != "Everyone" @@ -115,8 +93,7 @@ ReportDetails2_3(Policy) = Description if { } tests[{ - "Requirement" : "Anonymous users, including dial-in users, SHOULD NOT be admitted automatically", - "Control" : "Teams 2.3", + "PolicyId" : "MS.TEAMS.3.1v1", "Criticality" : "Should", "Commandlet" : ["Get-CsTeamsMeetingPolicy"], "ActualValue" : [Policy.AutoAdmittedUsers, Policy.AllowPSTNUsersToBypassLobby], @@ -131,8 +108,7 @@ tests[{ } tests[{ - "Requirement" : "Anonymous users, including dial-in users, SHOULD NOT be admitted automatically", - "Control" : "Teams 2.3", + "PolicyId" : "MS.TEAMS.3.1v1", "Criticality" : "Should", "Commandlet" : ["Get-CsTeamsMeetingPolicy"], "ActualValue" : "PowerShell Error", @@ -144,11 +120,10 @@ tests[{ #-- # -# Baseline 2.3: Policy 2 +# MS.TEAMS.3.2v1 #-- tests[{ - "Requirement" : "Internal users SHOULD be admitted automatically", - "Control" : "Teams 2.3", + "PolicyId" : "MS.TEAMS.3.2v1", "Criticality" : "Should", "Commandlet" : ["Get-CsTeamsMeetingPolicy"], "ActualValue" : Policy.AutoAdmittedUsers, @@ -162,11 +137,10 @@ tests[{ } # -# Baseline 2.3: Policy 2 +# MS.TEAMS.3.2v1 #-- tests[{ - "Requirement" : "Internal users SHOULD be admitted automatically", - "Control" : "Teams 2.3", + "PolicyId" : "MS.TEAMS.3.2v1", "Criticality" : "Should", "Commandlet" : ["Get-CsTeamsMeetingPolicy"], "ActualValue" : "PowerShell Error", @@ -177,13 +151,8 @@ tests[{ } #-- - -################ -# Baseline 2.4 # -################ - # -# Baseline 2.4: Policy 1 +# MS.TEAMS.4.1v1 #-- ExternalAccessConfig[Policy.Identity] { Policy := input.federation_configuration[_] @@ -193,8 +162,7 @@ ExternalAccessConfig[Policy.Identity] { } tests[{ - "Requirement" : "External access SHALL only be enabled on a per-domain basis", - "Control" : "Teams 2.4", + "PolicyId" : "MS.TEAMS.4.1v1", "Criticality" : "Shall", "Commandlet" : ["Get-CsTenantFederationConfiguration"], "ActualValue" : Policies, @@ -230,13 +198,8 @@ tests[{ } #-- - -################ -# Baseline 2.5 # -################ - # -# Baseline 2.5: Policy 1 +# MS.TEAMS.5.1v1 #-- # There are two relevant settings: # - AllowTeamsConsumer: Is contact to or from unmanaged users allowed at all? @@ -262,8 +225,7 @@ FederationConfiguration[Policy.Identity] { } tests[{ - "Requirement" : "Unmanaged users SHALL NOT be enabled to initiate contact with internal users", - "Control" : "Teams 2.5", + "PolicyId" : "MS.TEAMS.5.1v1", "Criticality" : "Shall", "Commandlet" : ["Get-CsTenantFederationConfiguration"], "ActualValue" : Policies, @@ -277,7 +239,7 @@ tests[{ #-- # -# Baseline 2.5: Policy 2 +# MS.TEAMS.5.2v1 #-- InternalCannotenable[Policy.Identity] { Policy := input.federation_configuration[_] @@ -285,8 +247,7 @@ InternalCannotenable[Policy.Identity] { } tests[{ - "Requirement" : "Internal users SHOULD NOT be enabled to initiate contact with unmanaged users", - "Control" : "Teams 2.5", + "PolicyId" : "MS.TEAMS.5.2v1", "Criticality" : "Should", "Commandlet" : ["Get-CsTenantFederationConfiguration"], "ActualValue" : Policies, @@ -299,13 +260,8 @@ tests[{ } #-- - -################ -# Baseline 2.6 # -################ - # -# Baseline 2.6: Policy 1 +# MS.TEAMS.6.1v1 #-- SkpyeBlocConfig[Policy.Identity] { Policy := input.federation_configuration[_] @@ -313,8 +269,7 @@ SkpyeBlocConfig[Policy.Identity] { } tests[{ - "Requirement" : "Contact with Skype users SHALL be blocked", - "Control" : "Teams 2.6", + "PolicyId" : "MS.TEAMS.6.1v1", "Criticality" : "Shall", "Commandlet" : ["Get-CsTenantFederationConfiguration"], "ActualValue" : Policies, @@ -327,13 +282,8 @@ tests[{ } #-- - -################ -# Baseline 2.7 # -################ - # -# Baseline 2.7: Policy 1 +# MS.TEAMS.7.1v1 #-- ConfigsAllowingEmail[Policy.Identity] { Policy := input.client_configuration[_] @@ -358,8 +308,7 @@ ReportDetails2_7(IsGCC, IsEnabled) = Description if { } tests[{ - "Requirement" : "Teams email integration SHALL be disabled", - "Control" : "Teams 2.7", + "PolicyId" : "MS.TEAMS.7.1v1", "Criticality" : "Shall", "Commandlet" : ["Get-CsTeamsClientConfiguration", "Get-CsTenant"], "ActualValue" : {"ClientConfig": input.client_configuration, "AssignedPlans": AssignedPlans}, @@ -380,15 +329,21 @@ tests[{ Conditions := [IsEnabled, IsGCC] Status := count([Condition | Condition = Conditions[_]; Condition == true]) > 0 } -#-- - -################ -# Baseline 2.8 # -################ +tests[{ + "PolicyId" : "MS.TEAMS.7.1v1", + "Criticality" : "Shall", + "Commandlet" : ["Get-CsTeamsClientConfiguration"], + "ActualValue" : "PowerShell Error", + "ReportDetails" : "PowerShell Error", + "RequirementMet" : false +}] { + count(input.teams_tenant_info) == 0 +} +#-- # -# Baseline 2.8: Policy 1 +# MS.TEAMS.8.1v1 #-- PoliciesBlockingDefaultApps[Policy.Identity] { Policy := input.app_policies[_] @@ -396,8 +351,7 @@ PoliciesBlockingDefaultApps[Policy.Identity] { } tests[{ - "Requirement" : "Agencies SHOULD allow all apps published by Microsoft, but MAY block specific Microsoft apps as needed", - "Control" : "Teams 2.8", + "PolicyId" : "MS.TEAMS.8.1v1", "Criticality" : "Should", "Commandlet" : ["Get-CsTeamsAppPermissionPolicy"], "ActualValue" : Policies, @@ -411,7 +365,7 @@ tests[{ #-- # -# Baseline 2.8: Policy 2 +# MS.TEAMS.8.2v1 #-- PoliciesAllowingGlobalApps[Policy.Identity] { Policy := input.app_policies[_] @@ -424,8 +378,7 @@ PoliciesAllowingCustomApps[Policy.Identity] { } tests[{ - "Requirement" : "Agencies SHOULD NOT allow installation of all third-party apps, but MAY allow specific apps as needed", - "Control" : "Teams 2.8", + "PolicyId" : "MS.TEAMS.8.2v1", "Criticality" : "Should", "Commandlet" : ["Get-CsTeamsAppPermissionPolicy"], "ActualValue" : Policies, @@ -438,8 +391,7 @@ tests[{ } tests[{ - "Requirement" : "Agencies SHOULD NOT allow installation of all custom apps, but MAY allow specific apps as needed", - "Control" : "Teams 2.8", + "PolicyId" : "MS.TEAMS.8.2av1", "Criticality" : "Should", "Commandlet" : ["Get-CsTeamsAppPermissionPolicy"], "ActualValue" : Policies, @@ -453,33 +405,27 @@ tests[{ #-- # -# Baseline 2.8: Policy 3 +# MS.TEAMS.8.3v1 #-- # At this time we are unable to test for X because of Y tests[{ - "Requirement" : "Agencies SHALL establish policy dictating the app review and approval process to be used by the agency", - "Control" : "Teams 2.8", + "PolicyId" : PolicyId, "Criticality" : "Shall/3rd Party", "Commandlet" : [], "ActualValue" : [], - "ReportDetails" : "Cannot be checked automatically. See Microsoft Teams Secure Configuration Baseline policy 2.8 for instructions on manual check", + "ReportDetails" : NotCheckedDetails(PolicyId), "RequirementMet" : false }] { + PolicyId := "MS.TEAMS.8.3v1" true } #-- - -################ -# Baseline 2.9 # -################ - # -# Baseline 2.9: Policy 1 +# MS.TEAMS.9.1v1 #-- tests[{ - "Requirement" : "Cloud video recording SHOULD be disabled in the global (org-wide default) meeting policy", - "Control" : "Teams 2.9", + "PolicyId" : "MS.TEAMS.9.1v1", "Criticality" : "Should", "Commandlet" : ["Get-CsTeamsMeetingPolicy"], "ActualValue" : Policy.AllowCloudRecording, @@ -492,11 +438,10 @@ tests[{ } # -# Baseline 2.9: Policy 1 +# MS.TEAMS.9.1v1 #-- tests[{ - "Requirement" : "Cloud video recording SHOULD be disabled in the global (org-wide default) meeting policy", - "Control" : "Teams 2.9", + "PolicyId" : "MS.TEAMS.9.1v1", "Criticality" : "Should", "Commandlet" : ["Get-CsTeamsMeetingPolicy"], "ActualValue" : "PowerShell Error", @@ -508,7 +453,7 @@ tests[{ #-- # -# Baseline 2.9: Policy 2 +# MS.TEAMS.9.3v1 #-- PoliciesAllowingOutsideRegionStorage[Policy.Identity] { Policy := input.meeting_policies[_] @@ -517,8 +462,7 @@ PoliciesAllowingOutsideRegionStorage[Policy.Identity] { } tests[{ - "Requirement" : "For all meeting polices that allow cloud recording, recordings SHOULD be stored inside the country of that agency's tenant", - "Control" : "Teams 2.9", + "PolicyId" : "MS.TEAMS.9.3v1", "Criticality" : "Should", "Commandlet" : ["Get-CsTeamsMeetingPolicy"], "ActualValue" : Policies, @@ -531,17 +475,11 @@ tests[{ } #-- - -################# -# Baseline 2.10 # -################# - # -# Baseline 2.10: Policy 1 +# MS.TEAMS.10.1v1 #-- tests[{ - "Requirement" : "Record an event SHOULD be set to Organizer can record", - "Control" : "Teams 2.10", + "PolicyId" : "MS.TEAMS.10.1v1", "Criticality" : "Should", "Commandlet" : ["Get-CsTeamsMeetingBroadcastPolicy"], "ActualValue" : Policy.BroadcastRecordingMode, @@ -554,11 +492,10 @@ tests[{ } # -# Baseline 2.10: Policy 1 +# MS.TEAMS.10.1v1 #-- tests[{ - "Requirement" : "Record an event SHOULD be set to Organizer can record", - "Control" : "Teams 2.10", + "PolicyId" : "MS.TEAMS.10.1v1", "Criticality" : "Should", "Commandlet" : ["Get-CsTeamsMeetingBroadcastPolicy"], "ActualValue" : "PowerShell Error", @@ -569,18 +506,12 @@ tests[{ } #-- - -################# -# Baseline 2.11 # -################# - # -# Baseline 2.11: Policy 1 +# MS.TEAMS.11.1v1 #-- # At this time we are unable to test because settings are configured in M365 Defender or using a third-party app tests[{ - "Requirement" : "A DLP solution SHALL be enabled", - "Control" : "Teams 2.11", + "PolicyId" : "MS.TEAMS.11.1v1", "Criticality" : "Shall/3rd Party", "Commandlet" : [], "ActualValue" : [], @@ -592,12 +523,11 @@ tests[{ #-- # -# Baseline 2.11: Policy 2 +# MS.TEAMS.11.2v1 #-- # At this time we are unable to test because settings are configured in M365 Defender or using a third-party app tests[{ - "Requirement" : "Agencies SHOULD use either the native DLP solution offered by Microsoft or a DLP solution that offers comparable services", - "Control" : "Teams 2.11", + "PolicyId" : "MS.TEAMS.11.2v1", "Criticality" : "Should/3rd Party", "Commandlet" : [], "ActualValue" : [], @@ -609,12 +539,11 @@ tests[{ #-- # -# Baseline 2.11: Policy 3 +# MS.TEAMS.11.4v1 #-- # At this time we are unable to test because settings are configured in M365 Defender or using a third-party app tests[{ - "Requirement" : "The DLP solution SHALL protect Personally Identifiable Information (PII) and sensitive information, as defined by the agency. At a minimum, the sharing of credit card numbers, taxpayer Identification Numbers (TIN), and Social Security Numbers (SSN) via email SHALL be restricted", - "Control" : "Teams 2.11", + "PolicyId" : "MS.TEAMS.11.4v1", "Criticality" : "Shall/3rd Party", "Commandlet" : [], "ActualValue" : [], @@ -625,18 +554,12 @@ tests[{ } #-- - -################# -# Baseline 2.12 # -################# - # -# Baseline 2.12: Policy 1 +# MS.TEAMS.12.1v1 #-- # At this time we are unable to test because settings are configured in M365 Defender or using a third-party app tests[{ - "Requirement" : "Attachments included with Teams messages SHOULD be scanned for malware", - "Control" : "Teams 2.12", + "PolicyId" : "MS.TEAMS.12.1v1", "Criticality" : "Should/3rd Party", "Commandlet" : [], "ActualValue" : [], @@ -648,12 +571,11 @@ tests[{ #-- # -# Baseline 2.12: Policy 2 +# MS.TEAMS.12.2v1 #-- # At this time we are unable to test because settings are configured in M365 Defender or using a third-party app tests[{ - "Requirement" : "Users SHOULD be prevented from opening or downloading files detected as malware", - "Control" : "Teams 2.12", + "PolicyId" : "MS.TEAMS.12.2v1", "Criticality" : "Should/3rd Party", "Commandlet" : [], "ActualValue" : [], @@ -664,18 +586,12 @@ tests[{ } #-- - -################# -# Baseline 2.13 # -################# - # -# Baseline 2.13: Policy 1 +# MS.TEAMS.13.1v1 #-- # At this time we are unable to test because settings are configured in M365 Defender or using a third-party app tests[{ - "Requirement" : "URL comparison with a block-list SHOULD be enabled", - "Control" : "Teams 2.13", + "PolicyId" : "MS.TEAMS.13.1v1", "Criticality" : "Should/3rd Party", "Commandlet" : [], "ActualValue" : [], @@ -687,12 +603,11 @@ tests[{ #-- # -# Baseline 2.13: Policy 2 +# MS.TEAMS.13.2v1 #-- # At this time we are unable to test because settings are configured in M365 Defender or using a third-party app tests[{ - "Requirement" : "Direct download links SHOULD be scanned for malware", - "Control" : "Teams 2.13", + "PolicyId" : "MS.TEAMS.13.2v1", "Criticality" : "Should/3rd Party", "Commandlet" : [], "ActualValue" : [], @@ -704,12 +619,11 @@ tests[{ #-- # -# Baseline 2.13: Policy 3 +# MS.TEAMS.13.3v1 #-- # At this time we are unable to test because settings are configured in M365 Defender or using a third-party app tests[{ - "Requirement" : "User click tracking SHOULD be enabled", - "Control" : "Teams 2.13", + "PolicyId" : "MS.TEAMS.13.3v1", "Criticality" : "Should/3rd Party", "Commandlet" : [], "ActualValue" : [], diff --git a/Rego/Utils/ReportUtils.rego b/Rego/Utils/ReportUtils.rego new file mode 100644 index 0000000000..f8460f06de --- /dev/null +++ b/Rego/Utils/ReportUtils.rego @@ -0,0 +1,62 @@ +package report.utils +import future.keywords + +# +BaselineVersion() := moduleVersion if { + not input.module_version + moduleVersion := "main" +} + +BaselineVersion() := moduleVersion if { + moduleVersion := input.module_version +} + +#baselineVersion := "3.0.0." # Baseline version is pinned to a module version +ScubaBaseUrl := sprintf("https://github.com/cisagov/ScubaGear/blob/%v/baselines/", [BaselineVersion()]) + +################ +# Helper functions for this file +################ + +PolicyAnchor(PolicyId) := anchor if { + anchor := sprintf("#%v", [replace(lower(PolicyId), ".", "")]) +} + +PolicyProduct(PolicyId) := product if { + dotIndexes := indexof_n(PolicyId, ".") + product := lower(substring(PolicyId, 3, dotIndexes[1]-dotIndexes[0]-1)) +} + +PolicyLink(PolicyId) := link if { + link := sprintf("Secure Configuration Baseline policy", [ScubaBaseUrl, PolicyProduct(PolicyId), PolicyAnchor(PolicyId)]) +} + +################ +# The report formatting functions below are generic and used throughout the policies # +################ + +# +NotCheckedDetails(PolicyId) := details if { + link := PolicyLink(PolicyId) + details := sprintf("Not currently checked automatically. See %v for instructions on manual check", [link]) +} + +# +Format(Array) := format_int(count(Array), 10) + +# +ReportDetailsBoolean(Status) := "Requirement met" if {Status == true} +ReportDetailsBoolean(Status) := "Requirement not met" if {Status == false} + +# +Description(String1, String2, String3) := trim(concat(" ", [String1, concat(" ", [String2, String3])]), " ") + +# +ReportDetailsString(Status, String) := Detail if { + Status == true + Detail := "Requirement met" +} +ReportDetailsString(Status, String) := Detail if { + Status == false + Detail := String +} \ No newline at end of file diff --git a/Testing/Unit/PowerShell/CreateReport/CreateReportStubs/TestResults.json b/Testing/Unit/PowerShell/CreateReport/CreateReportStubs/TestResults.json index 356d90a3de..ed79cc0e36 100644 --- a/Testing/Unit/PowerShell/CreateReport/CreateReportStubs/TestResults.json +++ b/Testing/Unit/PowerShell/CreateReport/CreateReportStubs/TestResults.json @@ -1,2465 +1,2318 @@ [ - { - "ActualValue": false, - "Commandlet": "Get-MgPolicyAdminConsentRequestPolicy", - "Control": "AAD 2.7", - "Criticality": "Shall", - "ReportDetails": "Requirement not met", - "Requirement": "An admin consent workflow SHALL be configured", - "RequirementMet": false - }, - { - "ActualValue": true, - "Commandlet": "Get-MgPolicyAuthorizationPolicy", - "Control": "AAD 2.6", - "Criticality": "Shall", - "ReportDetails": "Requirement not met", - "Requirement": "Only administrators SHALL be allowed to register third-party applications", - "RequirementMet": false - }, - { - "ActualValue": "", - "Commandlet": "Get-MgDirectoryRoleMember", - "Control": "AAD 2.12", - "Criticality": "Shall", - "ReportDetails": "0 admin(s) that are not cloud-only found", - "Requirement": "Users that need to be assigned to highly privileged Azure AD roles SHALL be provisioned cloud-only accounts that are separate from the on-premises directory or other federated identity providers", - "RequirementMet": true - }, - { - "ActualValue": "Role ID : 10dae51f-b6af-4016-8d66-8c2a99b929b3", - "Commandlet": "Get-MgPolicyAuthorizationPolicy", - "Control": "AAD 2.18", - "Criticality": "Should", - "ReportDetails": "Permission level set to \"Limited access\"", - "Requirement": "Guest users SHOULD have limited access to Azure AD directory objects", - "RequirementMet": true - }, - { - "ActualValue": "[ManagePermissionGrantsForSelf.microsoft-user-default-legacy]", - "Commandlet": "Get-MgPolicyAuthorizationPolicy", - "Control": "AAD 2.7", - "Criticality": "Shall", - "ReportDetails": "Requirement not met", - "Requirement": "Only administrators SHALL be allowed to consent to third-party applications", - "RequirementMet": false - }, - { - "ActualValue": "everyone", - "Commandlet": "Get-MgPolicyAuthorizationPolicy", - "Control": "AAD 2.18", - "Criticality": "Should", - "ReportDetails": "Requirement not met", - "Requirement": "Only users with the Guest Inviter role SHOULD be able to invite guest users", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": "", - "Control": "AAD 2.18", - "Criticality": "Should/Not-Implemented", - "ReportDetails": "Currently cannot be checked automatically. See Azure Active Directory Secure Configuration Baseline policy 2.18 for instructions on manual check", - "Requirement": "Guest invites SHOULD only be allowed to specific external domains that have been authorized by the agency for legitimate business purposes", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": "", - "Control": "AAD 2.2", - "Criticality": "Should/Not-Implemented", - "ReportDetails": "Currently cannot be checked automatically. See Azure Active Directory Secure Configuration Baseline policy 2.2 for instructions on manual check", - "Requirement": "A notification SHOULD be sent to the administrator when high-risk users are detected", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": "", - "Control": "AAD 2.4", - "Criticality": "Shall/Not-Implemented", - "ReportDetails": "Currently cannot be checked automatically. See Azure Active Directory Secure Configuration Baseline policy 2.4 for instructions on manual check", - "Requirement": "If phishing-resistant MFA cannot be used, an MFA method from the list [see AAD baseline 2.4] SHALL be used in the interim", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": "", - "Control": "AAD 2.4", - "Criticality": "Shall/Not-Implemented", - "ReportDetails": "Currently cannot be checked automatically. See Azure Active Directory Secure Configuration Baseline policy 2.4 for instructions on manual check", - "Requirement": "Phishing-resistant MFA SHALL be used for all users", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": "", - "Control": "AAD 2.4", - "Criticality": "Shall/Not-Implemented", - "ReportDetails": "Currently cannot be checked automatically. See Azure Active Directory Secure Configuration Baseline policy 2.4 for instructions on manual check", - "Requirement": "SMS or Voice as the MFA method SHALL NOT be used", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": "", - "Control": "AAD 2.5", - "Criticality": "Shall/Not-Implemented", - "ReportDetails": "Currently cannot be checked automatically. See Azure Active Directory Secure Configuration Baseline policy 2.5 for instructions on manual check", - "Requirement": "The following critical logs SHALL be sent at a minimum: AuditLogs, SignInLogs, RiskyUsers, UserRiskEvents, NonInteractiveUserSignInLogs, ServicePrincipalSignInLogs, ADFSSignInLogs, RiskyServicePrincipals, ServicePrincipalRiskEvents", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": "", - "Control": "AAD 2.5", - "Criticality": "Shall/Not-Implemented", - "ReportDetails": "Currently cannot be checked automatically. See Azure Active Directory Secure Configuration Baseline policy 2.5 for instructions on manual check", - "Requirement": "The logs SHALL be sent to the agency\u0027s SOC for monitoring", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": "", - "Control": "AAD 2.8", - "Criticality": "Shall/Not-Implemented", - "ReportDetails": "Currently cannot be checked automatically. See Azure Active Directory Secure Configuration Baseline policy 2.8 for instructions on manual check", - "Requirement": "User passwords SHALL NOT expire", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": "Get-MgIdentityConditionalAccessPolicy", - "Control": "AAD 2.1", - "Criticality": "Shall", - "ReportDetails": "0 conditional access policy(s) found that meet(s) all requirements", - "Requirement": "Legacy authentication SHALL be blocked", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": "Get-MgIdentityConditionalAccessPolicy", - "Control": "AAD 2.10", - "Criticality": "Shall", - "ReportDetails": "0 conditional access policy(s) found that meet(s) all requirements", - "Requirement": "Browser sessions SHALL not be persistent", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": "Get-MgIdentityConditionalAccessPolicy", - "Control": "AAD 2.13", - "Criticality": "Shall", - "ReportDetails": "0 conditional access policy(s) found that meet(s) all requirements", - "Requirement": "MFA SHALL be required for user access to highly privileged roles", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": "Get-MgIdentityConditionalAccessPolicy", - "Control": "AAD 2.17", - "Criticality": "Should", - "ReportDetails": "0 conditional access policy(s) found that meet(s) all requirements", - "Requirement": "Managed devices SHOULD be required for authentication", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": "Get-MgIdentityConditionalAccessPolicy", - "Control": "AAD 2.2", - "Criticality": "Shall", - "ReportDetails": "0 conditional access policy(s) found that meet(s) all requirements", - "Requirement": "Users detected as high risk SHALL be blocked", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": "Get-MgIdentityConditionalAccessPolicy", - "Control": "AAD 2.3", - "Criticality": "Shall", - "ReportDetails": "0 conditional access policy(s) found that meet(s) all requirements", - "Requirement": "Sign-ins detected as high risk SHALL be blocked", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": "Get-MgIdentityConditionalAccessPolicy", - "Control": "AAD 2.4", - "Criticality": "Shall", - "ReportDetails": "0 conditional access policy(s) found that meet(s) all requirements", - "Requirement": "MFA SHALL be required for all users", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": "Get-MgIdentityConditionalAccessPolicy", - "Control": "AAD 2.9", - "Criticality": "Shall", - "ReportDetails": "0 conditional access policy(s) found that meet(s) all requirements", - "Requirement": "Sign-in frequency SHALL be configured to 12 hours", - "RequirementMet": false - }, - { - "ActualValue": [ - "Application Administrator", - "Cloud Application Administrator", - "Exchange Administrator", - "Global Administrator", - "Hybrid Identity Administrator", - "Privileged Role Administrator", - "SharePoint Administrator", - "User Administrator" - ], - "Commandlet": "Get-MgRoleManagementDirectoryRoleAssignmentScheduleInstance", - "Control": "AAD 2.14", - "Criticality": "Shall", - "ReportDetails": "8 role(s) configured to allow permanent active assignment or expiration period too long:\u003cbr/\u003eApplication Administrator, Cloud Application Administrator, Exchange Administrator, Global Administrator, Hybrid Identity Administrator, Privileged Role Administrator, SharePoint Administrator, User Administrator", - "Requirement": "Permanent active role assignments SHALL NOT be allowed for highly privileged roles. Active assignments SHALL have an expiration period.", - "RequirementMet": false - }, - { - "ActualValue": [ - "Application Administrator", - "Cloud Application Administrator", - "Exchange Administrator", - "Global Administrator", - "Hybrid Identity Administrator", - "Privileged Role Administrator", - "SharePoint Administrator", - "User Administrator" - ], - "Commandlet": "Get-MgRoleManagementDirectoryRoleAssignmentScheduleInstance", - "Control": "AAD 2.15", - "Criticality": "Should", - "ReportDetails": "8 role(s) that do not require approval to activate found:\u003cbr/\u003eApplication Administrator, Cloud Application Administrator, Exchange Administrator, Global Administrator, Hybrid Identity Administrator, Privileged Role Administrator, SharePoint Administrator, User Administrator", - "Requirement": "Activation of highly privileged roles SHOULD require approval", - "RequirementMet": false - }, - { - "ActualValue": [ - "Application Administrator", - "Cloud Application Administrator", - "Exchange Administrator", - "Global Administrator", - "Hybrid Identity Administrator", - "Privileged Role Administrator", - "SharePoint Administrator", - "User Administrator" - ], - "Commandlet": "Get-MgRoleManagementDirectoryRoleAssignmentScheduleInstance", - "Control": "AAD 2.16", - "Criticality": "Shall", - "ReportDetails": "8 role(s) without notification e-mail configured for role assignments found:\u003cbr/\u003eApplication Administrator, Cloud Application Administrator, Exchange Administrator, Global Administrator, Hybrid Identity Administrator, Privileged Role Administrator, SharePoint Administrator, User Administrator", - "Requirement": "Eligible and Active highly privileged role assignments SHALL trigger an alert", - "RequirementMet": false - }, - { - "ActualValue": [ - "Application Administrator", - "Cloud Application Administrator", - "Exchange Administrator", - "Global Administrator", - "Hybrid Identity Administrator", - "Privileged Role Administrator", - "SharePoint Administrator", - "User Administrator" - ], - "Commandlet": "Get-MgRoleManagementDirectoryRoleAssignmentScheduleInstance", - "Control": "AAD 2.16", - "Criticality": "Shall", - "ReportDetails": "Requirement not met", - "Requirement": "User activation of the Global Administrator role SHALL trigger an alert", - "RequirementMet": false - }, - { - "ActualValue": [ - "Application Administrator", - "Cloud Application Administrator", - "Exchange Administrator", - "Hybrid Identity Administrator", - "Privileged Role Administrator", - "SharePoint Administrator", - "User Administrator" - ], - "Commandlet": "Get-MgRoleManagementDirectoryRoleAssignmentScheduleInstance", - "Control": "AAD 2.16", - "Criticality": "Should", - "ReportDetails": "7 role(s) without notification e-mail configured for role activations found:\u003cbr/\u003eApplication Administrator, Cloud Application Administrator, Exchange Administrator, Hybrid Identity Administrator, Privileged Role Administrator, SharePoint Administrator, User Administrator", - "Requirement": "User activation of other highly privileged roles SHOULD trigger an alert", - "RequirementMet": false - }, - { - "ActualValue": [ - "FNU LNU" - ], - "Commandlet": "Get-MgDirectoryRoleMember", - "Control": "AAD 2.11", - "Criticality": "Shall", - "ReportDetails": "1 global admin(s) found:\u003cbr/\u003eFNU LNU", - "Requirement": "A minimum of two users and a maximum of four users SHALL be provisioned with the Global Administrator role", - "RequirementMet": false - }, - { - "ActualValue": [ - "Global Administrator" - ], - "Commandlet": "Get-MgRoleManagementDirectoryRoleAssignmentScheduleInstance", - "Control": "AAD 2.14", - "Criticality": "Shall", - "ReportDetails": "1 role(s) assigned to users outside of PIM:\u003cbr/\u003eGlobal Administrator", - "Requirement": "Provisioning of users to highly privileged roles SHALL NOT occur outside of a PAM system, such as the Azure AD PIM service, because this bypasses the controls the PAM system provides", - "RequirementMet": false - }, - { - "ActualValue": false, - "Commandlet": [ - "Get-AntiPhishPolicy" - ], - "Control": "Defender 2.5", - "Criticality": "Shall", - "ReportDetails": "Requirement not met", - "Requirement": "All safety tips SHALL be enabled: domain impersonation default policy", - "RequirementMet": false - }, - { - "ActualValue": false, - "Commandlet": [ - "Get-AntiPhishPolicy" - ], - "Control": "Defender 2.5", - "Criticality": "Shall", - "ReportDetails": "Requirement not met", - "Requirement": "All safety tips SHALL be enabled: first contact default policy", - "RequirementMet": false - }, - { - "ActualValue": false, - "Commandlet": [ - "Get-AntiPhishPolicy" - ], - "Control": "Defender 2.5", - "Criticality": "Shall", - "ReportDetails": "Requirement not met", - "Requirement": "All safety tips SHALL be enabled: user impersonation default policy", - "RequirementMet": false - }, - { - "ActualValue": false, - "Commandlet": [ - "Get-AntiPhishPolicy" - ], - "Control": "Defender 2.5", - "Criticality": "Shall", - "ReportDetails": "Requirement not met", - "Requirement": "All safety tips SHALL be enabled: user impersonation unusual characters default policy", - "RequirementMet": false - }, - { - "ActualValue": true, - "Commandlet": [ - "Get-AntiPhishPolicy" - ], - "Control": "Defender 2.5", - "Criticality": "Shall", - "ReportDetails": "Requirement met", - "Requirement": "All safety tips SHALL be enabled: \"?\" for unauthenticated senders for spoof default policy", - "RequirementMet": true - }, - { - "ActualValue": true, - "Commandlet": [ - "Get-AntiPhishPolicy" - ], - "Control": "Defender 2.5", - "Criticality": "Shall", - "ReportDetails": "Requirement met", - "Requirement": "All safety tips SHALL be enabled: \"via\" tag default policy", - "RequirementMet": true - }, - { - "ActualValue": true, - "Commandlet": [ - "Get-HostedContentFilterPolicy" - ], - "Control": "Defender 2.6", - "Criticality": "Shall", - "ReportDetails": "Requirement met", - "Requirement": "Zero-hour auto purge (ZAP) SHALL be enabled for phishing: default policy", - "RequirementMet": true - }, - { - "ActualValue": true, - "Commandlet": [ - "Get-HostedContentFilterPolicy" - ], - "Control": "Defender 2.6", - "Criticality": "Shall", - "ReportDetails": "Requirement met", - "Requirement": "Zero-hour auto purge (ZAP) SHALL be enabled for spam messages: default policy", - "RequirementMet": true - }, - { - "ActualValue": true, - "Commandlet": [ - "Get-HostedContentFilterPolicy" - ], - "Control": "Defender 2.6", - "Criticality": "Shall", - "ReportDetails": "Requirement met", - "Requirement": "Zero-hour auto purge (ZAP) SHALL be enabled: default policy", - "RequirementMet": true - }, - { - "ActualValue": true, - "Commandlet": [ - "Get-HostedContentFilterPolicy" - ], - "Control": "Defender 2.6", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "Spam safety tips SHOULD be turned on: default policy", - "RequirementMet": true - }, - { - "ActualValue": 7, - "Commandlet": [ - "Get-HostedContentFilterPolicy" - ], - "Control": "Defender 2.6", - "Criticality": "Should", - "ReportDetails": "Requirement not met", - "Requirement": "The bulk complaint level (BCL) threshold SHOULD be set to six or lower: default policy", - "RequirementMet": false - }, - { - "ActualValue": 15, - "Commandlet": [ - "Get-HostedContentFilterPolicy" - ], - "Control": "Defender 2.6", - "Criticality": "Should", - "ReportDetails": "Requirement not met", - "Requirement": "Spam in quarantine SHOULD be retained for at least 30 days: default policy", - "RequirementMet": false - }, - { - "ActualValue": "MoveToJmf", - "Commandlet": [ - "Get-AntiPhishPolicy" - ], - "Control": "Defender 2.5", - "Criticality": "Shall", - "ReportDetails": "Requirement not met", - "Requirement": "Mail classified as spoofed SHALL be quarantined: default policy", - "RequirementMet": false - }, - { - "ActualValue": "MoveToJmf", - "Commandlet": [ - "Get-HostedContentFilterPolicy" - ], - "Control": "Defender 2.6", - "Criticality": "Shall", - "ReportDetails": "Requirement met", - "Requirement": "High confidence spam SHALL be moved to either the junk email folder or the quarantine folder: default policy", - "RequirementMet": true - }, - { - "ActualValue": "MoveToJmf", - "Commandlet": [ - "Get-HostedContentFilterPolicy" - ], - "Control": "Defender 2.6", - "Criticality": "Shall", - "ReportDetails": "Requirement met", - "Requirement": "Spam SHALL be moved to either the junk email folder or the quarantine folder: default policy", - "RequirementMet": true - }, - { - "ActualValue": "MoveToJmf", - "Commandlet": [ - "Get-HostedContentFilterPolicy" - ], - "Control": "Defender 2.6", - "Criticality": "Shall", - "ReportDetails": "Requirement not met", - "Requirement": "Phishing SHALL be quarantined: default policy", - "RequirementMet": false - }, - { - "ActualValue": "MoveToJmf", - "Commandlet": [ - "Get-HostedContentFilterPolicy" - ], - "Control": "Defender 2.6", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "Bulk email SHOULD be moved to either the junk email folder or the quarantine folder: default policy", - "RequirementMet": true - }, - { - "ActualValue": "NoAction", - "Commandlet": [ - "Get-AntiPhishPolicy" - ], - "Control": "Defender 2.5", - "Criticality": "Shall", - "ReportDetails": "Requirement not met", - "Requirement": "Message action SHALL be set to quarantine if the message is detected as impersonated: domains default policy", - "RequirementMet": false - }, - { - "ActualValue": "NoAction", - "Commandlet": [ - "Get-AntiPhishPolicy" - ], - "Control": "Defender 2.5", - "Criticality": "Shall", - "ReportDetails": "Requirement not met", - "Requirement": "Message action SHALL be set to quarantine if the message is detected as impersonated: mailbox default policy", - "RequirementMet": false - }, - { - "ActualValue": "NoAction", - "Commandlet": [ - "Get-AntiPhishPolicy" - ], - "Control": "Defender 2.5", - "Criticality": "Shall", - "ReportDetails": "Requirement not met", - "Requirement": "Message action SHALL be set to quarantine if the message is detected as impersonated: users default policy", - "RequirementMet": false - }, - { - "ActualValue": "Quarantine", - "Commandlet": [ - "Get-HostedContentFilterPolicy" - ], - "Control": "Defender 2.6", - "Criticality": "Shall", - "ReportDetails": "Requirement met", - "Requirement": "High confidence phishing SHALL be quarantined: default policy", - "RequirementMet": true - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - - ], - "Control": "Defender 2.10", - "Criticality": "Shall/Not-Implemented", - "ReportDetails": "Currently cannot be checked automatically. See Defender Secure Configuration Baseline policy 2.10 for instructions on manual check", - "Requirement": "Advanced audit SHALL be enabled", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - - ], - "Control": "Defender 2.10", - "Criticality": "Shall/Not-Implemented", - "ReportDetails": "Currently cannot be checked automatically. See Defender Secure Configuration Baseline policy 2.10 for instructions on manual check", - "Requirement": "Audit logs SHALL be maintained for at least the minimum duration dictated by OMB M-21-31", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - - ], - "Control": "Defender 2.2", - "Criticality": "Should/Not-Implemented", - "ReportDetails": "Currently cannot be checked automatically. See Defender Secure Configuration Baseline policy 2.2 for instructions on manual check", - "Requirement": "A list of apps that are not allowed to access files protected by DLP policy SHOULD be defined", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - - ], - "Control": "Defender 2.2", - "Criticality": "Should/Not-Implemented", - "ReportDetails": "Currently cannot be checked automatically. See Defender Secure Configuration Baseline policy 2.2 for instructions on manual check", - "Requirement": "A list of browsers that are not allowed to access files protected by DLP policy SHOULD be defined", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - - ], - "Control": "Defender 2.9", - "Criticality": "Should/Not-Implemented", - "ReportDetails": "Currently cannot be checked automatically. See Defender Secure Configuration Baseline policy 2.9 for instructions on manual check", - "Requirement": "The alerts SHOULD be sent to a monitored address or incorporated into a SIEM", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - "Get-AdminAuditLogConfig" - ], - "Control": "Defender 2.10", - "Criticality": "Shall", - "ReportDetails": "Requirement not met", - "Requirement": "Unified audit logging SHALL be enabled", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - "Get-AntiPhishPolicy" - ], - "Control": "Defender 2.5", - "Criticality": "Should", - "ReportDetails": "No users are included for targeted user protection.", - "Requirement": "User impersonation protection SHOULD be enabled for key agency leaders", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - "Get-AntiPhishPolicy" - ], - "Control": "Defender 2.5", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "All safety tips SHOULD be enabled: \"?\" for unauthenticated senders for spoof non-default policies", - "RequirementMet": true - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - "Get-AntiPhishPolicy" - ], - "Control": "Defender 2.5", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "All safety tips SHOULD be enabled: \"via\" tag non-default policies", - "RequirementMet": true - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - "Get-AntiPhishPolicy" - ], - "Control": "Defender 2.5", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "All safety tips SHOULD be enabled: domain impersonation non-default policies", - "RequirementMet": true - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - "Get-AntiPhishPolicy" - ], - "Control": "Defender 2.5", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "All safety tips SHOULD be enabled: first contact non-default policies", - "RequirementMet": true - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - "Get-AntiPhishPolicy" - ], - "Control": "Defender 2.5", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "All safety tips SHOULD be enabled: user impersonation non-default policies", - "RequirementMet": true - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - "Get-AntiPhishPolicy" - ], - "Control": "Defender 2.5", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "All safety tips SHOULD be enabled: user impersonation unusual characters non-default policies", - "RequirementMet": true - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - "Get-AntiPhishPolicy" - ], - "Control": "Defender 2.5", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "Mail classified as spoofed SHOULD be quarantined: non-default policies", - "RequirementMet": true - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - "Get-AntiPhishPolicy" - ], - "Control": "Defender 2.5", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "Message action SHOULD be set to quarantine if the message is detected as impersonated: domains non-default policies", - "RequirementMet": true - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - "Get-AntiPhishPolicy" - ], - "Control": "Defender 2.5", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "Message action SHOULD be set to quarantine if the message is detected as impersonated: mailbox non-default policies", - "RequirementMet": true - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - "Get-AntiPhishPolicy" - ], - "Control": "Defender 2.5", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "Message action SHOULD be set to quarantine if the message is detected as impersonated: users non-default policies", - "RequirementMet": true - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - "Get-AntiPhishPolicy" - ], - "Control": "Defender 2.5", - "Criticality": "Should", - "ReportDetails": "Requirement not met", - "Requirement": "Domain impersonation protection SHOULD be enabled for domains owned by the agency", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - "Get-AntiPhishPolicy" - ], - "Control": "Defender 2.5", - "Criticality": "Should", - "ReportDetails": "Requirement not met", - "Requirement": "Intelligence for impersonation protection SHALL be enabled", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - "Get-AntiPhishPolicy" - ], - "Control": "Defender 2.5", - "Criticality": "Should", - "ReportDetails": "The Custom Domains protection policies: Enabled, EnableTargetedDomainsProtection, and TargetedDomainsToProtect are not set correctly", - "Requirement": "Domain impersonation protection SHOULD be added for frequent partners", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - "Get-AtpPolicyForO365" - ], - "Control": "Defender 2.8", - "Criticality": "Should", - "ReportDetails": "Requirement not met", - "Requirement": "Safe attachments SHOULD be enabled for SharePoint, OneDrive, and Microsoft Teams", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - "Get-DLPCompliancePolicy" - ], - "Control": "Defender 2.2", - "Criticality": "Should", - "ReportDetails": "No policy found that applies to OneDrive.", - "Requirement": "The custom policy SHOULD be applied in OneDrive", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - "Get-DlpComplianceRule" - ], - "Control": "Defender 2.2", - "Criticality": "Shall", - "ReportDetails": "No matching rule found for U.S. Individual Taxpayer Identification Number (ITIN)", - "Requirement": "A custom policy SHALL be configured to protect PII and sensitive information, as defined by the agency: U.S. Individual Taxpayer Identification Number (ITIN)", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - "Get-DlpComplianceRule" - ], - "Control": "Defender 2.2", - "Criticality": "Shall", - "ReportDetails": "No matching rule found for U.S. Social Security Number (SSN)", - "Requirement": "A custom policy SHALL be configured to protect PII and sensitive information, as defined by the agency: U.S. Social Security Number (SSN)", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - "Get-EOPProtectionPolicyRule" - ], - "Control": "Defender 2.1", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "Standard Preset security profiles SHOULD NOT be used", - "RequirementMet": true - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - "Get-EOPProtectionPolicyRule" - ], - "Control": "Defender 2.1", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "Strict Preset security profiles SHOULD NOT be used", - "RequirementMet": true - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - "Get-HostedContentFilterPolicy" - ], - "Control": "Defender 2.6", - "Criticality": "Shall", - "ReportDetails": "Requirement met", - "Requirement": "Allowed senders MAY be added but allowed domains SHALL NOT be added: default policy", - "RequirementMet": true - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - "Get-HostedContentFilterPolicy" - ], - "Control": "Defender 2.6", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "Allowed senders MAY be added but allowed domains SHOULD NOT be added: non-default", - "RequirementMet": true - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - "Get-HostedContentFilterPolicy" - ], - "Control": "Defender 2.6", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "Bulk email SHOULD be moved to either the junk email folder or the quarantine folder: non-default policies", - "RequirementMet": true - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - "Get-HostedContentFilterPolicy" - ], - "Control": "Defender 2.6", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "High confidence phishing SHOULD be quarantined: non-default policies", - "RequirementMet": true - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - "Get-HostedContentFilterPolicy" - ], - "Control": "Defender 2.6", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "High confidence spam SHOULD be moved to either the junk email folder or the quarantine folder: non-default policies", - "RequirementMet": true - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - "Get-HostedContentFilterPolicy" - ], - "Control": "Defender 2.6", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "Phishing SHOULD be quarantined: non-default policies", - "RequirementMet": true - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - "Get-HostedContentFilterPolicy" - ], - "Control": "Defender 2.6", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "Spam SHOULD be moved to either the junk email folder or the quarantine folder: non-default policies", - "RequirementMet": true - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - "Get-HostedContentFilterPolicy" - ], - "Control": "Defender 2.6", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "Spam in quarantine SHOULD be retained for at least 30 days: non-default policies", - "RequirementMet": true - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - "Get-HostedContentFilterPolicy" - ], - "Control": "Defender 2.6", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "Spam safety tips SHOULD be turned on: non-default policies", - "RequirementMet": true - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - "Get-HostedContentFilterPolicy" - ], - "Control": "Defender 2.6", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "The bulk complaint level (BCL) threshold SHOULD be set to six or lower: non-default policies", - "RequirementMet": true - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - "Get-HostedContentFilterPolicy" - ], - "Control": "Defender 2.6", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "Zero-hour auto purge (ZAP) SHOULD be enabled for Spam: non-default", - "RequirementMet": true - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - "Get-HostedContentFilterPolicy" - ], - "Control": "Defender 2.6", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "Zero-hour auto purge (ZAP) SHOULD be enabled for phishing: non-default", - "RequirementMet": true - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - "Get-HostedContentFilterPolicy" - ], - "Control": "Defender 2.6", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "Zero-hour auto purge (ZAP) SHOULD be enabled: non-default", - "RequirementMet": true - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - "Get-MalwareFilterPolicy" - ], - "Control": "Defender 2.3", - "Criticality": "Should", - "ReportDetails": "No malware policies found that block .cmd files.", - "Requirement": "Disallowed file types SHALL be determined and set. At a minimum, click-to-run files SHOULD be blocked: cmd files", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - "Get-MalwareFilterPolicy" - ], - "Control": "Defender 2.3", - "Criticality": "Should", - "ReportDetails": "No malware policies found that block .exe files.", - "Requirement": "Disallowed file types SHALL be determined and set. At a minimum, click-to-run files SHOULD be blocked: exe files", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - "Get-MalwareFilterPolicy" - ], - "Control": "Defender 2.3", - "Criticality": "Should", - "ReportDetails": "No malware policies found that block .vbe files.", - "Requirement": "Disallowed file types SHALL be determined and set. At a minimum, click-to-run files SHOULD be blocked: vbe files", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - "Get-MalwareFilterPolicy" - ], - "Control": "Defender 2.4", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "Zero-hour Auto Purge (ZAP) for malware SHOULD be enabled in the default anti-malware policy and in all existing custom policies", - "RequirementMet": true - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - "Get-SafeAttachmentPolicy", - "Get-SafeAttachmentRule", - "Get-AcceptedDomain" - ], - "Control": "Defender 2.8", - "Criticality": "Shall", - "ReportDetails": "No enabled policy found with action set to block that apply to all domains", - "Requirement": "The action for malware in email attachments SHALL be set to block", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - "Get-SafeAttachmentPolicy", - "Get-SafeAttachmentRule", - "Get-AcceptedDomain" - ], - "Control": "Defender 2.8", - "Criticality": "Should", - "ReportDetails": "No enabled policy found with action set to block and at least one contact specified", - "Requirement": "Redirect emails with detected attachments to an agency-specified email SHOULD be enabled", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - "Get-SafeAttachmentRule", - "Get-AcceptedDomain" - ], - "Control": "Defender 2.8", - "Criticality": "Shall", - "ReportDetails": "No policy found that applies to all domains: tqhjy.onmicrosoft.com", - "Requirement": "At least one Safe Attachments Policy SHALL include all agency domains-and by extension-all users", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - "Get-SafeLinksPolicy", - "Get-SafeLinksRule" - ], - "Control": "Defender 2.7", - "Criticality": "Shall", - "ReportDetails": "Requirement not met", - "Requirement": "Internal agency email messages SHALL have safe links enabled", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - "Get-SafeLinksPolicy", - "Get-SafeLinksRule" - ], - "Control": "Defender 2.7", - "Criticality": "Shall", - "ReportDetails": "Requirement not met", - "Requirement": "Malicious link click checking SHALL be enabled with Microsoft Teams", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - "Get-SafeLinksPolicy", - "Get-SafeLinksRule" - ], - "Control": "Defender 2.7", - "Criticality": "Shall", - "ReportDetails": "Requirement not met", - "Requirement": "Real-time suspicious URL and file-link scanning SHALL be enabled", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - "Get-SafeLinksPolicy", - "Get-SafeLinksRule" - ], - "Control": "Defender 2.7", - "Criticality": "Shall", - "ReportDetails": "Requirement not met", - "Requirement": "Safe Links in Office 365 apps SHALL be turned on", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - "Get-SafeLinksPolicy", - "Get-SafeLinksRule" - ], - "Control": "Defender 2.7", - "Criticality": "Shall", - "ReportDetails": "Requirement not met", - "Requirement": "URL rewriting and malicious link click checking SHALL be enabled", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - "Get-SafeLinksPolicy", - "Get-SafeLinksRule" - ], - "Control": "Defender 2.7", - "Criticality": "Shall", - "ReportDetails": "Requirement not met", - "Requirement": "URLs SHALL be scanned completely before message delivery", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - "Get-SafeLinksPolicy", - "Get-SafeLinksRule" - ], - "Control": "Defender 2.7", - "Criticality": "Shall", - "ReportDetails": "Requirement not met", - "Requirement": "User click tracking SHALL be enabled", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - "Get-SafeLinksPolicy", - "Get-SafeLinksRule" - ], - "Control": "Defender 2.7", - "Criticality": "Shall", - "ReportDetails": "Requirement not met", - "Requirement": "Users SHALL NOT be enabled to click through to the original URL", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - "Get-SafeLinksRule", - "Get-AcceptedDomain" - ], - "Control": "Defender 2.7", - "Criticality": "Shall", - "ReportDetails": "No policy found that applies to all domains: tqhjy.onmicrosoft.com", - "Requirement": "The Safe Links Policy SHALL include all agency domains-and by extension-all users", - "RequirementMet": false - }, - { - "ActualValue": [ - "Default" - ], - "Commandlet": [ - "Get-MalwareFilterPolicy" - ], - "Control": "Defender 2.3", - "Criticality": "Shall", - "ReportDetails": "1 malware policy(ies) found that do(es) not have the common attachments filter enabled: Default", - "Requirement": "The common attachments filter SHALL be enabled in the default anti-malware policy and in all existing policies", - "RequirementMet": false - }, - { - "ActualValue": [ - "Default Teams DLP policy rule" - ], - "Commandlet": [ - "Get-DlpComplianceRule" - ], - "Control": "Defender 2.2", - "Criticality": "Should", - "ReportDetails": "1 rule(s) found that do(es) not notify at least one user: Default Teams DLP policy rule", - "Requirement": "Notifications to inform users and help educate them on the proper use of sensitive information SHOULD be enabled", - "RequirementMet": false - }, - { - "ActualValue": [ - "Default Teams DLP policy rule", - "Items containing 1-9 credit card numbers shared externally", - "Items with 10 or more credit card numbers shared externally" - ], - "Commandlet": [ - "Get-DlpComplianceRule" - ], - "Control": "Defender 2.2", - "Criticality": "Shall", - "ReportDetails": "Requirement met", - "Requirement": "A custom policy SHALL be configured to protect PII and sensitive information, as defined by the agency: Credit Card Number", - "RequirementMet": true - }, - { - "ActualValue": [ - "Default Teams DLP policy rule", - "Items containing 1-9 credit card numbers shared externally", - "Items with 10 or more credit card numbers shared externally" - ], - "Commandlet": [ - "Get-DlpComplianceRule" - ], - "Control": "Defender 2.2", - "Criticality": "Should", - "ReportDetails": "3 rule(s) found that do(es) not block access: Default Teams DLP policy rule, Items containing 1-9 credit card numbers shared externally, Items with 10 or more credit card numbers shared externally", - "Requirement": "The action for the DLP policy SHOULD be set to block sharing sensitive information with everyone when DLP conditions are met", - "RequirementMet": false - }, - { - "ActualValue": [ - "Malware campaign detected after delivery", - "Unusual increase in email reported as phish" - ], - "Commandlet": [ - "Get-ProtectionAlert" - ], - "Control": "Defender 2.9", - "Criticality": "Shall", - "ReportDetails": "2 disabled required alert(s) found: Malware campaign detected after delivery, Unusual increase in email reported as phish", - "Requirement": "At a minimum, the alerts required by the Exchange Online Minimum Viable Secure Configuration Baseline SHALL be enabled", - "RequirementMet": false - }, - { - "ActualValue": [ - { - "Locations": [ - "All" - ], - "Name": "Default Office 365 DLP policy", - "Workload": "Exchange, SharePoint, OneDriveForBusiness" - } - ], - "Commandlet": [ - "Get-DLPCompliancePolicy" - ], - "Control": "Defender 2.2", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "The custom policy SHOULD be applied in Exchange", - "RequirementMet": true - }, - { - "ActualValue": [ - { - "Locations": [ - "All" - ], - "Name": "Default Office 365 DLP policy", - "Workload": "Exchange, SharePoint, OneDriveForBusiness" - } - ], - "Commandlet": [ - "Get-DLPCompliancePolicy" - ], - "Control": "Defender 2.2", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "The custom policy SHOULD be applied in SharePoint", - "RequirementMet": true - }, - { - "ActualValue": [ - { - "Locations": [ - "All" - ], - "Name": "Default policy for Teams", - "Workload": "Exchange, SharePoint, OneDriveForBusiness, Teams" - } - ], - "Commandlet": [ - "Get-DLPCompliancePolicy" - ], - "Control": "Defender 2.2", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "The custom policy SHOULD be applied in Teams", - "RequirementMet": true - }, - { - "ActualValue": false, - "Commandlet": "Get-HostedConnectionFilterPolicy", - "Control": "EXO 2.12", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "Safe lists SHOULD NOT be enabled", - "RequirementMet": true - }, - { - "ActualValue": false, - "Commandlet": "Get-OrganizationConfig", - "Control": "EXO 2.13", - "Criticality": "Shall", - "ReportDetails": "Requirement met", - "Requirement": "Mailbox auditing SHALL be enabled", - "RequirementMet": true - }, - { - "ActualValue": true, - "Commandlet": "Get-TransportConfig", - "Control": "EXO 2.5", - "Criticality": "Shall", - "ReportDetails": "Requirement met", - "Requirement": "SMTP AUTH SHALL be disabled in Exchange Online", - "RequirementMet": true - }, - { - "ActualValue": [ - - ], - "Commandlet": "", - "Control": "EXO 2.10", - "Criticality": "Shall/3rd Party", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "Requirement": "Emails SHALL be scanned for malware", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": "", - "Control": "EXO 2.10", - "Criticality": "Shall/3rd Party", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "Requirement": "Emails identified as containing malware SHALL be quarantined or dropped", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": "", - "Control": "EXO 2.10", - "Criticality": "Should/3rd Party", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "Requirement": "Email scanning SHOULD be capable of reviewing emails after delivery", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": "", - "Control": "EXO 2.11", - "Criticality": "Should/3rd Party", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "Requirement": "Impersonation protection checks SHOULD be used", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": "", - "Control": "EXO 2.11", - "Criticality": "Should/3rd Party", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "Requirement": "The phishing protection solution SHOULD include an AI-based phishing detection tool comparable to EOP Mailbox Intelligence", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": "", - "Control": "EXO 2.11", - "Criticality": "Should/3rd Party", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "Requirement": "User warnings, comparable to the user safety tips included with EOP, SHOULD be displayed", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": "", - "Control": "EXO 2.14", - "Criticality": "Shall/3rd Party", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "Requirement": "A spam filter SHALL be enabled. The filtering solution selected SHOULD offer services comparable to the native spam filtering offered by Microsoft", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": "", - "Control": "EXO 2.14", - "Criticality": "Shall/3rd Party", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "Requirement": "Allowed senders MAY be added, but allowed domains SHALL NOT be added", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": "", - "Control": "EXO 2.14", - "Criticality": "Shall/3rd Party", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "Requirement": "Spam and high confidence spam SHALL be moved to either the junk email folder or the quarantine folder", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": "", - "Control": "EXO 2.15", - "Criticality": "Should/3rd Party", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "Requirement": "Direct download links SHOULD be scanned for malware", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": "", - "Control": "EXO 2.15", - "Criticality": "Should/3rd Party", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "Requirement": "URL comparison with a block-list SHOULD be enabled", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": "", - "Control": "EXO 2.15", - "Criticality": "Should/3rd Party", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "Requirement": "User click tracking SHOULD be enabled", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": "", - "Control": "EXO 2.16", - "Criticality": "Shall/3rd Party", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "Requirement": "At a minimum, the following alerts SHALL be enabled...[see Exchange Online secure baseline for list]", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": "", - "Control": "EXO 2.16", - "Criticality": "Should/3rd Party", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "Requirement": "The alerts SHOULD be sent to a monitored address or incorporated into a SIEM", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": "", - "Control": "EXO 2.17", - "Criticality": "Shall/3rd Party", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "Requirement": "Advanced audit SHALL be enabled", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": "", - "Control": "EXO 2.17", - "Criticality": "Shall/3rd Party", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "Requirement": "Audit logs SHALL be maintained for at least the minimum duration dictated by OMB M-21-31", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": "", - "Control": "EXO 2.17", - "Criticality": "Shall/3rd Party", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "Requirement": "Unified audit logging SHALL be enabled", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": "", - "Control": "EXO 2.2", - "Criticality": "Shall/Not-Implemented", - "ReportDetails": "Currently cannot be checked automatically. See Exchange Online Secure Configuration Baseline policy 2.# for instructions on manual check", - "Requirement": "A list of approved IP addresses for sending mail SHALL be maintained", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": "", - "Control": "EXO 2.8", - "Criticality": "Shall/3rd Party", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "Requirement": "A DLP solution SHALL be used. The selected DLP solution SHOULD offer services comparable to the native DLP solution offered by Microsoft", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": "", - "Control": "EXO 2.8", - "Criticality": "Shall/3rd Party", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "Requirement": "The DLP solution SHALL protect PII and sensitive information, as defined by the agency. At a minimum, the sharing of credit card numbers, Taxpayer Identification Numbers (TIN), and Social Security Numbers (SSN) via email SHALL be restricted", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": "", - "Control": "EXO 2.9", - "Criticality": "Shall/3rd Party", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "Requirement": "Disallowed file types SHALL be determined and set. At a minimum, click-to-run files SHOULD be blocked (e.g., .exe, .cmd, and .vbe)", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": "", - "Control": "EXO 2.9", - "Criticality": "Shall/3rd Party", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "Requirement": "Emails SHALL be filtered by the file types of included attachments. The selected filtering solution SHOULD offer services comparable to Microsoft Defender\u0027s Common Attachment Filter", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": "", - "Control": "EXO 2.9", - "Criticality": "Should/3rd Party", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "Requirement": "The attachment filter SHOULD attempt to determine the true file type and assess the file extension", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": "Get-HostedConnectionFilterPolicy", - "Control": "EXO 2.12", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "IP allow lists SHOULD NOT be created", - "RequirementMet": true - }, - { - "ActualValue": [ - - ], - "Commandlet": "Get-TransportRule", - "Control": "EXO 2.7", - "Criticality": "Shall", - "ReportDetails": "No transport rule found with that applies to emails received from outside the organization", - "Requirement": "External sender warnings SHALL be implemented", - "RequirementMet": false - }, - { - "ActualValue": [ - "Anonymous:CalendarSharingFreeBusyReviewer", - "*:CalendarSharingFreeBusySimple" - ], - "Commandlet": "Get-SharingPolicy", - "Control": "EXO 2.6", - "Criticality": "Shall", - "ReportDetails": "Requirement met", - "Requirement": "Calendar details SHALL NOT be shared with all domains, although they MAY be shared with specific domains", - "RequirementMet": true - }, - { - "ActualValue": [ - "Anonymous:CalendarSharingFreeBusyReviewer", - "*:CalendarSharingFreeBusySimple" - ], - "Commandlet": "Get-SharingPolicy", - "Control": "EXO 2.6", - "Criticality": "Shall", - "ReportDetails": "Requirement met", - "Requirement": "Contact folders SHALL NOT be shared with all domains, although they MAY be shared with specific domains", - "RequirementMet": true - }, - { - "ActualValue": [ - [ - { - "domain": "tqhjy.onmicrosoft.com", - "rdata": "" - } - ], - [ - - ] - ], - "Commandlet": "Get-DkimSigningConfig, Resolve-DnsName", - "Control": "EXO 2.3", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "DKIM SHOULD be enabled for any custom domain", - "RequirementMet": true - }, - { - "ActualValue": [ - { - "domain": "tqhjy.onmicrosoft.com", - "rdata": "" - } - ], - "Commandlet": "Resolve-DnsName", - "Control": "EXO 2.4", - "Criticality": "Shall", - "ReportDetails": "1 of 1 agency domain(s) found in violation: tqhjy.onmicrosoft.com", - "Requirement": "A DMARC policy SHALL be published for every second-level domain", - "RequirementMet": false - }, - { - "ActualValue": [ - { - "domain": "tqhjy.onmicrosoft.com", - "rdata": "" - } - ], - "Commandlet": "Resolve-DnsName", - "Control": "EXO 2.4", - "Criticality": "Shall", - "ReportDetails": "1 of 1 agency domain(s) found in violation: tqhjy.onmicrosoft.com", - "Requirement": "An agency point of contact SHOULD be included for aggregate and/or failure reports", - "RequirementMet": false - }, - { - "ActualValue": [ - { - "domain": "tqhjy.onmicrosoft.com", - "rdata": "" - } - ], - "Commandlet": "Resolve-DnsName", - "Control": "EXO 2.4", - "Criticality": "Shall", - "ReportDetails": "1 of 1 agency domain(s) found in violation: tqhjy.onmicrosoft.com", - "Requirement": "The DMARC message rejection option SHALL be \"p=reject\"", - "RequirementMet": false - }, - { - "ActualValue": [ - { - "domain": "tqhjy.onmicrosoft.com", - "rdata": "" - } - ], - "Commandlet": "Resolve-DnsName", - "Control": "EXO 2.4", - "Criticality": "Shall", - "ReportDetails": "1 of 1 agency domain(s) found in violation: tqhjy.onmicrosoft.com", - "Requirement": "The DMARC point of contact for aggregate reports SHALL include reports@dmarc.cyber.dhs.gov", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": "Resolve-DnsName", - "Control": "EXO 2.2", - "Criticality": "Shall", - "ReportDetails": "Requirement met", - "Requirement": "An SPF policy(s) that designates only these addresses as approved senders SHALL be published", - "RequirementMet": true - }, - { - "ActualValue": [ - "*" - ], - "Commandlet": "Get-RemoteDomain", - "Control": "EXO 2.1", - "Criticality": "Shall", - "ReportDetails": "1 remote domain(s) that allows automatic forwarding: *", - "Requirement": "Automatic forwarding to external domains SHALL be disabled", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - - ], - "Control": "OneDrive 2.6", - "Criticality": "Shall/Not-Implemented", - "ReportDetails": "Currently cannot be checked automatically. See Onedrive Secure Configuration Baseline policy 2.6 for instructions on manual check", - "Requirement": "OneDrive Client Sync SHALL be restricted to the local domain", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - - ], - "Control": "OneDrive 2.7", - "Criticality": "Shall/Not-Implemented", - "ReportDetails": "Currently cannot be checked automatically. See Onedrive Secure Configuration Baseline policy 2.7 for instructions on manual check", - "Requirement": "Legacy Authentication SHALL be blocked", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - "Get-SPOTenant" - ], - "Control": "OneDrive 2.1", - "Criticality": "Should", - "ReportDetails": "Requirement not met", - "Requirement": "Anyone links SHOULD be disabled", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - "Get-SPOTenant" - ], - "Control": "OneDrive 2.2", - "Criticality": "Should", - "ReportDetails": "Requirement not met", - "Requirement": "An expiration date SHOULD be set for Anyone links", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - "Get-SPOTenant" - ], - "Control": "OneDrive 2.2", - "Criticality": "Should", - "ReportDetails": "Requirement not met", - "Requirement": "Expiration date SHOULD be set to thirty days", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - "Get-SPOTenant" - ], - "Control": "OneDrive 2.3", - "Criticality": "Should", - "ReportDetails": "Requirement not met", - "Requirement": "Anyone link permissions SHOULD be limited to View", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - "Get-SPOTenant" - ], - "Control": "OneDrive 2.4", - "Criticality": "Shall", - "ReportDetails": "Requirement not met", - "Requirement": "OneDrive Client for Windows SHALL be restricted to agency-Defined Domain(s)", - "RequirementMet": false - }, - { - "ActualValue": [ - { - "AllowedDomainList": [ - - ], - "BlockMacSync": false, - "DisableReportProblemDialog": false, - "ExcludedFileExtensions": [ - "" - ], - "OptOutOfGrooveBlock": false, - "OptOutOfGrooveSoftBlock": false, - "TenantRestrictionEnabled": false - } - ], - "Commandlet": [ - "Get-SPOTenantSyncClientRestriction" - ], - "Control": "OneDrive 2.5", - "Criticality": "Shall", - "ReportDetails": "Requirement met", - "Requirement": "OneDrive Client Sync SHALL only be allowed only within the local domain", - "RequirementMet": true - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - - ], - "Control": "Sharepoint 2.3", - "Criticality": "Should/Not-Implemented", - "ReportDetails": "Currently cannot be checked automatically. See Sharepoint Secure Configuration Baseline policy 2.3 for instructions on manual check", - "Requirement": "Sharing settings for specific SharePoint sites SHOULD align to their sensitivity level", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - - ], - "Control": "Sharepoint 2.5", - "Criticality": "Shall/Not-Implemented", - "ReportDetails": "Currently cannot be checked automatically. See Sharepoint Secure Configuration Baseline policy 2.5 for instructions on manual check", - "Requirement": "Users SHALL be prevented from running custom scripts on personal sites (OneDrive)", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - "Get-SPOTenant" - ], - "Control": "Sharepoint 2.1", - "Criticality": "Shall", - "ReportDetails": "Requirement not met", - "Requirement": "File and folder links default sharing setting SHALL be set to \"Specific People (Only the People the User Specifies)\"", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - "Get-SPOTenant" - ], - "Control": "Sharepoint 2.2", - "Criticality": "Should", - "ReportDetails": "Requirement not met", - "Requirement": "External sharing SHOULD be limited to approved domains and security groups per interagency collaboration needs", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - "Get-SPOTenant" - ], - "Control": "Sharepoint 2.4", - "Criticality": "Should", - "ReportDetails": "Requirement not met", - "Requirement": "Expiration timers SHOULD be set to 30 days", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - "Get-SPOTenant" - ], - "Control": "Sharepoint 2.4", - "Criticality": "Should", - "ReportDetails": "Requirement not met", - "Requirement": "Expiration timers for \u0027guest access to a site or OneDrive\u0027 and \u0027people who use a verification code\u0027 SHOULD be set", - "RequirementMet": false - }, - { - "ActualValue": [ - { - "AllowDownloadingNonWebViewableFiles": false, - "AllowEditing": true, - "AllowSelfServiceUpgrade": true, - "AnonymousLinkExpirationInDays": 0, - "AuthenticationContextName": null, - "BlockDownloadLinksFileType": 1, - "BlockDownloadPolicy": false, - "CommentsOnSitePagesDisabled": false, - "CompatibilityLevel": 15, - "ConditionalAccessPolicy": 0, - "DefaultLinkPermission": 0, - "DefaultLinkToExistingAccess": false, - "DefaultShareLinkRole": 0, - "DefaultShareLinkScope": 0, - "DefaultSharingLinkType": 0, - "DenyAddAndCustomizePages": 2, - "DisableAppViews": 2, - "DisableCompanyWideSharingLinks": 2, - "DisableFlows": 2, - "DisableSharingForNonOwnersStatus": null, - "ExcludeBlockDownloadPolicySiteOwners": false, - "ExcludedBlockDownloadGroupIds": [ - - ], - "ExternalUserExpirationInDays": 0, - "GroupId": "00000000-0000-0000-0000-000000000000", - "HubSiteId": "00000000-0000-0000-0000-000000000000", - "InformationBarriersMode": "", - "InformationSegment": [ - - ], - "IsHubSite": false, - "IsTeamsChannelConnected": false, - "IsTeamsConnected": false, - "LastContentModifiedDate": "/Date(1669883125563)/", - "LimitedAccessFileType": 1, - "LocaleId": 1033, - "LockIssue": null, - "LockState": "Unlock", - "LoopDefaultSharingLinkRole": 0, - "LoopDefaultSharingLinkScope": -1, - "LoopOverrideSharingCapability": false, - "LoopSharingCapability": 2, - "MediaTranscription": 0, - "OverrideBlockUserInfoVisibility": 0, - "OverrideSharingCapability": false, - "OverrideTenantAnonymousLinkExpirationPolicy": false, - "OverrideTenantExternalUserExpirationPolicy": false, - "Owner": "efb52a3c-c813-4e58-855e-63e4bfb5a20e", - "PWAEnabled": 1, - "ReadOnlyForUnmanagedDevices": false, - "RelatedGroupId": "00000000-0000-0000-0000-000000000000", - "RequestFilesLinkEnabled": true, - "RequestFilesLinkExpirationInDays": -1, - "ResourceQuota": 300, - "ResourceQuotaWarningLevel": 255, - "ResourceUsageAverage": 0, - "ResourceUsageCurrent": 0, - "RestrictedAccessControl": false, - "RestrictedToGeo": 3, - "SandboxedCodeActivationCapability": 2, - "SensitivityLabel": null, - "SharingAllowedDomainList": "", - "SharingBlockedDomainList": "", - "SharingCapability": 2, - "SharingDomainRestrictionMode": 0, - "SharingLockDownCanBeCleared": true, - "SharingLockDownEnabled": false, - "ShowPeoplePickerSuggestionsForGuestUsers": false, - "SiteDefinedSharingCapability": 2, - "SocialBarOnSitePagesDisabled": false, - "Status": "Active", - "StorageQuota": 26214400, - "StorageQuotaType": null, - "StorageQuotaWarningLevel": 25574400, - "StorageUsageCurrent": 1, - "TeamsChannelType": 0, - "Template": "SITEPAGEPUBLISHING#0", - "Title": "Communication site", - "Url": "https://tqhjy.sharepoint.com/", - "WebsCount": 1 - } - ], - "Commandlet": [ - "Get-SPOSite" - ], - "Control": "Sharepoint 2.5", - "Criticality": "Shall", - "ReportDetails": "Requirement met", - "Requirement": "Users SHALL be prevented from running custom scripts on self-service created sites", - "RequirementMet": true - }, - { - "ActualValue": true, - "Commandlet": [ - "Get-CsTeamsMeetingPolicy" - ], - "Control": "Teams 2.9", - "Criticality": "Should", - "ReportDetails": "Requirement not met", - "Requirement": "Cloud video recording SHOULD be disabled in the global (org-wide default) meeting policy", - "RequirementMet": false - }, - { - "ActualValue": "AlwaysEnabled", - "Commandlet": [ - "Get-CsTeamsMeetingPolicy" - ], - "Control": "Teams 2.10", - "Criticality": "Should", - "ReportDetails": "Requirement not met", - "Requirement": "Record an event SHOULD be set to Organizer can record", - "RequirementMet": false - }, - { - "ActualValue": "EveryoneInCompany", - "Commandlet": [ - "Get-CsTeamsMeetingPolicy" - ], - "Control": "Teams 2.3", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "Internal users SHOULD be admitted automatically", - "RequirementMet": true - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - - ], - "Control": "Teams 2.11", - "Criticality": "Shall/3rd Party", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "Requirement": "A DLP solution SHALL be enabled", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - - ], - "Control": "Teams 2.11", - "Criticality": "Shall/3rd Party", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "Requirement": "The DLP solution SHALL protect Personally Identifiable Information (PII) and sensitive information, as defined by the agency. At a minimum, the sharing of credit card numbers, taxpayer Identification Numbers (TIN), and Social Security Numbers (SSN) via email SHALL be restricted", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - - ], - "Control": "Teams 2.11", - "Criticality": "Should/3rd Party", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "Requirement": "Agencies SHOULD use either the native DLP solution offered by Microsoft or a DLP solution that offers comparable services", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - - ], - "Control": "Teams 2.12", - "Criticality": "Should/3rd Party", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "Requirement": "Attachments included with Teams messages SHOULD be scanned for malware", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - - ], - "Control": "Teams 2.12", - "Criticality": "Should/3rd Party", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "Requirement": "Users SHOULD be prevented from opening or downloading files detected as malware", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - - ], - "Control": "Teams 2.13", - "Criticality": "Should/3rd Party", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "Requirement": "Direct download links SHOULD be scanned for malware", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - - ], - "Control": "Teams 2.13", - "Criticality": "Should/3rd Party", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "Requirement": "URL comparison with a block-list SHOULD be enabled", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - - ], - "Control": "Teams 2.13", - "Criticality": "Should/3rd Party", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "Requirement": "User click tracking SHOULD be enabled", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - - ], - "Control": "Teams 2.8", - "Criticality": "Shall/3rd Party", - "ReportDetails": "Cannot be checked automatically. See Microsoft Teams Secure Configuration Baseline policy 2.8 for instructions on manual check", - "Requirement": "Agencies SHALL establish policy dictating the app review and approval process to be used by the agency", - "RequirementMet": false - }, - { - "ActualValue": [ - "EveryoneInCompany", - false - ], - "Commandlet": [ - "Get-CsTeamsMeetingPolicy" - ], - "Control": "Teams 2.3", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "Anonymous users, including dial-in users, SHOULD NOT be admitted automatically", - "RequirementMet": true - }, - { - "ActualValue": [ - [ - "Global" - ], - "MicrosoftCommunicationsOnline/NOAM-ED6-A5" - ], - "Commandlet": [ - "Get-CsTeamsClientConfiguration" - ], - "Control": "Teams 2.7", - "Criticality": "Shall", - "ReportDetails": "1 Requirement not met: Email integration is enabled across domain: Global", - "Requirement": "Teams email integration SHALL be disabled", - "RequirementMet": false - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - "Get-CsTeamsAppPermissionPolicy" - ], - "Control": "Teams 2.8", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "Agencies SHOULD allow all apps published by Microsoft, but MAY block specific Microsoft apps as needed", - "RequirementMet": true - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - "Get-CsTeamsMeetingPolicy" - ], - "Control": "Teams 2.1", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "External participants SHOULD NOT be enabled to request control of shared desktops or windows in the Global (Org-wide default) meeting policy or in custom meeting policies if any exist", - "RequirementMet": true - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - "Get-CsTeamsMeetingPolicy" - ], - "Control": "Teams 2.2", - "Criticality": "Shall", - "ReportDetails": "Requirement met", - "Requirement": "Anonymous users SHALL NOT be enabled to start meetings in the Global (Org-wide default) meeting policy or in custom meeting policies if any exist", - "RequirementMet": true - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - "Get-CsTeamsMeetingPolicy" - ], - "Control": "Teams 2.4", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "Anonymous users SHOULD be enabled to join meetings", - "RequirementMet": true - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - "Get-CsTeamsMeetingPolicy" - ], - "Control": "Teams 2.9", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "For all meeting polices that allow cloud recording, recordings SHOULD be stored inside the country of that agencyGs tenant", - "RequirementMet": true - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - "Get-CsTenantFederationConfiguration" - ], - "Control": "Teams 2.4", - "Criticality": "Shall", - "ReportDetails": "Requirement met", - "Requirement": "External access SHALL only be enabled on a per-domain basis", - "RequirementMet": true - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - "Get-CsTenantFederationConfiguration" - ], - "Control": "Teams 2.5", - "Criticality": "Shall", - "ReportDetails": "Requirement met", - "Requirement": "Unmanaged users SHALL NOT be enabled to initiate contact with internal users", - "RequirementMet": true - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - "Get-CsTenantFederationConfiguration" - ], - "Control": "Teams 2.5", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "Internal users SHOULD NOT be enabled to initiate contact with unmanaged users", - "RequirementMet": true - }, - { - "ActualValue": [ - - ], - "Commandlet": [ - "Get-CsTenantFederationConfiguration" - ], - "Control": "Teams 2.6", - "Criticality": "Shall", - "ReportDetails": "Requirement met", - "Requirement": "Contact with Skype users SHALL be blocked", - "RequirementMet": true - }, - { - "ActualValue": [ - "Global" - ], - "Commandlet": [ - "Get-CsTeamsAppPermissionPolicy" - ], - "Control": "Teams 2.8", - "Criticality": "Should", - "ReportDetails": "1 meeting policy(ies) found that allow custom apps by default: Global", - "Requirement": "Agencies SHOULD NOT allow installation of all custom apps, but MAY allow specific apps as needed", - "RequirementMet": false - }, - { - "ActualValue": [ - "Global" - ], - "Commandlet": [ - "Get-CsTeamsAppPermissionPolicy" - ], - "Control": "Teams 2.8", - "Criticality": "Should", - "ReportDetails": "1 meeting policy(ies) found that allow third-party apps by default: Global", - "Requirement": "Agencies SHOULD NOT allow installation of all third-party apps, but MAY allow specific apps as needed", - "RequirementMet": false - } -] + { + "ActualValue": "", + "Commandlet": [ + "Get-MgSubscribedSku", + "Get-PrivilegedUser" + ], + "Criticality": "Shall", + "PolicyId": "MS.AAD.12.1v1", + "ReportDetails": "0 admin(s) that are not cloud-only found", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Shall/Not-Implemented", + "PolicyId": "MS.AAD.4.2v1", + "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Shall/Not-Implemented", + "PolicyId": "MS.AAD.4.3v1", + "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Shall/Not-Implemented", + "PolicyId": "MS.AAD.4.4v1", + "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Shall/Not-Implemented", + "PolicyId": "MS.AAD.5.1v1", + "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Shall/Not-Implemented", + "PolicyId": "MS.AAD.5.4v1", + "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Shall/Not-Implemented", + "PolicyId": "MS.AAD.8.1v1", + "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Should/Not-Implemented", + "PolicyId": "MS.AAD.18.2v1", + "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Should/Not-Implemented", + "PolicyId": "MS.AAD.2.2v1", + "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Should/Not-Implemented", + "PolicyId": "MS.AAD.5.2v1", + "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Should/Not-Implemented", + "PolicyId": "MS.AAD.5.3v1", + "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", + "RequirementMet": false + }, + { + "ActualValue": { + "all_allow_invite_values": [ + { + "AllowInvitesFromValue": "everyone", + "PolicyId": "authorizationPolicy" + } + ] + }, + "Commandlet": [ + "Get-MgPolicyAuthorizationPolicy" + ], + "Criticality": "Should", + "PolicyId": "MS.AAD.18.1v1", + "ReportDetails": "Permission level set to \"everyone\" (authorizationPolicy)", + "RequirementMet": false + }, + { + "ActualValue": { + "all_allowed_create_values": [ + { + "DefaultUser_AllowedToCreateApps": true, + "PolicyId": "authorizationPolicy" + } + ] + }, + "Commandlet": [ + "Get-MgPolicyAuthorizationPolicy" + ], + "Criticality": "Shall", + "PolicyId": "MS.AAD.6.1v1", + "ReportDetails": "1 authorization policies found that allow non-admin users to register third-party applications:
authorizationPolicy", + "RequirementMet": false + }, + { + "ActualValue": { + "all_consent_policies": [ + { + "IsEnabled": true, + "PolicyId": null + } + ] + }, + "Commandlet": [ + "Get-MgPolicyAdminConsentRequestPolicy" + ], + "Criticality": "Shall", + "PolicyId": "MS.AAD.7.2v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": { + "all_grant_policy_values": [ + { + "DefaultUser_DefaultGrantPolicy": [ + "ManagePermissionGrantsForSelf.microsoft-user-default-legacy" + ], + "PolicyId": "authorizationPolicy" + } + ] + }, + "Commandlet": [ + "Get-MgPolicyAuthorizationPolicy" + ], + "Criticality": "Shall", + "PolicyId": "MS.AAD.7.1v1", + "ReportDetails": "1 authorization policies found that allow non-admin users to consent to third-party applications:
authorizationPolicy", + "RequirementMet": false + }, + { + "ActualValue": { + "all_roleid_values": [ + { + "GuestUserRoleId": "10dae51f-b6af-4016-8d66-8c2a99b929b3", + "GuestUserRoleIdString": "Limited access", + "Id": "authorizationPolicy" + } + ] + }, + "Commandlet": [ + "Get-MgPolicyAuthorizationPolicy" + ], + "Criticality": "Should", + "PolicyId": "MS.AAD.18.3v1", + "ReportDetails": "Permission level set to \"Limited access\" (authorizationPolicy)", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-MgIdentityConditionalAccessPolicy" + ], + "Criticality": "Shall", + "PolicyId": "MS.AAD.9.1v1", + "ReportDetails": "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies.", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-MgIdentityConditionalAccessPolicy" + ], + "Criticality": "Should", + "PolicyId": "MS.AAD.17.1v1", + "ReportDetails": "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies.", + "RequirementMet": false + }, + { + "ActualValue": [ + "Addam Schroll", + "Andrew Huynh", + "Grant Dasher", + "Nanda Katikaneni", + "Shanti Satyapal", + "Ted Kolovos", + "Thomas Comeau" + ], + "Commandlet": [ + "Get-MgSubscribedSku", + "Get-PrivilegedUser" + ], + "Criticality": "Shall", + "PolicyId": "MS.AAD.11.1v1", + "ReportDetails": "7 global admin(s) found:
Addam Schroll, Andrew Huynh, Grant Dasher, Nanda Katikaneni, Shanti Satyapal, Ted Kolovos, Thomas Comeau", + "RequirementMet": false + }, + { + "ActualValue": [ + "Application Administrator", + "Cloud Application Administrator", + "Hybrid Identity Administrator", + "Privileged Role Administrator", + "SharePoint Administrator" + ], + "Commandlet": [ + "Get-MgSubscribedSku", + "Get-PrivilegedRole" + ], + "Criticality": "Should", + "PolicyId": "MS.AAD.15.1v1", + "ReportDetails": "5 role(s) that do not require approval to activate found:
Application Administrator, Cloud Application Administrator, Hybrid Identity Administrator, Privileged Role Administrator, SharePoint Administrator", + "RequirementMet": false + }, + { + "ActualValue": [ + "Exchange Administrator", + "Global Administrator", + "Privileged Role Administrator", + "SharePoint Administrator" + ], + "Commandlet": [ + "Get-MgSubscribedSku", + "Get-PrivilegedRole" + ], + "Criticality": "Shall", + "PolicyId": "MS.AAD.14.2v1", + "ReportDetails": "4 role(s) assigned to users outside of PIM:
Exchange Administrator, Global Administrator, Privileged Role Administrator, SharePoint Administrator", + "RequirementMet": false + }, + { + "ActualValue": [ + "Global Administrator", + "SharePoint Administrator", + "User Administrator" + ], + "Commandlet": [ + "Get-MgSubscribedSku", + "Get-PrivilegedRole" + ], + "Criticality": "Shall", + "PolicyId": "MS.AAD.14.1v1", + "ReportDetails": "3 role(s) configured to allow permanent active assignment or expiration period too long:
Global Administrator, SharePoint Administrator, User Administrator", + "RequirementMet": false + }, + { + "ActualValue": [ + "Live - Block legacy authentication" + ], + "Commandlet": [ + "Get-MgIdentityConditionalAccessPolicy" + ], + "Criticality": "Shall", + "PolicyId": "MS.AAD.1.1v1", + "ReportDetails": "1 conditional access policy(s) found that meet(s) all requirements:
Live - Block legacy authentication. View all CA policies.", + "RequirementMet": true + }, + { + "ActualValue": [ + "Live - MFA Required for Everyone" + ], + "Commandlet": [ + "Get-MgIdentityConditionalAccessPolicy" + ], + "Criticality": "Shall", + "PolicyId": "MS.AAD.4.1v1", + "ReportDetails": "1 conditional access policy(s) found that meet(s) all requirements:
Live - MFA Required for Everyone. View all CA policies.", + "RequirementMet": true + }, + { + "ActualValue": [ + "Live - MFA required for Highly Privileged Roles" + ], + "Commandlet": [ + "Get-MgSubscribedSku", + "Get-PrivilegedRole", + "Get-MgIdentityConditionalAccessPolicy" + ], + "Criticality": "Shall", + "PolicyId": "MS.AAD.13.1v1", + "ReportDetails": "1 conditional access policy(s) found that meet(s) all requirements:
Live - MFA required for Highly Privileged Roles. View all CA policies.", + "RequirementMet": true + }, + { + "ActualValue": [ + "Live - Prevent Persistent Sessions u0026 Enforce Sign-in Frequency" + ], + "Commandlet": [ + "Get-MgIdentityConditionalAccessPolicy" + ], + "Criticality": "Shall", + "PolicyId": "MS.AAD.10.1v1", + "ReportDetails": "1 conditional access policy(s) found that meet(s) all requirements:
Live - Prevent Persistent Sessions u0026 Enforce Sign-in Frequency. View all CA policies.", + "RequirementMet": true + }, + { + "ActualValue": [ + "Live - Risky Sign Ins Block Access" + ], + "Commandlet": [ + "Get-MgIdentityConditionalAccessPolicy" + ], + "Criticality": "Shall", + "PolicyId": "MS.AAD.3.1v1", + "ReportDetails": "1 conditional access policy(s) found that meet(s) all requirements:
Live - Risky Sign Ins Block Access. View all CA policies.", + "RequirementMet": true + }, + { + "ActualValue": [ + "Live - Risky Users Block Access" + ], + "Commandlet": [ + "Get-MgIdentityConditionalAccessPolicy" + ], + "Criticality": "Shall", + "PolicyId": "MS.AAD.2.1v1", + "ReportDetails": "1 conditional access policy(s) found that meet(s) all requirements:
Live - Risky Users Block Access. View all CA policies.", + "RequirementMet": true + }, + { + "ActualValue": [ + "Privileged Role Administrator" + ], + "Commandlet": [ + "Get-MgSubscribedSku", + "Get-PrivilegedRole" + ], + "Criticality": "Shall", + "PolicyId": "MS.AAD.16.2v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [ + "Privileged Role Administrator" + ], + "Commandlet": [ + "Get-MgSubscribedSku", + "Get-PrivilegedRole" + ], + "Criticality": "Should", + "PolicyId": "MS.AAD.16.3v1", + "ReportDetails": "1 role(s) without notification e-mail configured for role activations found:
Privileged Role Administrator", + "RequirementMet": false + }, + { + "ActualValue": [ + "Privileged Role Administrator", + "User Administrator" + ], + "Commandlet": [ + "Get-MgSubscribedSku", + "Get-PrivilegedRole" + ], + "Criticality": "Shall", + "PolicyId": "MS.AAD.16.1v1", + "ReportDetails": "2 role(s) without notification e-mail configured for role assignments found:
Privileged Role Administrator, User Administrator", + "RequirementMet": false + }, + { + "ActualValue": [ + { + "Name": "EnableGroupSpecificConsent", + "SettingsGroup": "Consent Policy Settings", + "Value": "false" + } + ], + "Commandlet": [ + "Get-MgDirectorySetting" + ], + "Criticality": "Shall", + "PolicyId": "MS.AAD.7.3v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": false, + "Commandlet": [ + "Get-AntiPhishPolicy" + ], + "Control": "Defender 2.5", + "Criticality": "Shall", + "ReportDetails": "Requirement not met", + "Requirement": "All safety tips SHALL be enabled: domain impersonation default policy", + "RequirementMet": false + }, + { + "ActualValue": false, + "Commandlet": [ + "Get-AntiPhishPolicy" + ], + "Control": "Defender 2.5", + "Criticality": "Shall", + "ReportDetails": "Requirement not met", + "Requirement": "All safety tips SHALL be enabled: user impersonation default policy", + "RequirementMet": false + }, + { + "ActualValue": false, + "Commandlet": [ + "Get-AntiPhishPolicy" + ], + "Control": "Defender 2.5", + "Criticality": "Shall", + "ReportDetails": "Requirement not met", + "Requirement": "All safety tips SHALL be enabled: user impersonation unusual characters default policy", + "RequirementMet": false + }, + { + "ActualValue": false, + "Commandlet": [ + "Get-AntiPhishPolicy" + ], + "Criticality": "Shall", + "PolicyId": "MS.DEFENDER.5.8v1", + "ReportDetails": "Requirement not met", + "RequirementMet": false + }, + { + "ActualValue": true, + "Commandlet": [ + "Get-AntiPhishPolicy" + ], + "Control": "Defender 2.5", + "Criticality": "Shall", + "ReportDetails": "Requirement met", + "Requirement": "All safety tips SHALL be enabled: \"?\" for unauthenticated senders for spoof default policy", + "RequirementMet": true + }, + { + "ActualValue": true, + "Commandlet": [ + "Get-AntiPhishPolicy" + ], + "Control": "Defender 2.5", + "Criticality": "Shall", + "ReportDetails": "Requirement met", + "Requirement": "All safety tips SHALL be enabled: \"via\" tag default policy", + "RequirementMet": true + }, + { + "ActualValue": true, + "Commandlet": [ + "Get-HostedContentFilterPolicy" + ], + "Control": "Defender 2.6", + "Criticality": "Shall", + "ReportDetails": "Requirement met", + "Requirement": "Zero-hour auto purge (ZAP) SHALL be enabled for phishing: default policy", + "RequirementMet": true + }, + { + "ActualValue": true, + "Commandlet": [ + "Get-HostedContentFilterPolicy" + ], + "Control": "Defender 2.6", + "Criticality": "Shall", + "ReportDetails": "Requirement met", + "Requirement": "Zero-hour auto purge (ZAP) SHALL be enabled for spam messages: default policy", + "RequirementMet": true + }, + { + "ActualValue": true, + "Commandlet": [ + "Get-HostedContentFilterPolicy" + ], + "Criticality": "Shall", + "PolicyId": "MS.DEFENDER.6.7v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": true, + "Commandlet": [ + "Get-HostedContentFilterPolicy" + ], + "Criticality": "Should", + "PolicyId": "MS.DEFENDER.6.6v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": 7, + "Commandlet": [ + "Get-HostedContentFilterPolicy" + ], + "Criticality": "Should", + "PolicyId": "MS.DEFENDER.6.1v1", + "ReportDetails": "Requirement not met", + "RequirementMet": false + }, + { + "ActualValue": 15, + "Commandlet": [ + "Get-HostedContentFilterPolicy" + ], + "Criticality": "Should", + "PolicyId": "MS.DEFENDER.6.5v1", + "ReportDetails": "Requirement not met", + "RequirementMet": false + }, + { + "ActualValue": "MoveToJmf", + "Commandlet": [ + "Get-AntiPhishPolicy" + ], + "Criticality": "Shall", + "PolicyId": "MS.DEFENDER.5.7v1", + "ReportDetails": "Requirement not met", + "RequirementMet": false + }, + { + "ActualValue": "MoveToJmf", + "Commandlet": [ + "Get-HostedContentFilterPolicy" + ], + "Control": "Defender 2.6", + "Criticality": "Shall", + "ReportDetails": "Requirement met", + "Requirement": "High confidence spam SHALL be moved to either the junk email folder or the quarantine folder: default policy", + "RequirementMet": true + }, + { + "ActualValue": "MoveToJmf", + "Commandlet": [ + "Get-HostedContentFilterPolicy" + ], + "Criticality": "Shall", + "PolicyId": "MS.DEFENDER.6.2v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": "MoveToJmf", + "Commandlet": [ + "Get-HostedContentFilterPolicy" + ], + "Criticality": "Shall", + "PolicyId": "MS.DEFENDER.6.3v1", + "ReportDetails": "Requirement not met", + "RequirementMet": false + }, + { + "ActualValue": "MoveToJmf", + "Commandlet": [ + "Get-HostedContentFilterPolicy" + ], + "Criticality": "Should", + "PolicyId": "MS.DEFENDER.6.4v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": "NoAction", + "Commandlet": [ + "Get-AntiPhishPolicy" + ], + "Control": "Defender 2.5", + "Criticality": "Shall", + "ReportDetails": "Requirement not met", + "Requirement": "Message action SHALL be set to quarantine if the message is detected as impersonated: domains default policy", + "RequirementMet": false + }, + { + "ActualValue": "NoAction", + "Commandlet": [ + "Get-AntiPhishPolicy" + ], + "Control": "Defender 2.5", + "Criticality": "Shall", + "ReportDetails": "Requirement not met", + "Requirement": "Message action SHALL be set to quarantine if the message is detected as impersonated: mailbox default policy", + "RequirementMet": false + }, + { + "ActualValue": "NoAction", + "Commandlet": [ + "Get-AntiPhishPolicy" + ], + "Criticality": "Shall", + "PolicyId": "MS.DEFENDER.5.6v1", + "ReportDetails": "Requirement not met", + "RequirementMet": false + }, + { + "ActualValue": "Quarantine", + "Commandlet": [ + "Get-HostedContentFilterPolicy" + ], + "Control": "Defender 2.6", + "Criticality": "Shall", + "ReportDetails": "Requirement met", + "Requirement": "High confidence phishing SHALL be quarantined: default policy", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Shall/Not-Implemented", + "PolicyId": "MS.DEFENDER.10.2v1", + "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Shall/Not-Implemented", + "PolicyId": "MS.DEFENDER.10.3v1", + "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Should/Not-Implemented", + "PolicyId": "MS.DEFENDER.2.5v1", + "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Should/Not-Implemented", + "PolicyId": "MS.DEFENDER.2.6v1", + "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Should/Not-Implemented", + "PolicyId": "MS.DEFENDER.9.2v1", + "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-AntiPhishPolicy" + ], + "Control": "Defender 2.5", + "Criticality": "Should", + "ReportDetails": "Requirement met", + "Requirement": "All safety tips SHOULD be enabled: \"?\" for unauthenticated senders for spoof non-default policies", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-AntiPhishPolicy" + ], + "Control": "Defender 2.5", + "Criticality": "Should", + "ReportDetails": "Requirement met", + "Requirement": "All safety tips SHOULD be enabled: \"via\" tag non-default policies", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-AntiPhishPolicy" + ], + "Control": "Defender 2.5", + "Criticality": "Should", + "ReportDetails": "Requirement met", + "Requirement": "All safety tips SHOULD be enabled: domain impersonation non-default policies", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-AntiPhishPolicy" + ], + "Control": "Defender 2.5", + "Criticality": "Should", + "ReportDetails": "Requirement met", + "Requirement": "All safety tips SHOULD be enabled: first contact non-default policies", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-AntiPhishPolicy" + ], + "Control": "Defender 2.5", + "Criticality": "Should", + "ReportDetails": "Requirement met", + "Requirement": "All safety tips SHOULD be enabled: user impersonation non-default policies", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-AntiPhishPolicy" + ], + "Control": "Defender 2.5", + "Criticality": "Should", + "ReportDetails": "Requirement met", + "Requirement": "All safety tips SHOULD be enabled: user impersonation unusual characters non-default policies", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-AntiPhishPolicy" + ], + "Control": "Defender 2.5", + "Criticality": "Should", + "ReportDetails": "Requirement met", + "Requirement": "Mail classified as spoofed SHOULD be quarantined: non-default policies", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-AntiPhishPolicy" + ], + "Control": "Defender 2.5", + "Criticality": "Should", + "ReportDetails": "Requirement met", + "Requirement": "Message action SHOULD be set to quarantine if the message is detected as impersonated: domains non-default policies", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-AntiPhishPolicy" + ], + "Control": "Defender 2.5", + "Criticality": "Should", + "ReportDetails": "Requirement met", + "Requirement": "Message action SHOULD be set to quarantine if the message is detected as impersonated: mailbox non-default policies", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-AntiPhishPolicy" + ], + "Control": "Defender 2.5", + "Criticality": "Should", + "ReportDetails": "Requirement met", + "Requirement": "Message action SHOULD be set to quarantine if the message is detected as impersonated: users non-default policies", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-AntiPhishPolicy" + ], + "Criticality": "Should", + "PolicyId": "MS.DEFENDER.5.1v1", + "ReportDetails": "No users are included for targeted user protection.", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-AntiPhishPolicy" + ], + "Criticality": "Should", + "PolicyId": "MS.DEFENDER.5.2v1", + "ReportDetails": "Requirement not met", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-AntiPhishPolicy" + ], + "Criticality": "Should", + "PolicyId": "MS.DEFENDER.5.3v1", + "ReportDetails": "The Custom Domains protection policies: Enabled, EnableTargetedDomainsProtection, and TargetedDomainsToProtect are not set correctly", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-AntiPhishPolicy" + ], + "Criticality": "Should", + "PolicyId": "MS.DEFENDER.5.5v1", + "ReportDetails": "Requirement not met", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-DLPCompliancePolicy" + ], + "Control": "Defender 2.2", + "Criticality": "Should", + "ReportDetails": "No policy found that applies to OneDrive.", + "Requirement": "The custom policy SHOULD be applied in OneDrive", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-DLPCompliancePolicy" + ], + "Control": "Defender 2.2", + "Criticality": "Should", + "ReportDetails": "No policy found that applies to SharePoint.", + "Requirement": "The custom policy SHOULD be applied in SharePoint", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-DLPCompliancePolicy" + ], + "Control": "Defender 2.2", + "Criticality": "Should", + "ReportDetails": "No policy found that applies to Teams.", + "Requirement": "The custom policy SHOULD be applied in Teams", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-DLPCompliancePolicy" + ], + "Criticality": "Should", + "PolicyId": "MS.DEFENDER.2.2v1", + "ReportDetails": "No policy found that applies to Exchange.", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-DlpComplianceRule" + ], + "Control": "Defender 2.2", + "Criticality": "Shall", + "ReportDetails": "No matching rule found for Credit Card Number", + "Requirement": "A custom policy SHALL be configured to protect PII and sensitive information, as defined by the agency: Credit Card Number", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-DlpComplianceRule" + ], + "Control": "Defender 2.2", + "Criticality": "Shall", + "ReportDetails": "No matching rule found for U.S. Individual Taxpayer Identification Number (ITIN)", + "Requirement": "A custom policy SHALL be configured to protect PII and sensitive information, as defined by the agency: U.S. Individual Taxpayer Identification Number (ITIN)", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-DlpComplianceRule" + ], + "Criticality": "Shall", + "PolicyId": "MS.DEFENDER.2.1v1", + "ReportDetails": "No matching rule found for U.S. Social Security Number (SSN)", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-DlpComplianceRule" + ], + "Criticality": "Should", + "PolicyId": "MS.DEFENDER.2.3v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-DlpComplianceRule" + ], + "Criticality": "Should", + "PolicyId": "MS.DEFENDER.2.4v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-EOPProtectionPolicyRule" + ], + "Control": "Defender 2.1", + "Criticality": "Should", + "ReportDetails": "Requirement met", + "Requirement": "Strict Preset security profiles SHOULD NOT be used", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-EOPProtectionPolicyRule" + ], + "Criticality": "Should", + "PolicyId": "MS.DEFENDER.1.1v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-HostedContentFilterPolicy" + ], + "Control": "Defender 2.6", + "Criticality": "Should", + "ReportDetails": "Requirement met", + "Requirement": "Allowed senders MAY be added but allowed domains SHOULD NOT be added: non-default", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-HostedContentFilterPolicy" + ], + "Control": "Defender 2.6", + "Criticality": "Should", + "ReportDetails": "Requirement met", + "Requirement": "Bulk email SHOULD be moved to either the junk email folder or the quarantine folder: non-default policies", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-HostedContentFilterPolicy" + ], + "Control": "Defender 2.6", + "Criticality": "Should", + "ReportDetails": "Requirement met", + "Requirement": "High confidence phishing SHOULD be quarantined: non-default policies", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-HostedContentFilterPolicy" + ], + "Control": "Defender 2.6", + "Criticality": "Should", + "ReportDetails": "Requirement met", + "Requirement": "High confidence spam SHOULD be moved to either the junk email folder or the quarantine folder: non-default policies", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-HostedContentFilterPolicy" + ], + "Control": "Defender 2.6", + "Criticality": "Should", + "ReportDetails": "Requirement met", + "Requirement": "Phishing SHOULD be quarantined: non-default policies", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-HostedContentFilterPolicy" + ], + "Control": "Defender 2.6", + "Criticality": "Should", + "ReportDetails": "Requirement met", + "Requirement": "Spam SHOULD be moved to either the junk email folder or the quarantine folder: non-default policies", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-HostedContentFilterPolicy" + ], + "Control": "Defender 2.6", + "Criticality": "Should", + "ReportDetails": "Requirement met", + "Requirement": "Spam in quarantine SHOULD be retained for at least 30 days: non-default policies", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-HostedContentFilterPolicy" + ], + "Control": "Defender 2.6", + "Criticality": "Should", + "ReportDetails": "Requirement met", + "Requirement": "Spam safety tips SHOULD be turned on: non-default policies", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-HostedContentFilterPolicy" + ], + "Control": "Defender 2.6", + "Criticality": "Should", + "ReportDetails": "Requirement met", + "Requirement": "The bulk complaint level (BCL) threshold SHOULD be set to six or lower: non-default policies", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-HostedContentFilterPolicy" + ], + "Control": "Defender 2.6", + "Criticality": "Should", + "ReportDetails": "Requirement met", + "Requirement": "Zero-hour auto purge (ZAP) SHOULD be enabled for Spam: non-default", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-HostedContentFilterPolicy" + ], + "Control": "Defender 2.6", + "Criticality": "Should", + "ReportDetails": "Requirement met", + "Requirement": "Zero-hour auto purge (ZAP) SHOULD be enabled for phishing: non-default", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-HostedContentFilterPolicy" + ], + "Control": "Defender 2.6", + "Criticality": "Should", + "ReportDetails": "Requirement met", + "Requirement": "Zero-hour auto purge (ZAP) SHOULD be enabled: non-default", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-HostedContentFilterPolicy" + ], + "Criticality": "Shall", + "PolicyId": "MS.DEFENDER.6.8v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-MalwareFilterPolicy" + ], + "Criticality": "Shall", + "PolicyId": "MS.DEFENDER.3.1v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-MalwareFilterPolicy" + ], + "Criticality": "Should", + "PolicyId": "MS.DEFENDER.4.1v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-SafeAttachmentPolicy", + "Get-SafeAttachmentRule", + "Get-AcceptedDomain" + ], + "Criticality": "Shall", + "PolicyId": "MS.DEFENDER.8.2v1", + "ReportDetails": "No enabled policy found with action set to block that apply to all domains", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-SafeAttachmentPolicy", + "Get-SafeAttachmentRule", + "Get-AcceptedDomain" + ], + "Criticality": "Should", + "PolicyId": "MS.DEFENDER.8.3v1", + "ReportDetails": "No enabled policy found with action set to block and at least one contact specified", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-SafeAttachmentRule", + "Get-AcceptedDomain" + ], + "Criticality": "Shall", + "PolicyId": "MS.DEFENDER.8.1v1", + "ReportDetails": "No policy found that applies to all domains: alexwilber.myo365.site, y2zj1.onmicrosoft.com", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-SafeLinksPolicy", + "Get-SafeLinksRule" + ], + "Criticality": "Shall", + "PolicyId": "MS.DEFENDER.7.2v1", + "ReportDetails": "Requirement not met", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-SafeLinksPolicy", + "Get-SafeLinksRule" + ], + "Criticality": "Shall", + "PolicyId": "MS.DEFENDER.7.3v1", + "ReportDetails": "Requirement not met", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-SafeLinksPolicy", + "Get-SafeLinksRule" + ], + "Criticality": "Shall", + "PolicyId": "MS.DEFENDER.7.4v1", + "ReportDetails": "Requirement not met", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-SafeLinksPolicy", + "Get-SafeLinksRule" + ], + "Criticality": "Shall", + "PolicyId": "MS.DEFENDER.7.5v1", + "ReportDetails": "Requirement not met", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-SafeLinksPolicy", + "Get-SafeLinksRule" + ], + "Criticality": "Shall", + "PolicyId": "MS.DEFENDER.7.6v1", + "ReportDetails": "Requirement not met", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-SafeLinksPolicy", + "Get-SafeLinksRule" + ], + "Criticality": "Shall", + "PolicyId": "MS.DEFENDER.7.7v1", + "ReportDetails": "Requirement not met", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-SafeLinksPolicy", + "Get-SafeLinksRule" + ], + "Criticality": "Shall", + "PolicyId": "MS.DEFENDER.7.8v1", + "ReportDetails": "Requirement not met", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-SafeLinksPolicy", + "Get-SafeLinksRule" + ], + "Criticality": "Shall", + "PolicyId": "MS.DEFENDER.7.9v1", + "ReportDetails": "Requirement not met", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-SafeLinksRule", + "Get-AcceptedDomain" + ], + "Criticality": "Shall", + "PolicyId": "MS.DEFENDER.7.1v1", + "ReportDetails": "No policy found that applies to all domains: alexwilber.myo365.site, y2zj1.onmicrosoft.com", + "RequirementMet": false + }, + { + "ActualValue": [ + "A potentially malicious URL click was detected", + "Malware campaign detected after delivery", + "Messages have been delayed", + "Suspicious Email Forwarding Activity", + "Suspicious connector activity", + "Suspicious email sending patterns detected", + "Tenant restricted from sending unprovisioned email", + "Unusual increase in email reported as phish", + "User restricted from sending email" + ], + "Commandlet": [ + "Get-ProtectionAlert" + ], + "Criticality": "Shall", + "PolicyId": "MS.DEFENDER.9.1v1", + "ReportDetails": "9 disabled required alert(s) found: A potentially malicious URL click was detected, Malware campaign detected after delivery, Messages have been delayed, Suspicious Email Forwarding Activity, Suspicious connector activity, Suspicious email sending patterns detected, Tenant restricted from sending unprovisioned email, Unusual increase in email reported as phish, User restricted from sending email", + "RequirementMet": false + }, + { + "ActualValue": [ + "Default" + ], + "Commandlet": [ + "Get-MalwareFilterPolicy" + ], + "Control": "Defender 2.3", + "Criticality": "Should", + "ReportDetails": "Requirement met", + "Requirement": "Disallowed file types SHALL be determined and set. At a minimum, click-to-run files SHOULD be blocked: cmd files", + "RequirementMet": true + }, + { + "ActualValue": [ + "Default" + ], + "Commandlet": [ + "Get-MalwareFilterPolicy" + ], + "Control": "Defender 2.3", + "Criticality": "Should", + "ReportDetails": "Requirement met", + "Requirement": "Disallowed file types SHALL be determined and set. At a minimum, click-to-run files SHOULD be blocked: vbe files", + "RequirementMet": true + }, + { + "ActualValue": [ + "Default" + ], + "Commandlet": [ + "Get-MalwareFilterPolicy" + ], + "Criticality": "Should", + "PolicyId": "MS.DEFENDER.3.2v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [ + { + "EnableATPForSPOTeamsODB": true, + "Identity": "Default" + } + ], + "Commandlet": [ + "Get-AtpPolicyForO365" + ], + "Criticality": "Should", + "PolicyId": "MS.DEFENDER.8.4v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [ + { + "Identity": "Admin Audit Log Settings", + "UnifiedAuditLogIngestionEnabled": true + } + ], + "Commandlet": [ + "Get-AdminAuditLogConfig" + ], + "Criticality": "Shall", + "PolicyId": "MS.DEFENDER.10.1v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Shall/3rd Party", + "PolicyId": "MS.EXO.10.1v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Shall/3rd Party", + "PolicyId": "MS.EXO.10.2v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Shall/3rd Party", + "PolicyId": "MS.EXO.14.1v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Shall/3rd Party", + "PolicyId": "MS.EXO.14.2v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Shall/3rd Party", + "PolicyId": "MS.EXO.14.3v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Shall/3rd Party", + "PolicyId": "MS.EXO.16.1v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Shall/3rd Party", + "PolicyId": "MS.EXO.17.1v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Shall/3rd Party", + "PolicyId": "MS.EXO.17.2v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Shall/3rd Party", + "PolicyId": "MS.EXO.17.3v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Shall/3rd Party", + "PolicyId": "MS.EXO.8.1v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Shall/3rd Party", + "PolicyId": "MS.EXO.8.2v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Shall/3rd Party", + "PolicyId": "MS.EXO.9.1v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Shall/3rd Party", + "PolicyId": "MS.EXO.9.3v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Shall/Not-Implemented", + "PolicyId": "MS.EXO.2.1v1", + "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Should/3rd Party", + "PolicyId": "MS.EXO.10.3v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Should/3rd Party", + "PolicyId": "MS.EXO.11.1v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Should/3rd Party", + "PolicyId": "MS.EXO.11.2v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Should/3rd Party", + "PolicyId": "MS.EXO.11.3v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Should/3rd Party", + "PolicyId": "MS.EXO.15.1v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Should/3rd Party", + "PolicyId": "MS.EXO.15.2v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Should/3rd Party", + "PolicyId": "MS.EXO.15.3v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Should/3rd Party", + "PolicyId": "MS.EXO.16.2v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Should/3rd Party", + "PolicyId": "MS.EXO.9.2v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-ScubaDmarcRecords", + "Get-AcceptedDomain" + ], + "Criticality": "Shall", + "PolicyId": "MS.EXO.4.1v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-ScubaDmarcRecords", + "Get-AcceptedDomain" + ], + "Criticality": "Shall", + "PolicyId": "MS.EXO.4.2v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-ScubaDmarcRecords", + "Get-AcceptedDomain" + ], + "Criticality": "Shall", + "PolicyId": "MS.EXO.4.3v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-ScubaDmarcRecords", + "Get-AcceptedDomain" + ], + "Criticality": "Should", + "PolicyId": "MS.EXO.4.4v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-TransportRule" + ], + "Criticality": "Shall", + "PolicyId": "MS.EXO.7.1v1", + "ReportDetails": "No transport rule found that applies warnings to emails received from outside the organization", + "RequirementMet": false + }, + { + "ActualValue": [ + [], + [ + null + ] + ], + "Commandlet": [ + "Get-DkimSigningConfig", + "Get-ScubaDkimRecords", + "Get-AcceptedDomain" + ], + "Criticality": "Should", + "PolicyId": "MS.EXO.3.1v1", + "ReportDetails": "1 of 1 agency domain(s) found in violation: alexwilber.myo365.site", + "RequirementMet": false + }, + { + "ActualValue": [ + { + "AddressBookPolicyRoutingEnabled": false, + "AdminDisplayName": "", + "AgentGeneratedMessageLoopDetectionInSmtpEnabled": true, + "AgentGeneratedMessageLoopDetectionInSubmissionEnabled": true, + "AllowLegacyTLSClients": false, + "AnonymousSenderToRecipientRatePerHour": 1800, + "AttributionRejectBeforeMServRequest": false, + "AttributionRejectConsumerMessages": false, + "ClearCategories": true, + "ConvertDisclaimerWrapperToEml": false, + "ConvertReportToMessage": false, + "CurrentTransportSystemState": "Green", + "DSNConversionMode": "PreserveDSNBody", + "DiagnosticsAggregationServicePort": 9710, + "DistinguishedName": "CN=Transport Settings,CN=Configuration,CN=y2zj1.onmicrosoft.com,CN=ConfigurationUnits,DC=NAMPR10A008,DC=PROD,DC=OUTLOOK,DC=COM", + "EnableExternalHTTPMailDelivery": false, + "ExchangeObjectId": "b4f29764-fa61-4718-ac8d-29e1ad3007b9", + "ExchangeVersion": "0.1 (8.0.535.0)", + "ExternalDelayDsnEnabled": true, + "ExternalDsnDefaultLanguage": null, + "ExternalDsnLanguageDetectionEnabled": true, + "ExternalDsnMaxMessageAttachSize": "10 MB (10,485,760 bytes)", + "ExternalDsnReportingAuthority": null, + "ExternalDsnSendHtml": true, + "ExternalPostmasterAddress": null, + "GenerateCopyOfDSNFor": [], + "Guid": "b4f29764-fa61-4718-ac8d-29e1ad3007b9", + "HeaderPromotionModeSetting": "NoCreate", + "HygieneSuite": "Premium", + "Id": "Transport Settings", + "Identity": "Transport Settings", + "InternalDelayDsnEnabled": true, + "InternalDsnDefaultLanguage": null, + "InternalDsnLanguageDetectionEnabled": true, + "InternalDsnMaxMessageAttachSize": "10 MB (10,485,760 bytes)", + "InternalDsnReportingAuthority": null, + "InternalDsnSendHtml": true, + "InternalSMTPServers": [], + "IsValid": true, + "JournalArchivingEnabled": false, + "JournalMessageExpirationDays": 0, + "JournalReportDLMemberSubstitutionEnabled": false, + "JournalingReportNdrTo": "u003cu003e", + "LegacyArchiveJournalingEnabled": false, + "LegacyArchiveLiveJournalingEnabled": false, + "LegacyJournalingMigrationEnabled": false, + "MaxAllowedAgentGeneratedMessageDepth": 3, + "MaxAllowedAgentGeneratedMessageDepthPerAgent": 2, + "MaxDumpsterSizePerDatabase": "18 MB (18,874,368 bytes)", + "MaxDumpsterTime": "7.00:00:00", + "MaxReceiveSize": "Unlimited", + "MaxRecipientEnvelopeLimit": "Unlimited", + "MaxSendSize": "Unlimited", + "MessageExpiration": "1.00:00:00", + "MigrationEnabled": true, + "Name": "Transport Settings", + "ObjectCategory": "NAMPR10A008.PROD.OUTLOOK.COM/Configuration/Schema/ms-Exch-Transport-Settings", + "ObjectClass": [ + "top", + "container", + "msExchTransportSettings" + ], + "ObjectState": "Unchanged", + "OpenDomainRoutingEnabled": false, + "OrganizationFederatedMailbox": "FederatedEmail.4c1f4d8b-8179-4148-93bf-00a95fa1e042@y2zj1.onmicrosoft.com", + "OrganizationId": "NAMPR10A008.PROD.OUTLOOK.COM/Microsoft Exchange Hosted Organizations/y2zj1.onmicrosoft.com - NAMPR10A008.PROD.OUTLOOK.COM/ConfigurationUnits/y2zj1.onmicrosoft.com/Configuration", + "OrganizationalUnitRoot": "y2zj1.onmicrosoft.com", + "OriginatingServer": "DM5PR10A08DC002.NAMPR10A008.PROD.OUTLOOK.COM", + "OtherWellKnownObjects": [], + "PreserveReportBodypart": true, + "QueueDiagnosticsAggregationInterval": "00:01:00", + "RedirectDLMessagesForLegacyArchiveJournaling": false, + "RedirectUnprovisionedUserMessagesForLegacyArchiveJournaling": false, + "ReplyAllStormBlockDurationHours": 6, + "ReplyAllStormDetectionMinimumRecipients": 2500, + "ReplyAllStormDetectionMinimumReplies": 10, + "ReplyAllStormProtectionEnabled": true, + "Rfc2231EncodingEnabled": false, + "SafetyNetHoldTime": "7.00:00:00", + "SmtpClientAuthenticationDisabled": true, + "SupervisionTags": [ + "Reject", + "Allow" + ], + "TLSReceiveDomainSecureList": [], + "TLSSendDomainSecureList": [], + "TransportRuleAttachmentTextScanLimit": "1 MB (1,048,576 bytes)", + "TransportRuleCollectionAddedRecipientsLimit": 100, + "TransportRuleCollectionRegexCharsLimit": "20 KB (20,480 bytes)", + "TransportRuleConfig": [ + "TransportRuleMinProductVersion:14.0.0.0", + "TransportRuleRegexValidationTimeout:00:00:00.3000000", + "TransportRuleAttachmentTextScanLimit:1 MB (1,048,576 bytes)", + "TransportRuleSizeLimit:8 KB (8,192 bytes)", + "TransportRuleCollectionRegexCharsLimit:20 KB (20,480 bytes)", + "TransportRuleLimit:300", + "TransportRuleCollectionAddedRecipientsLimit:100" + ], + "TransportRuleLimit": 300, + "TransportRuleMinProductVersion": { + "Build": 0, + "Major": 14, + "MajorRevision": 0, + "Minor": 0, + "MinorRevision": 0, + "Revision": 0 + }, + "TransportRuleRegexValidationTimeout": "00:00:00.3000000", + "TransportRuleSizeLimit": "8 KB (8,192 bytes)", + "TransportSystemState": "", + "VerifySecureSubmitEnabled": false, + "VoicemailJournalingEnabled": true, + "WhenChanged": "/Date(1643184486000)/", + "WhenChangedUTC": "/Date(1643184486000)/", + "WhenCreated": "/Date(1643059670000)/", + "WhenCreatedUTC": "/Date(1643059670000)/", + "Xexch50Enabled": true + } + ], + "Commandlet": [ + "Get-TransportConfig" + ], + "Criticality": "Shall", + "PolicyId": "MS.EXO.5.1v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [ + { + "AdminDisplayName": "", + "Default": true, + "DistinguishedName": "CN=Default Sharing Policy,CN=Federation,CN=Configuration,CN=y2zj1.onmicrosoft.com,CN=ConfigurationUnits,DC=NAMPR10A008,DC=PROD,DC=OUTLOOK,DC=COM", + "Domains": [ + "Anonymous:CalendarSharingFreeBusyReviewer", + "*:CalendarSharingFreeBusySimple" + ], + "Enabled": true, + "ExchangeObjectId": "2f1ca8cf-5ba5-45e3-b73a-1405ff552a2e", + "ExchangeVersion": "0.10 (14.0.100.0)", + "Guid": "2f1ca8cf-5ba5-45e3-b73a-1405ff552a2e", + "Id": "Default Sharing Policy", + "Identity": "Default Sharing Policy", + "IsValid": true, + "Name": "Default Sharing Policy", + "ObjectCategory": "NAMPR10A008.PROD.OUTLOOK.COM/Configuration/Schema/ms-Exch-Sharing-Policy", + "ObjectClass": [ + "top", + "msExchSharingPolicy" + ], + "ObjectState": "Changed", + "OrganizationId": "NAMPR10A008.PROD.OUTLOOK.COM/Microsoft Exchange Hosted Organizations/y2zj1.onmicrosoft.com - NAMPR10A008.PROD.OUTLOOK.COM/ConfigurationUnits/y2zj1.onmicrosoft.com/Configuration", + "OrganizationalUnitRoot": "y2zj1.onmicrosoft.com", + "OriginatingServer": "DM5PR10A08DC002.NAMPR10A008.PROD.OUTLOOK.COM", + "WhenChanged": "/Date(1645650761000)/", + "WhenChangedUTC": "/Date(1645650761000)/", + "WhenCreated": "/Date(1645650752000)/", + "WhenCreatedUTC": "/Date(1645650752000)/" + } + ], + "Commandlet": [ + "Get-SharingPolicy" + ], + "Criticality": "Shall", + "PolicyId": "MS.EXO.6.1v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [ + { + "AdminDisplayName": "", + "Default": true, + "DistinguishedName": "CN=Default Sharing Policy,CN=Federation,CN=Configuration,CN=y2zj1.onmicrosoft.com,CN=ConfigurationUnits,DC=NAMPR10A008,DC=PROD,DC=OUTLOOK,DC=COM", + "Domains": [ + "Anonymous:CalendarSharingFreeBusyReviewer", + "*:CalendarSharingFreeBusySimple" + ], + "Enabled": true, + "ExchangeObjectId": "2f1ca8cf-5ba5-45e3-b73a-1405ff552a2e", + "ExchangeVersion": "0.10 (14.0.100.0)", + "Guid": "2f1ca8cf-5ba5-45e3-b73a-1405ff552a2e", + "Id": "Default Sharing Policy", + "Identity": "Default Sharing Policy", + "IsValid": true, + "Name": "Default Sharing Policy", + "ObjectCategory": "NAMPR10A008.PROD.OUTLOOK.COM/Configuration/Schema/ms-Exch-Sharing-Policy", + "ObjectClass": [ + "top", + "msExchSharingPolicy" + ], + "ObjectState": "Changed", + "OrganizationId": "NAMPR10A008.PROD.OUTLOOK.COM/Microsoft Exchange Hosted Organizations/y2zj1.onmicrosoft.com - NAMPR10A008.PROD.OUTLOOK.COM/ConfigurationUnits/y2zj1.onmicrosoft.com/Configuration", + "OrganizationalUnitRoot": "y2zj1.onmicrosoft.com", + "OriginatingServer": "DM5PR10A08DC002.NAMPR10A008.PROD.OUTLOOK.COM", + "WhenChanged": "/Date(1645650761000)/", + "WhenChangedUTC": "/Date(1645650761000)/", + "WhenCreated": "/Date(1645650752000)/", + "WhenCreatedUTC": "/Date(1645650752000)/" + } + ], + "Commandlet": [ + "Get-SharingPolicy" + ], + "Criticality": "Shall", + "PolicyId": "MS.EXO.6.2v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [ + { + "AdminDisplayName": "", + "DirectoryBasedEdgeBlockMode": "Default", + "DistinguishedName": "CN=Default,CN=Hosted Connection Filter,CN=Transport Settings,CN=Configuration,CN=y2zj1.onmicrosoft.com,CN=ConfigurationUnits,DC=NAMPR10A008,DC=PROD,DC=OUTLOOK,DC=COM", + "EnableSafeList": false, + "ExchangeObjectId": "3843aef3-f3bd-49c1-a674-4d6741ac11b6", + "ExchangeVersion": "0.20 (15.0.0.0)", + "Guid": "3843aef3-f3bd-49c1-a674-4d6741ac11b6", + "IPAllowList": [], + "IPBlockList": [], + "Id": "Default", + "Identity": "Default", + "IsDefault": true, + "IsValid": true, + "Name": "Default", + "ObjectCategory": "NAMPR10A008.PROD.OUTLOOK.COM/Configuration/Schema/ms-Exch-Hosted-Connection-Filter-Policy", + "ObjectClass": [ + "top", + "msExchHostedConnectionFilterPolicy" + ], + "ObjectState": "Unchanged", + "OrganizationId": "NAMPR10A008.PROD.OUTLOOK.COM/Microsoft Exchange Hosted Organizations/y2zj1.onmicrosoft.com - NAMPR10A008.PROD.OUTLOOK.COM/ConfigurationUnits/y2zj1.onmicrosoft.com/Configuration", + "OrganizationalUnitRoot": "y2zj1.onmicrosoft.com", + "OriginatingServer": "DM5PR10A08DC002.NAMPR10A008.PROD.OUTLOOK.COM", + "WhenChanged": "/Date(1645650833000)/", + "WhenChangedUTC": "/Date(1645650833000)/", + "WhenCreated": "/Date(1645650828000)/", + "WhenCreatedUTC": "/Date(1645650828000)/" + } + ], + "Commandlet": [ + "Get-HostedConnectionFilterPolicy" + ], + "Criticality": "Should", + "PolicyId": "MS.EXO.12.1v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [ + { + "AdminDisplayName": "", + "DirectoryBasedEdgeBlockMode": "Default", + "DistinguishedName": "CN=Default,CN=Hosted Connection Filter,CN=Transport Settings,CN=Configuration,CN=y2zj1.onmicrosoft.com,CN=ConfigurationUnits,DC=NAMPR10A008,DC=PROD,DC=OUTLOOK,DC=COM", + "EnableSafeList": false, + "ExchangeObjectId": "3843aef3-f3bd-49c1-a674-4d6741ac11b6", + "ExchangeVersion": "0.20 (15.0.0.0)", + "Guid": "3843aef3-f3bd-49c1-a674-4d6741ac11b6", + "IPAllowList": [], + "IPBlockList": [], + "Id": "Default", + "Identity": "Default", + "IsDefault": true, + "IsValid": true, + "Name": "Default", + "ObjectCategory": "NAMPR10A008.PROD.OUTLOOK.COM/Configuration/Schema/ms-Exch-Hosted-Connection-Filter-Policy", + "ObjectClass": [ + "top", + "msExchHostedConnectionFilterPolicy" + ], + "ObjectState": "Unchanged", + "OrganizationId": "NAMPR10A008.PROD.OUTLOOK.COM/Microsoft Exchange Hosted Organizations/y2zj1.onmicrosoft.com - NAMPR10A008.PROD.OUTLOOK.COM/ConfigurationUnits/y2zj1.onmicrosoft.com/Configuration", + "OrganizationalUnitRoot": "y2zj1.onmicrosoft.com", + "OriginatingServer": "DM5PR10A08DC002.NAMPR10A008.PROD.OUTLOOK.COM", + "WhenChanged": "/Date(1645650833000)/", + "WhenChangedUTC": "/Date(1645650833000)/", + "WhenCreated": "/Date(1645650828000)/", + "WhenCreatedUTC": "/Date(1645650828000)/" + } + ], + "Commandlet": [ + "Get-HostedConnectionFilterPolicy" + ], + "Criticality": "Should", + "PolicyId": "MS.EXO.12.2v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [ + { + "AuditDisabled": false, + "DisplayName": "y2zj1", + "Name": "y2zj1.onmicrosoft.com" + } + ], + "Commandlet": [ + "Get-OrganizationConfig" + ], + "Criticality": "Shall", + "PolicyId": "MS.EXO.13.1v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-ScubaSpfRecords", + "Get-AcceptedDomain" + ], + "Criticality": "Shall", + "PolicyId": "MS.EXO.2.2v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [ + "*" + ], + "Commandlet": [ + "Get-RemoteDomain" + ], + "Criticality": "Shall", + "PolicyId": "MS.EXO.1.1v1", + "ReportDetails": "1 remote domain(s) that allows automatic forwarding: *", + "RequirementMet": false + }, + { + "ActualValue": "PowerShell Error", + "Commandlet": [ + "Get-DlpPolicy" + ], + "Criticality": "Should", + "PolicyId": "MS.POWERPLATFORM.2.2v1", + "ReportDetails": "PowerShell Error", + "RequirementMet": false + }, + { + "ActualValue": "PowerShell Error", + "Commandlet": [ + "Get-PowerAppTenantIsolationPolicy" + ], + "Criticality": "Shall", + "PolicyId": "MS.POWERPLATFORM.3.1v1", + "ReportDetails": "PowerShell Error", + "RequirementMet": false + }, + { + "ActualValue": "PowerShell Error", + "Commandlet": [ + "Get-TenantSettings" + ], + "Control": "Power Platform 2.1", + "Criticality": "Shall", + "ReportDetails": "PowerShell Error", + "Requirement": "The ability to create trial environments SHALL be restricted to admins", + "RequirementMet": false + }, + { + "ActualValue": "PowerShell Error", + "Commandlet": [ + "Get-TenantSettings" + ], + "Criticality": "Shall", + "PolicyId": "MS.POWERPLATFORM.1.1v1", + "ReportDetails": "PowerShell Error", + "RequirementMet": false + }, + { + "ActualValue": "PowerShell error", + "Commandlet": [ + "Get-DlpPolicy" + ], + "Criticality": "Should", + "PolicyId": "MS.POWERPLATFORM.2.3v1", + "ReportDetails": "PowerShell error", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Shall/Not-Implemented", + "PolicyId": "MS.POWERPLATFORM.4.1v1", + "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Should/Not-Implemented", + "PolicyId": "MS.POWERPLATFORM.3.2v1", + "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Should/Not-Implemented", + "PolicyId": "MS.POWERPLATFORM.3.3v1", + "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-DlpPolicy" + ], + "Criticality": "Shall", + "PolicyId": "MS.POWERPLATFORM.2.1v1", + "ReportDetails": "No policy found that applies to default environment", + "RequirementMet": false + }, + { + "ActualValue": 1, + "Commandlet": [ + "Get-SPOTenant", + "Get-PnPTenant" + ], + "Criticality": "Should", + "PolicyId": "MS.SHAREPOINT.1.3v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": 2, + "Commandlet": [ + "Get-SPOSite", + "Get-PnPTenantSite" + ], + "Control": "Sharepoint 2.5", + "Criticality": "Shall", + "ReportDetails": "Requirement met", + "Requirement": "Users SHALL be prevented from running custom scripts on self-service created sites", + "RequirementMet": true + }, + { + "ActualValue": 2, + "Commandlet": [ + "Get-SPOTenant", + "Get-PnPTenant" + ], + "Criticality": "Shall", + "PolicyId": "MS.SHAREPOINT.1.1v1", + "ReportDetails": "Requirement not met", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Control": "Sharepoint 2.5", + "Criticality": "Shall/Not-Implemented", + "PolicyId": "MS.SHAREPOINT.TBD", + "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", + "Requirement": "Users SHALL be prevented from running custom scripts on personal sites (OneDrive)", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Shall/Not-Implemented", + "PolicyId": "MS.SHAREPOINT.1.2v1", + "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Should/Not-Implemented", + "PolicyId": "MS.SHAREPOINT.2.1v1", + "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", + "RequirementMet": false + }, + { + "ActualValue": [ + 1, + true, + 29 + ], + "Commandlet": [ + "Get-SPOTenant", + "Get-PnPTenant" + ], + "Control": "Sharepoint 2.4", + "Criticality": "Should", + "ReportDetails": "Requirement not met: Expiration timer for 'People who use a verification code' NOT set to 30 days", + "Requirement": "Expiration timer for 'People who use a verification code' should be set to 30 days", + "RequirementMet": false + }, + { + "ActualValue": [ + 1, + true, + 31 + ], + "Commandlet": [ + "Get-SPOTenant", + "Get-PnPTenant" + ], + "Criticality": "Should", + "PolicyId": "MS.SHAREPOINT.3.1v1", + "ReportDetails": "Requirement not met: Expiration timer for 'Guest access to a site or OneDrive' NOT set to 30 days", + "RequirementMet": false + }, + { + "ActualValue": true, + "Commandlet": [ + "Get-CsTeamsMeetingPolicy" + ], + "Criticality": "Should", + "PolicyId": "MS.TEAMS.9.1v1", + "ReportDetails": "Requirement not met", + "RequirementMet": false + }, + { + "ActualValue": "AlwaysEnabled", + "Commandlet": [ + "Get-CsTeamsMeetingBroadcastPolicy" + ], + "Criticality": "Should", + "PolicyId": "MS.TEAMS.10.1v1", + "ReportDetails": "Requirement not met", + "RequirementMet": false + }, + { + "ActualValue": "EveryoneInCompany", + "Commandlet": [ + "Get-CsTeamsMeetingPolicy" + ], + "Criticality": "Should", + "PolicyId": "MS.TEAMS.3.2v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Shall/3rd Party", + "PolicyId": "MS.TEAMS.11.1v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Shall/3rd Party", + "PolicyId": "MS.TEAMS.11.4v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Shall/3rd Party", + "PolicyId": "MS.TEAMS.8.3v1", + "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Should/3rd Party", + "PolicyId": "MS.TEAMS.11.2v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Should/3rd Party", + "PolicyId": "MS.TEAMS.12.1v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Should/3rd Party", + "PolicyId": "MS.TEAMS.12.2v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Should/3rd Party", + "PolicyId": "MS.TEAMS.13.1v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Should/3rd Party", + "PolicyId": "MS.TEAMS.13.2v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Should/3rd Party", + "PolicyId": "MS.TEAMS.13.3v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [ + "EveryoneInCompany", + false + ], + "Commandlet": [ + "Get-CsTeamsMeetingPolicy" + ], + "Criticality": "Should", + "PolicyId": "MS.TEAMS.3.1v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [ + [], + "MicrosoftCommunicationsOnline/NOAM-ED6-A7" + ], + "Commandlet": [ + "Get-CsTeamsClientConfiguration" + ], + "Criticality": "Shall", + "PolicyId": "MS.TEAMS.7.1v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-CsTeamsAppPermissionPolicy" + ], + "Criticality": "Should", + "PolicyId": "MS.TEAMS.8.1v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-CsTeamsMeetingPolicy" + ], + "Control": "Teams 2.4", + "Criticality": "Should", + "ReportDetails": "Requirement met", + "Requirement": "Anonymous users SHOULD be enabled to join meetings", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-CsTeamsMeetingPolicy" + ], + "Criticality": "Shall", + "PolicyId": "MS.TEAMS.2.1v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-CsTeamsMeetingPolicy" + ], + "Criticality": "Should", + "PolicyId": "MS.TEAMS.1.1v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-CsTeamsMeetingPolicy" + ], + "Criticality": "Should", + "PolicyId": "MS.TEAMS.9.3v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-CsTenantFederationConfiguration" + ], + "Criticality": "Shall", + "PolicyId": "MS.TEAMS.4.1v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-CsTenantFederationConfiguration" + ], + "Criticality": "Shall", + "PolicyId": "MS.TEAMS.6.1v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [ + "Global" + ], + "Commandlet": [ + "Get-CsTeamsAppPermissionPolicy" + ], + "Criticality": "Should", + "PolicyId": "MS.TEAMS.8.2av1", + "ReportDetails": "1 meeting policy(ies) found that allow custom apps by default: Global", + "RequirementMet": false + }, + { + "ActualValue": [ + "Global" + ], + "Commandlet": [ + "Get-CsTeamsAppPermissionPolicy" + ], + "Criticality": "Should", + "PolicyId": "MS.TEAMS.8.2v1", + "ReportDetails": "1 meeting policy(ies) found that allow third-party apps by default: Global", + "RequirementMet": false + }, + { + "ActualValue": [ + "Global" + ], + "Commandlet": [ + "Get-CsTenantFederationConfiguration" + ], + "Criticality": "Shall", + "PolicyId": "MS.TEAMS.5.1v1", + "ReportDetails": "1 Configuration allowed unmanaged users to initiate contact with internal user across domains: Global", + "RequirementMet": false + }, + { + "ActualValue": [ + "Global" + ], + "Commandlet": [ + "Get-CsTenantFederationConfiguration" + ], + "Criticality": "Should", + "PolicyId": "MS.TEAMS.5.2v1", + "ReportDetails": "1 Internal users are enabled to initiate contact with unmanaged users across domains: Global", + "RequirementMet": false + } +] \ No newline at end of file diff --git a/Testing/Unit/PowerShell/CreateReport/Import-SecureBaseline.Tests.ps1 b/Testing/Unit/PowerShell/CreateReport/Import-SecureBaseline.Tests.ps1 new file mode 100644 index 0000000000..73414e4ce7 --- /dev/null +++ b/Testing/Unit/PowerShell/CreateReport/Import-SecureBaseline.Tests.ps1 @@ -0,0 +1,69 @@ +$CreateReportModulePath = Join-Path -Path $PSScriptRoot -ChildPath "../../../../PowerShell/ScubaGear/Modules/CreateReport/CreateReport.psm1" +Import-Module $CreateReportModulePath -Force + +InModuleScope CreateReport { + + Describe -tag "Markdown" -name 'Check Secure Baseline Markdown document for ' -ForEach @( + @{Product = "aad"; MarkdownFilePath = "baselines/aad.md"} + @{Product = "defender"; MarkdownFilePath = "baselines/defender.md"} + @{Product = "exo"; MarkdownFilePath = "baselines/exo.md"} + @{Product = "onedrive"; MarkdownFilePath = "baselines/onedrive.md"} + @{Product = "powerbi"; MarkdownFilePath = "baselines/powerbi.md"} + @{Product = "powerplatform"; MarkdownFilePath = "baselines/powerplatform.md"} + @{Product = "sharepoint"; MarkdownFilePath = "baselines/sharepoint.md"} + @{Product = "teams"; MarkdownFilePath = "baselines/teams.md"} + ){ + It "Markdown file exists for " { + Test-Path -Path $MarkdownFilePath | Should -BeTrue -Because "Current Location: $(Get-Location) File: $MarkdownFilePath " + } + } + Describe -tag "Markdown" -name 'Fail import secure baseline ' { + It "Fails on bad baseline path" { + {Import-SecureBaseline -BaselinePath "garbage path"} | + Should -Throw + } + } + Describe -tag "Markdown" -name 'Import secure baseline' { + BeforeAll{ + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', 'Baseline', Justification = 'Variable is used in another scope')] + $Baselines = Import-SecureBaseline -BaselinePath "./baselines/" + } + It "Validate import of markdown for all products" { + $Baselines.GetType().Name -Eq [hashtable] | Should -BeTrue + $Baselines.Count | Should -BeExactly 8 -Because "Markdown expected for all products." + } + It "Validate markdown group count for " -ForEach @( + @{Product = "aad"; GroupCount = 18; PolicyCount = 33} + @{Product = "defender"; GroupCount = 10; PolicyCount = 46} + @{Product = "exo"; GroupCount = 17; PolicyCount = 39} + @{Product = "onedrive"; GroupCount = 7; PolicyCount = 8} + @{Product = "powerbi"; GroupCount = 10; PolicyCount = 12} + @{Product = "powerplatform"; GroupCount = 4; PolicyCount = 8} + @{Product = "sharepoint"; GroupCount = 5; PolicyCount = 6} + @{Product = "teams"; GroupCount = 13; PolicyCount = 28} + ){ + {$Baselines.$Product} | Should -Not -Throw + $Groups = $Baselines.$Product + $Groups.Length | Should -BeExactly $GroupCount + + $NumberOfPolicies = 0 + foreach ($Group in $Groups){ + $Group.GroupName | Should -Not -BeNullOrEmpty + [int]$Group.GroupNumber | Should -BeLessOrEqual $GroupCount + $Controls = $Group.Controls + $NumberOfPolicies += $Controls.Length + + foreach ($Control in $Controls){ + $Control.Id -Match "^MS\.$($Product.ToUpper())\.\d{1,}\.\d{1,}v\d{1,}$" | Should -BeTrue + $Control.Value -Match "^.*\.$" | Should -BeTrue -Because "$Control.Id does not end with period." + #$Control.Value -Match '^(.+)(SHALL|SHOULD|MAY){1,1}(.+\.)$' + #@("SHALL", "SHOULD", "MAY") -Contains $Matches.2 | Should -BeTrue -Because "$($Control.Id) must contain valid criticality but has $($Matches.2)" + #@("SHALL", "SHOULD", "MAY") -Contains $Control.Criticality | Should -BeTrue + $Control.Deleted.GetType() -Eq [bool]| Should -BeTrue -Because "Type should be boolean." + } + } + + $NumberOfPolicies | Should -BeExactly $PolicyCount + } + } +} \ No newline at end of file diff --git a/Testing/Unit/PowerShell/CreateReport/New-MarkdownAnchor.Tests.ps1 b/Testing/Unit/PowerShell/CreateReport/New-MarkdownAnchor.Tests.ps1 new file mode 100644 index 0000000000..92178de4bc --- /dev/null +++ b/Testing/Unit/PowerShell/CreateReport/New-MarkdownAnchor.Tests.ps1 @@ -0,0 +1,40 @@ +$CreateReportModulePath = Join-Path -Path $PSScriptRoot -ChildPath "../../../../PowerShell/ScubaGear/Modules/CreateReport/CreateReport.psm1" +Import-Module $CreateReportModulePath + +InModuleScope CreateReport { + Describe -Tag "Markdown" -name "Parameter error handling" { + It "Empty group number" { + {New-MarkdownAnchor -GroupNumber "" -GroupName "A valid name"} | + Should -Throw -Because "Invalid GroupNumber parameter" + } + It "Empty group name" { + {New-MarkdownAnchor -GroupNumber "1" -GroupName ""} | + Should -Throw -Because "Invalid GroupName parameter" + } + It "Null group number" { + {New-MarkdownAnchor -GroupNumber $null -GroupName "A valid name"} | + Should -Throw -Because "Invalid GroupNumber parameter" + } + It "Null group name" { + {New-MarkdownAnchor -GroupNumber "1" -GroupName $null} | + Should -Throw -Because "Invalid GroupName parameter" + } + It "Bad group number" { + {New-MarkdownAnchor -GroupNumber "-" -GroupName "A valid name"} | + Should -Throw -ExceptionType ArgumentException + } + } + + Describe -tag "Markdown" -name 'Test HTML document anchors' { + It "Test Valid Group Data: " -ForEach @( + @{ GroupNumber = " 1"; GroupName = "A leading space" }, + @{ GroupNumber = "99 "; GroupName = "The trailing space"} + ){ + $Anchor = New-MarkdownAnchor -GroupNumber $GroupNumber -GroupName $GroupName + $Anchor.StartsWith("#$GoupNumber") | Should -BeTrue + $Anchor -Contains " " | Should -BeFalse + $GroupName.Split(' ').ForEach{ + $Anchor -Like "*$($_.ToLower())*" | Should -BeTrue -Because "$Anchor contains $($_.ToLower())"} + } + } +} \ No newline at end of file diff --git a/Testing/Unit/PowerShell/CreateReport/New-Report.Tests.ps1 b/Testing/Unit/PowerShell/CreateReport/New-Report.Tests.ps1 index 3e4c3b22fb..b39fd24f98 100644 --- a/Testing/Unit/PowerShell/CreateReport/New-Report.Tests.ps1 +++ b/Testing/Unit/PowerShell/CreateReport/New-Report.Tests.ps1 @@ -1,14 +1,14 @@ -BeforeAll { - Import-Module (Join-Path -Path $PSScriptRoot -ChildPath '../../../../PowerShell/ScubaGear/Modules/CreateReport') - New-Item -Path (Join-Path -Path $PSScriptRoot -ChildPath "./CreateReportStubs") -Name "CreateReportUnitFolder" -ErrorAction SilentlyContinue -ItemType Directory | Out-Null - New-Item -Path (Join-Path -Path $PSScriptRoot -ChildPath "./CreateReportStubs/CreateReportUnitFolder") -Name "IndividualReports" -ErrorAction SilentlyContinue -ItemType Directory | Out-Null -} +Import-Module (Join-Path -Path $PSScriptRoot -ChildPath '../../../../PowerShell/ScubaGear/Modules/CreateReport') -Describe -Tag CreateReport -Name 'New-Report' { - Context "Light mode case" { +InModuleScope CreateReport { + Describe -Tag CreateReport -Name 'New-Report' { BeforeAll { - [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', 'ProductNames')] - $ProductNames = @("teams", "exo", "defender", "aad", "powerplatform", "sharepoint", "onedrive") + Mock -CommandName Write-Error {} + New-Item -Path (Join-Path -Path "TestDrive:" -ChildPath "CreateReportStubs") -Name "CreateReportUnitFolder" -ItemType Directory + New-Item -Path (Join-Path -Path "TestDrive:" -ChildPath "CreateReportStubs/CreateReportUnitFolder") -Name "IndividualReports" -ItemType Directory + $TestOutPath = (Join-Path -Path "TestDrive:" -ChildPath "CreateReportStubs") + Copy-Item -Path (Join-Path -Path $PSScriptRoot -ChildPath "CreateReportStubs/*") -Destination $TestOutPath -Recurse + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', 'ArgToProd')] $ArgToProd = @{ teams = "Teams"; @@ -29,83 +29,39 @@ Describe -Tag CreateReport -Name 'New-Report' { SharePoint = "SharePoint Online"; OneDrive = "OneDrive for Business"; } - $IndividualReportPath = (Join-Path -Path $PSScriptRoot -ChildPath "./CreateReportStubs/CreateReportUnitFolder/IndividualReports") + $IndividualReportPath = (Join-Path -Path "TestDrive:" -ChildPath "CreateReportStubs/CreateReportUnitFolder/IndividualReports") [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', 'CreateReportParams')] $CreateReportParams = @{ - 'IndividualReportPath' = $IndividualReportPath; - 'OutPath' = (Join-Path -Path $PSScriptRoot -ChildPath "./CreateReportStubs"); - 'OutProviderFileName' = "ProviderSettingsExport"; - 'OutRegoFileName' = "TestResults"; - 'DarkMode' = $false; - } - } - It 'Creates a report for Azure Active Directory' { - $ProductName = 'aad' - $CreateReportParams += @{ - 'BaselineName' = $ArgToProd[$ProductName]; - 'FullName' = $ProdToFullName[$ProductName]; - } - New-Report @CreateReportParams - Test-Path -Path "$($IndividualReportPath)/$($ArgToProd[$ProductName])Report.html" -PathType leaf | Should -Be $true - } - It 'Creates a report for Microsoft Defender for Office 365' { - $ProductName = 'defender' - $CreateReportParams += @{ - 'BaselineName' = $ArgToProd[$ProductName]; - 'FullName' = $ProdToFullName[$ProductName]; - } - New-Report @CreateReportParams - Test-Path -Path "$($IndividualReportPath)/$($ArgToProd[$ProductName])Report.html" -PathType leaf | Should -Be $true - } - It 'Creates a report for Exchange Online' { - $ProductName = 'exo' - $CreateReportParams += @{ - 'BaselineName' = $ArgToProd[$ProductName]; - 'FullName' = $ProdToFullName[$ProductName]; - } - New-Report @CreateReportParams - Test-Path -Path "$($IndividualReportPath)/$($ArgToProd[$ProductName])Report.html" -PathType leaf | Should -Be $true - } - It 'Creates a report for One Drive for Business' { - $ProductName = 'onedrive' - $CreateReportParams += @{ - 'BaselineName' = $ArgToProd[$ProductName]; - 'FullName' = $ProdToFullName[$ProductName]; - } - New-Report @CreateReportParams - Test-Path -Path "$($IndividualReportPath)/$($ArgToProd[$ProductName])Report.html" -PathType leaf | Should -Be $true - } - It 'Creates a report for Power Platform' { - $ProductName = 'powerplatform' - $CreateReportParams += @{ - 'BaselineName' = $ArgToProd[$ProductName]; - 'FullName' = $ProdToFullName[$ProductName]; + 'IndividualReportPath' = $IndividualReportPath + 'OutPath' = $TestOutPath + 'OutProviderFileName' = "ProviderSettingsExport" + 'OutRegoFileName' = "TestResults" + 'DarkMode' = $false + 'SecureBaselines' = Import-SecureBaseline } - New-Report @CreateReportParams - Test-Path -Path "$($IndividualReportPath)/$($ArgToProd[$ProductName])Report.html" -PathType leaf | Should -Be $true } - It 'Creates a report for SharePoint Online' { - $ProductName = 'sharepoint' + It 'Creates a report for ' -ForEach @( + @{Product = 'aad'; ErrorCount = 1}, + @{Product = 'defender'; ErrorCount = 3}, + @{Product = 'exo'; ErrorCount = 2}, + @{Product = 'onedrive'; ErrorCount = 8}, + @{Product = 'powerplatform'; ErrorCount = 0}, + @{Product = 'sharepoint'; ErrorCount = 3}, + @{Product = 'teams'; ErrorCount = 5} + ){ $CreateReportParams += @{ - 'BaselineName' = $ArgToProd[$ProductName]; - 'FullName' = $ProdToFullName[$ProductName]; + 'BaselineName' = $ArgToProd[$Product]; + 'FullName' = $ProdToFullName[$Product]; } - New-Report @CreateReportParams - Test-Path -Path "$($IndividualReportPath)/$($ArgToProd[$ProductName])Report.html" -PathType leaf | Should -Be $true - } - It 'Creates a report for Microsoft Teams' { - $ProductName = 'teams' - $CreateReportParams += @{ - 'BaselineName' = $ArgToProd[$ProductName]; - 'FullName' = $ProdToFullName[$ProductName]; - } - New-Report @CreateReportParams - Test-Path -Path "$($IndividualReportPath)/$($ArgToProd[$ProductName])Report.html" -PathType leaf | Should -Be $true + + { New-Report @CreateReportParams } | Should -Not -Throw + + Should -Invoke -CommandName Write-Error -Exactly -Times $ErrorCount + Test-Path -Path "$($IndividualReportPath)/$($ArgToProd[$Product])Report.html" -PathType leaf | Should -Be $true } } -} -AfterAll { - Remove-Module CreateReport -ErrorAction SilentlyContinue - Remove-Item -Recurse -Force -Path (Join-Path -Path $PSScriptRoot -ChildPath "./CreateReportStubs/CreateReportUnitFolder") -ErrorAction SilentlyContinue -} + AfterAll { + Remove-Module CreateReport -ErrorAction SilentlyContinue + } +} \ No newline at end of file diff --git a/Testing/Unit/PowerShell/Orchestrator/Invoke-ReportCreation.Tests.ps1 b/Testing/Unit/PowerShell/Orchestrator/Invoke-ReportCreation.Tests.ps1 index d58824481a..d21798612d 100644 --- a/Testing/Unit/PowerShell/Orchestrator/Invoke-ReportCreation.Tests.ps1 +++ b/Testing/Unit/PowerShell/Orchestrator/Invoke-ReportCreation.Tests.ps1 @@ -8,7 +8,10 @@ InModuleScope Orchestrator { Mock -ModuleName Orchestrator New-Report {} function Pluralize {} Mock -ModuleName Orchestrator Pluralize {} - + function Import-SecureBaseline{} + Mock -ModuleName Orchestrator Import-SecureBaseline { + return @() + } Mock -CommandName Write-Progress {} Mock -CommandName Join-Path { "." } Mock -CommandName Out-File {} diff --git a/Testing/Unit/PowerShell/ScubaConfig/ScubaConfigDeleteTests.ps1 b/Testing/Unit/PowerShell/ScubaConfig/ScubaConfigDelete.Tests.ps1 similarity index 100% rename from Testing/Unit/PowerShell/ScubaConfig/ScubaConfigDeleteTests.ps1 rename to Testing/Unit/PowerShell/ScubaConfig/ScubaConfigDelete.Tests.ps1 diff --git a/Testing/Unit/Rego/AAD/AADConfig2_05_test.rego b/Testing/Unit/Rego/AAD/AADConfig2_05_test.rego deleted file mode 100644 index 529a8a0e9a..0000000000 --- a/Testing/Unit/Rego/AAD/AADConfig2_05_test.rego +++ /dev/null @@ -1,35 +0,0 @@ -package aad -import future.keywords - - -# -# Policy 1 -#-- -test_NotImplemented_Correct_V1 if { - ControlNumber := "AAD 2.5" - Requirement := "The following critical logs SHALL be sent at a minimum: AuditLogs, SignInLogs, RiskyUsers, UserRiskEvents, NonInteractiveUserSignInLogs, ServicePrincipalSignInLogs, ADFSSignInLogs, RiskyServicePrincipals, ServicePrincipalRiskEvents" - - Output := tests with input as { } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Currently cannot be checked automatically. See Azure Active Directory Secure Configuration Baseline policy 2.5 for instructions on manual check" -} - -# -# Policy 2 -#-- -test_NotImplemented_Correct_V2 if { - ControlNumber := "AAD 2.5" - Requirement := "The logs SHALL be sent to the agency's SOC for monitoring" - - Output := tests with input as { } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Currently cannot be checked automatically. See Azure Active Directory Secure Configuration Baseline policy 2.5 for instructions on manual check" -} \ No newline at end of file diff --git a/Testing/Unit/Rego/AAD/AADConfig2_08_test.rego b/Testing/Unit/Rego/AAD/AADConfig2_08_test.rego deleted file mode 100644 index 009b21f2b1..0000000000 --- a/Testing/Unit/Rego/AAD/AADConfig2_08_test.rego +++ /dev/null @@ -1,19 +0,0 @@ -package aad -import future.keywords - - -# -# Policy 1 -#-- -test_NotImplemented_Correct if { - ControlNumber := "AAD 2.8" - Requirement := "User passwords SHALL NOT expire" - - Output := tests with input as { } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Currently cannot be checked automatically. See Azure Active Directory Secure Configuration Baseline policy 2.8 for instructions on manual check" -} \ No newline at end of file diff --git a/Testing/Unit/Rego/AAD/AADConfig2_01_test.rego b/Testing/Unit/Rego/AAD/AADConfig_01_test.rego similarity index 86% rename from Testing/Unit/Rego/AAD/AADConfig2_01_test.rego rename to Testing/Unit/Rego/AAD/AADConfig_01_test.rego index c2dcf7ede8..89470124d1 100644 --- a/Testing/Unit/Rego/AAD/AADConfig2_01_test.rego +++ b/Testing/Unit/Rego/AAD/AADConfig_01_test.rego @@ -1,13 +1,11 @@ package aad import future.keywords - # # Policy 1 #--tests for no exclusions test_NoExclusionsConditions_Correct if { - ControlNumber := "AAD 2.1" - Requirement := "Legacy authentication SHALL be blocked" + PolicyId := "MS.AAD.1.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -33,7 +31,7 @@ test_NoExclusionsConditions_Correct if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -41,8 +39,7 @@ test_NoExclusionsConditions_Correct if { } test_NoExclusionsIncludeApplications_Incorrect if { - ControlNumber := "AAD 2.1" - Requirement := "Legacy authentication SHALL be blocked" + PolicyId := "MS.AAD.1.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -67,7 +64,7 @@ test_NoExclusionsIncludeApplications_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -75,8 +72,7 @@ test_NoExclusionsIncludeApplications_Incorrect if { } test_NoExclusionsIncludeUsers_Incorrect if { - ControlNumber := "AAD 2.1" - Requirement := "Legacy authentication SHALL be blocked" + PolicyId := "MS.AAD.1.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -101,7 +97,7 @@ test_NoExclusionsIncludeUsers_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -109,8 +105,7 @@ test_NoExclusionsIncludeUsers_Incorrect if { } test_NoExclusionsExcludeUsers_Incorrect if { - ControlNumber := "AAD 2.1" - Requirement := "Legacy authentication SHALL be blocked" + PolicyId := "MS.AAD.1.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -136,7 +131,7 @@ test_NoExclusionsExcludeUsers_Incorrect if { } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -144,8 +139,7 @@ test_NoExclusionsExcludeUsers_Incorrect if { } test_NoExclusionsExcludeGroups_Incorrect if { - ControlNumber := "AAD 2.1" - Requirement := "Legacy authentication SHALL be blocked" + PolicyId := "MS.AAD.1.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -170,7 +164,7 @@ test_NoExclusionsExcludeGroups_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -178,8 +172,7 @@ test_NoExclusionsExcludeGroups_Incorrect if { } test_NoExclusionsClientAppTypes_Incorrect if { - ControlNumber := "AAD 2.1" - Requirement := "Legacy authentication SHALL be blocked" + PolicyId := "MS.AAD.1.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -204,7 +197,7 @@ test_NoExclusionsClientAppTypes_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -212,8 +205,7 @@ test_NoExclusionsClientAppTypes_Incorrect if { } test_NoExclusionsBuiltInControls_Incorrect if { - ControlNumber := "AAD 2.1" - Requirement := "Legacy authentication SHALL be blocked" + PolicyId := "MS.AAD.1.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -238,7 +230,7 @@ test_NoExclusionsBuiltInControls_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -246,8 +238,7 @@ test_NoExclusionsBuiltInControls_Incorrect if { } test_NoExclusionsState_Incorrect if { - ControlNumber := "AAD 2.1" - Requirement := "Legacy authentication SHALL be blocked" + PolicyId := "MS.AAD.1.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -272,7 +263,7 @@ test_NoExclusionsState_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -281,8 +272,7 @@ test_NoExclusionsState_Incorrect if { #--tests for user exclusions and no group exclusions test_NoExclusionsExemptUsers_Correct if { - ControlNumber := "AAD 2.1" - Requirement := "Legacy authentication SHALL be blocked" + PolicyId := "MS.AAD.1.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -320,7 +310,7 @@ test_NoExclusionsExemptUsers_Correct if { } } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -328,8 +318,7 @@ test_NoExclusionsExemptUsers_Correct if { } test_UserExclusionsConditions_Correct if { - ControlNumber := "AAD 2.1" - Requirement := "Legacy authentication SHALL be blocked" + PolicyId := "MS.AAD.1.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -366,7 +355,7 @@ test_UserExclusionsConditions_Correct if { } } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -374,8 +363,7 @@ test_UserExclusionsConditions_Correct if { } test_MultiUserExclusionsConditions_Correct if { - ControlNumber := "AAD 2.1" - Requirement := "Legacy authentication SHALL be blocked" + PolicyId := "MS.AAD.1.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -413,7 +401,7 @@ test_MultiUserExclusionsConditions_Correct if { } } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -421,8 +409,7 @@ test_MultiUserExclusionsConditions_Correct if { } test_UserExclusionNoExempt_Incorrect if { - ControlNumber := "AAD 2.1" - Requirement := "Legacy authentication SHALL be blocked" + PolicyId := "MS.AAD.1.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -446,7 +433,7 @@ test_UserExclusionNoExempt_Incorrect if { } ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -454,8 +441,7 @@ test_UserExclusionNoExempt_Incorrect if { } test_UserExclusionsSingleExempt_Incorrect if { - ControlNumber := "AAD 2.1" - Requirement := "Legacy authentication SHALL be blocked" + PolicyId := "MS.AAD.1.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -491,7 +477,7 @@ test_UserExclusionsSingleExempt_Incorrect if { } } } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -499,8 +485,7 @@ test_UserExclusionsSingleExempt_Incorrect if { } test_UserExclusionsNoExempt_Incorrect if { - ControlNumber := "AAD 2.1" - Requirement := "Legacy authentication SHALL be blocked" + PolicyId := "MS.AAD.1.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -535,7 +520,7 @@ test_UserExclusionsNoExempt_Incorrect if { } } } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -543,8 +528,7 @@ test_UserExclusionsNoExempt_Incorrect if { } test_UserExclusionsIncludeApplications_Incorrect if { - ControlNumber := "AAD 2.1" - Requirement := "Legacy authentication SHALL be blocked" + PolicyId := "MS.AAD.1.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -580,7 +564,7 @@ test_UserExclusionsIncludeApplications_Incorrect if { } } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -588,8 +572,7 @@ test_UserExclusionsIncludeApplications_Incorrect if { } test_UserExclusionsIncludeUsers_Incorrect if { - ControlNumber := "AAD 2.1" - Requirement := "Legacy authentication SHALL be blocked" + PolicyId := "MS.AAD.1.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -625,7 +608,7 @@ test_UserExclusionsIncludeUsers_Incorrect if { } } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -633,8 +616,7 @@ test_UserExclusionsIncludeUsers_Incorrect if { } test_UserExclusionsExcludeGroups_Incorrect if { - ControlNumber := "AAD 2.1" - Requirement := "Legacy authentication SHALL be blocked" + PolicyId := "MS.AAD.1.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -669,7 +651,7 @@ test_UserExclusionsExcludeGroups_Incorrect if { } } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -677,8 +659,7 @@ test_UserExclusionsExcludeGroups_Incorrect if { } test_UserExclusionsClientAppTypes_Incorrect if { - ControlNumber := "AAD 2.1" - Requirement := "Legacy authentication SHALL be blocked" + PolicyId := "MS.AAD.1.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -715,7 +696,7 @@ test_UserExclusionsClientAppTypes_Incorrect if { } } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -723,8 +704,7 @@ test_UserExclusionsClientAppTypes_Incorrect if { } test_UserExclusionsBuiltInControls_Incorrect if { - ControlNumber := "AAD 2.1" - Requirement := "Legacy authentication SHALL be blocked" + PolicyId := "MS.AAD.1.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -761,7 +741,7 @@ test_UserExclusionsBuiltInControls_Incorrect if { } } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -769,8 +749,7 @@ test_UserExclusionsBuiltInControls_Incorrect if { } test_UserExclusionsState_Incorrect if { - ControlNumber := "AAD 2.1" - Requirement := "Legacy authentication SHALL be blocked" + PolicyId := "MS.AAD.1.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -808,7 +787,7 @@ test_UserExclusionsState_Incorrect if { } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -817,8 +796,7 @@ test_UserExclusionsState_Incorrect if { #--tests for group exclusions and no user exclusions test_NoExclusionsExemptGroups_Correct if { - ControlNumber := "AAD 2.1" - Requirement := "Legacy authentication SHALL be blocked" + PolicyId := "MS.AAD.1.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -856,7 +834,7 @@ test_NoExclusionsExemptGroups_Correct if { } } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -864,8 +842,7 @@ test_NoExclusionsExemptGroups_Correct if { } test_GroupExclusionNoExempt_Incorrect if { - ControlNumber := "AAD 2.1" - Requirement := "Legacy authentication SHALL be blocked" + PolicyId := "MS.AAD.1.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -903,7 +880,7 @@ test_GroupExclusionNoExempt_Incorrect if { } } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -911,8 +888,7 @@ test_GroupExclusionNoExempt_Incorrect if { } test_GroupExclusionsNoExempt_Incorrect if { - ControlNumber := "AAD 2.1" - Requirement := "Legacy authentication SHALL be blocked" + PolicyId := "MS.AAD.1.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -949,7 +925,7 @@ test_GroupExclusionsNoExempt_Incorrect if { } } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -957,8 +933,7 @@ test_GroupExclusionsNoExempt_Incorrect if { } test_GroupExclusionsSingleExempt_Incorrect if { - ControlNumber := "AAD 2.1" - Requirement := "Legacy authentication SHALL be blocked" + PolicyId := "MS.AAD.1.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -995,7 +970,7 @@ test_GroupExclusionsSingleExempt_Incorrect if { } } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -1003,8 +978,7 @@ test_GroupExclusionsSingleExempt_Incorrect if { } test_GroupExclusionConditions_Correct if { - ControlNumber := "AAD 2.1" - Requirement := "Legacy authentication SHALL be blocked" + PolicyId := "MS.AAD.1.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -1042,7 +1016,7 @@ test_GroupExclusionConditions_Correct if { } } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -1050,8 +1024,7 @@ test_GroupExclusionConditions_Correct if { } test_MultiGroupExclusionsConditions_Correct if { - ControlNumber := "AAD 2.1" - Requirement := "Legacy authentication SHALL be blocked" + PolicyId := "MS.AAD.1.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -1089,7 +1062,7 @@ test_MultiGroupExclusionsConditions_Correct if { } } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -1098,8 +1071,7 @@ test_MultiGroupExclusionsConditions_Correct if { #--tests when both group and user exclusions present test_UserGroupExclusionConditions_Correct if { - ControlNumber := "AAD 2.1" - Requirement := "Legacy authentication SHALL be blocked" + PolicyId := "MS.AAD.1.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -1137,7 +1109,7 @@ test_UserGroupExclusionConditions_Correct if { } } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -1145,8 +1117,7 @@ test_UserGroupExclusionConditions_Correct if { } test_UserGroupExclusionNoExempt_Incorrect if { - ControlNumber := "AAD 2.1" - Requirement := "Legacy authentication SHALL be blocked" + PolicyId := "MS.AAD.1.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -1172,7 +1143,7 @@ test_UserGroupExclusionNoExempt_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -1180,8 +1151,7 @@ test_UserGroupExclusionNoExempt_Incorrect if { } test_UserGroupExclusionUserExemptOnly_Incorrect if { - ControlNumber := "AAD 2.1" - Requirement := "Legacy authentication SHALL be blocked" + PolicyId := "MS.AAD.1.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -1219,7 +1189,7 @@ test_UserGroupExclusionUserExemptOnly_Incorrect if { } } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -1227,8 +1197,7 @@ test_UserGroupExclusionUserExemptOnly_Incorrect if { } test_UserGroupExclusionGroupExemptOnly_Incorrect if { - ControlNumber := "AAD 2.1" - Requirement := "Legacy authentication SHALL be blocked" + PolicyId := "MS.AAD.1.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -1266,7 +1235,7 @@ test_UserGroupExclusionGroupExemptOnly_Incorrect if { } } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -1274,8 +1243,7 @@ test_UserGroupExclusionGroupExemptOnly_Incorrect if { } test_UserGroupExclusionTooFewUserExempts_Incorrect if { - ControlNumber := "AAD 2.1" - Requirement := "Legacy authentication SHALL be blocked" + PolicyId := "MS.AAD.1.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -1313,7 +1281,7 @@ test_UserGroupExclusionTooFewUserExempts_Incorrect if { } } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet diff --git a/Testing/Unit/Rego/AAD/AADConfig2_02_test.rego b/Testing/Unit/Rego/AAD/AADConfig_02_test.rego similarity index 86% rename from Testing/Unit/Rego/AAD/AADConfig2_02_test.rego rename to Testing/Unit/Rego/AAD/AADConfig_02_test.rego index 6ed420eb79..aa826a04ff 100644 --- a/Testing/Unit/Rego/AAD/AADConfig2_02_test.rego +++ b/Testing/Unit/Rego/AAD/AADConfig_02_test.rego @@ -1,5 +1,6 @@ package aad import future.keywords +import data.report.utils.NotCheckedDetails # @@ -7,8 +8,7 @@ import future.keywords #-- test_NoExclusionsConditions_Correct if { - ControlNumber := "AAD 2.2" - Requirement := "Users detected as high risk SHALL be blocked" + PolicyId := "MS.AAD.2.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -43,7 +43,7 @@ test_NoExclusionsConditions_Correct if { } ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -51,8 +51,7 @@ test_NoExclusionsConditions_Correct if { } test_NoExclusionsExemptUsers_Correct if { - ControlNumber := "AAD 2.2" - Requirement := "Users detected as high risk SHALL be blocked" + PolicyId := "MS.AAD.2.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -99,7 +98,7 @@ test_NoExclusionsExemptUsers_Correct if { } } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -107,8 +106,7 @@ test_NoExclusionsExemptUsers_Correct if { } test_NoExclusionsExemptGroups_Correct if { - ControlNumber := "AAD 2.2" - Requirement := "Users detected as high risk SHALL be blocked" + PolicyId := "MS.AAD.2.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -155,7 +153,7 @@ test_NoExclusionsExemptGroups_Correct if { } } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -164,8 +162,7 @@ test_NoExclusionsExemptGroups_Correct if { # User exclusions test test_UserExclusionNoExempt_Incorrect if { - ControlNumber := "AAD 2.2" - Requirement := "Users detected as high risk SHALL be blocked" + PolicyId := "MS.AAD.2.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -200,7 +197,7 @@ test_UserExclusionNoExempt_Incorrect if { } ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -208,8 +205,7 @@ test_UserExclusionNoExempt_Incorrect if { } test_UserExclusionConditions_Correct if { - ControlNumber := "AAD 2.2" - Requirement := "Users detected as high risk SHALL be blocked" + PolicyId := "MS.AAD.2.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -256,7 +252,7 @@ test_UserExclusionConditions_Correct if { } } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -264,8 +260,7 @@ test_UserExclusionConditions_Correct if { } test_UserExclusionsNoExempt_Incorrect if { - ControlNumber := "AAD 2.2" - Requirement := "Users detected as high risk SHALL be blocked" + PolicyId := "MS.AAD.2.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -300,7 +295,7 @@ test_UserExclusionsNoExempt_Incorrect if { } ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -308,8 +303,7 @@ test_UserExclusionsNoExempt_Incorrect if { } test_UserExclusionsSingleExempt_Incorrect if { - ControlNumber := "AAD 2.2" - Requirement := "Users detected as high risk SHALL be blocked" + PolicyId := "MS.AAD.2.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -356,7 +350,7 @@ test_UserExclusionsSingleExempt_Incorrect if { } } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -364,8 +358,7 @@ test_UserExclusionsSingleExempt_Incorrect if { } test_MultiUserExclusionsConditions_Correct if { - ControlNumber := "AAD 2.2" - Requirement := "Users detected as high risk SHALL be blocked" + PolicyId := "MS.AAD.2.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -412,7 +405,7 @@ test_MultiUserExclusionsConditions_Correct if { } } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -421,8 +414,7 @@ test_MultiUserExclusionsConditions_Correct if { # Group Exclusion tests test_GroupExclusionNoExempt_Incorrect if { - ControlNumber := "AAD 2.2" - Requirement := "Users detected as high risk SHALL be blocked" + PolicyId := "MS.AAD.2.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -457,7 +449,7 @@ test_GroupExclusionNoExempt_Incorrect if { } ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -465,8 +457,7 @@ test_GroupExclusionNoExempt_Incorrect if { } test_GroupExclusionsConditions_Correct if { - ControlNumber := "AAD 2.2" - Requirement := "Users detected as high risk SHALL be blocked" + PolicyId := "MS.AAD.2.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -512,7 +503,7 @@ test_GroupExclusionsConditions_Correct if { } } } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -520,8 +511,7 @@ test_GroupExclusionsConditions_Correct if { } test_GroupExclusionsNoExempt_Incorrect if { - ControlNumber := "AAD 2.2" - Requirement := "Users detected as high risk SHALL be blocked" + PolicyId := "MS.AAD.2.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -556,7 +546,7 @@ test_GroupExclusionsNoExempt_Incorrect if { } ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -564,8 +554,7 @@ test_GroupExclusionsNoExempt_Incorrect if { } test_GroupExclusionsSingleExempt_Incorrect if { - ControlNumber := "AAD 2.2" - Requirement := "Users detected as high risk SHALL be blocked" + PolicyId := "MS.AAD.2.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -611,7 +600,7 @@ test_GroupExclusionsSingleExempt_Incorrect if { } } } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -619,8 +608,7 @@ test_GroupExclusionsSingleExempt_Incorrect if { } test_MultiGroupExclusionsConditions_Correct if { - ControlNumber := "AAD 2.2" - Requirement := "Users detected as high risk SHALL be blocked" + PolicyId := "MS.AAD.2.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -666,7 +654,7 @@ test_MultiGroupExclusionsConditions_Correct if { } } } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -675,8 +663,7 @@ test_MultiGroupExclusionsConditions_Correct if { # User and group exclusions tests test_UserGroupExclusionConditions_Correct if { - ControlNumber := "AAD 2.2" - Requirement := "Users detected as high risk SHALL be blocked" + PolicyId := "MS.AAD.2.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -721,7 +708,7 @@ test_UserGroupExclusionConditions_Correct if { } } } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -729,8 +716,7 @@ test_UserGroupExclusionConditions_Correct if { } test_UserGroupExclusionNoExempt_Incorrect if { - ControlNumber := "AAD 2.2" - Requirement := "Users detected as high risk SHALL be blocked" + PolicyId := "MS.AAD.2.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -765,7 +751,7 @@ test_UserGroupExclusionNoExempt_Incorrect if { } ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -773,8 +759,7 @@ test_UserGroupExclusionNoExempt_Incorrect if { } test_UserGroupExclusionUserExemptOnly_Incorrect if { - ControlNumber := "AAD 2.2" - Requirement := "Users detected as high risk SHALL be blocked" + PolicyId := "MS.AAD.2.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -819,7 +804,7 @@ test_UserGroupExclusionUserExemptOnly_Incorrect if { } } } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -827,8 +812,7 @@ test_UserGroupExclusionUserExemptOnly_Incorrect if { } test_UserGroupExclusionGroupExemptOnly_Incorrect if { - ControlNumber := "AAD 2.2" - Requirement := "Users detected as high risk SHALL be blocked" + PolicyId := "MS.AAD.2.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -873,7 +857,7 @@ test_UserGroupExclusionGroupExemptOnly_Incorrect if { } } } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -881,8 +865,7 @@ test_UserGroupExclusionGroupExemptOnly_Incorrect if { } test_UserGroupExclusionTooFewUserExempts_Incorrect if { - ControlNumber := "AAD 2.2" - Requirement := "Users detected as high risk SHALL be blocked" + PolicyId := "MS.AAD.2.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -927,7 +910,7 @@ test_UserGroupExclusionTooFewUserExempts_Incorrect if { } } } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -936,8 +919,7 @@ test_UserGroupExclusionTooFewUserExempts_Incorrect if { # Other Conditions tests test_IncludeApplications_Incorrect if { - ControlNumber := "AAD 2.2" - Requirement := "Users detected as high risk SHALL be blocked" + PolicyId := "MS.AAD.2.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -973,7 +955,7 @@ test_IncludeApplications_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -981,8 +963,7 @@ test_IncludeApplications_Incorrect if { } test_IncludeUsers_Incorrect if { - ControlNumber := "AAD 2.2" - Requirement := "Users detected as high risk SHALL be blocked" + PolicyId := "MS.AAD.2.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -1018,7 +999,7 @@ test_IncludeUsers_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -1026,8 +1007,7 @@ test_IncludeUsers_Incorrect if { } test_ExcludeUsers_Incorrect if { - ControlNumber := "AAD 2.2" - Requirement := "Users detected as high risk SHALL be blocked" + PolicyId := "MS.AAD.2.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -1063,7 +1043,7 @@ test_ExcludeUsers_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -1071,8 +1051,7 @@ test_ExcludeUsers_Incorrect if { } test_ExcludeGroups_Incorrect if { - ControlNumber := "AAD 2.2" - Requirement := "Users detected as high risk SHALL be blocked" + PolicyId := "MS.AAD.2.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -1108,7 +1087,7 @@ test_ExcludeGroups_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -1116,8 +1095,7 @@ test_ExcludeGroups_Incorrect if { } test_ExcludeRoles_Incorrect if { - ControlNumber := "AAD 2.2" - Requirement := "Users detected as high risk SHALL be blocked" + PolicyId := "MS.AAD.2.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -1153,7 +1131,7 @@ test_ExcludeRoles_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -1161,8 +1139,7 @@ test_ExcludeRoles_Incorrect if { } test_BuiltInControls_Incorrect if { - ControlNumber := "AAD 2.2" - Requirement := "Users detected as high risk SHALL be blocked" + PolicyId := "MS.AAD.2.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -1198,7 +1175,7 @@ test_BuiltInControls_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -1206,8 +1183,7 @@ test_BuiltInControls_Incorrect if { } test_State_Incorrect if { - ControlNumber := "AAD 2.2" - Requirement := "Users detected as high risk SHALL be blocked" + PolicyId := "MS.AAD.2.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -1243,7 +1219,7 @@ test_State_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -1251,8 +1227,7 @@ test_State_Incorrect if { } test_UserRiskLevels_Incorrect if { - ControlNumber := "AAD 2.2" - Requirement := "Users detected as high risk SHALL be blocked" + PolicyId := "MS.AAD.2.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -1288,7 +1263,7 @@ test_UserRiskLevels_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -1296,8 +1271,7 @@ test_UserRiskLevels_Incorrect if { } test_ServicePlans_Incorrect if { - ControlNumber := "AAD 2.2" - Requirement := "Users detected as high risk SHALL be blocked" + PolicyId := "MS.AAD.2.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -1329,7 +1303,7 @@ test_ServicePlans_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -1340,14 +1314,13 @@ test_ServicePlans_Incorrect if { # Policy 2 #-- test_NotImplemented_Correct if { - ControlNumber := "AAD 2.2" - Requirement := "A notification SHOULD be sent to the administrator when high-risk users are detected" + PolicyId := "MS.AAD.2.2v1" Output := tests with input as { } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Currently cannot be checked automatically. See Azure Active Directory Secure Configuration Baseline policy 2.2 for instructions on manual check" + RuleOutput[0].ReportDetails == NotCheckedDetails(PolicyId) } \ No newline at end of file diff --git a/Testing/Unit/Rego/AAD/AADConfig2_03_test.rego b/Testing/Unit/Rego/AAD/AADConfig_03_test.rego similarity index 87% rename from Testing/Unit/Rego/AAD/AADConfig2_03_test.rego rename to Testing/Unit/Rego/AAD/AADConfig_03_test.rego index 99c191f682..e9987c0489 100644 --- a/Testing/Unit/Rego/AAD/AADConfig2_03_test.rego +++ b/Testing/Unit/Rego/AAD/AADConfig_03_test.rego @@ -7,8 +7,7 @@ import future.keywords #-- test_NoExclusionsConditions_Correct if { - ControlNumber := "AAD 2.3" - Requirement := "Sign-ins detected as high risk SHALL be blocked" + PolicyId := "MS.AAD.3.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -43,7 +42,7 @@ test_NoExclusionsConditions_Correct if { } ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -51,8 +50,7 @@ test_NoExclusionsConditions_Correct if { } test_NoExclusionsExemptUsers_Correct if { - ControlNumber := "AAD 2.3" - Requirement := "Sign-ins detected as high risk SHALL be blocked" + PolicyId := "MS.AAD.3.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -99,7 +97,7 @@ test_NoExclusionsExemptUsers_Correct if { } } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -107,8 +105,7 @@ test_NoExclusionsExemptUsers_Correct if { } test_NoExclusionsExemptGroups_Correct if { - ControlNumber := "AAD 2.3" - Requirement := "Sign-ins detected as high risk SHALL be blocked" + PolicyId := "MS.AAD.3.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -155,7 +152,7 @@ test_NoExclusionsExemptGroups_Correct if { } } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -164,8 +161,7 @@ test_NoExclusionsExemptGroups_Correct if { # User exclusions test test_UserExclusionNoExempt_Incorrect if { - ControlNumber := "AAD 2.3" - Requirement := "Sign-ins detected as high risk SHALL be blocked" + PolicyId := "MS.AAD.3.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -200,7 +196,7 @@ test_UserExclusionNoExempt_Incorrect if { } ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -208,8 +204,7 @@ test_UserExclusionNoExempt_Incorrect if { } test_UserExclusionConditions_Correct if { - ControlNumber := "AAD 2.3" - Requirement := "Sign-ins detected as high risk SHALL be blocked" + PolicyId := "MS.AAD.3.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -256,7 +251,7 @@ test_UserExclusionConditions_Correct if { } } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -264,8 +259,7 @@ test_UserExclusionConditions_Correct if { } test_UserExclusionsNoExempt_Incorrect if { - ControlNumber := "AAD 2.3" - Requirement := "Sign-ins detected as high risk SHALL be blocked" + PolicyId := "MS.AAD.3.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -300,7 +294,7 @@ test_UserExclusionsNoExempt_Incorrect if { } ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -308,8 +302,7 @@ test_UserExclusionsNoExempt_Incorrect if { } test_UserExclusionsSingleExempt_Incorrect if { - ControlNumber := "AAD 2.3" - Requirement := "Sign-ins detected as high risk SHALL be blocked" + PolicyId := "MS.AAD.3.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -356,7 +349,7 @@ test_UserExclusionsSingleExempt_Incorrect if { } } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -364,8 +357,7 @@ test_UserExclusionsSingleExempt_Incorrect if { } test_MultiUserExclusionsConditions_Correct if { - ControlNumber := "AAD 2.3" - Requirement := "Sign-ins detected as high risk SHALL be blocked" + PolicyId := "MS.AAD.3.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -412,7 +404,7 @@ test_MultiUserExclusionsConditions_Correct if { } } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -421,8 +413,7 @@ test_MultiUserExclusionsConditions_Correct if { # Group Exclusion tests test_GroupExclusionNoExempt_Incorrect if { - ControlNumber := "AAD 2.3" - Requirement := "Sign-ins detected as high risk SHALL be blocked" + PolicyId := "MS.AAD.3.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -457,7 +448,7 @@ test_GroupExclusionNoExempt_Incorrect if { } ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -465,8 +456,7 @@ test_GroupExclusionNoExempt_Incorrect if { } test_GroupExclusionsConditions_Correct if { - ControlNumber := "AAD 2.3" - Requirement := "Sign-ins detected as high risk SHALL be blocked" + PolicyId := "MS.AAD.3.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -512,7 +502,7 @@ test_GroupExclusionsConditions_Correct if { } } } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -520,8 +510,7 @@ test_GroupExclusionsConditions_Correct if { } test_GroupExclusionsNoExempt_Incorrect if { - ControlNumber := "AAD 2.3" - Requirement := "Sign-ins detected as high risk SHALL be blocked" + PolicyId := "MS.AAD.3.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -556,7 +545,7 @@ test_GroupExclusionsNoExempt_Incorrect if { } ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -564,8 +553,7 @@ test_GroupExclusionsNoExempt_Incorrect if { } test_GroupExclusionsSingleExempt_Incorrect if { - ControlNumber := "AAD 2.3" - Requirement := "Sign-ins detected as high risk SHALL be blocked" + PolicyId := "MS.AAD.3.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -611,7 +599,7 @@ test_GroupExclusionsSingleExempt_Incorrect if { } } } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -619,8 +607,7 @@ test_GroupExclusionsSingleExempt_Incorrect if { } test_MultiGroupExclusionsConditions_Correct if { - ControlNumber := "AAD 2.3" - Requirement := "Sign-ins detected as high risk SHALL be blocked" + PolicyId := "MS.AAD.3.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -666,7 +653,7 @@ test_MultiGroupExclusionsConditions_Correct if { } } } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -675,8 +662,7 @@ test_MultiGroupExclusionsConditions_Correct if { # User and group exclusions tests test_UserGroupExclusionConditions_Correct if { - ControlNumber := "AAD 2.3" - Requirement := "Sign-ins detected as high risk SHALL be blocked" + PolicyId := "MS.AAD.3.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -721,7 +707,7 @@ test_UserGroupExclusionConditions_Correct if { } } } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -729,8 +715,7 @@ test_UserGroupExclusionConditions_Correct if { } test_UserGroupExclusionNoExempt_Incorrect if { - ControlNumber := "AAD 2.3" - Requirement := "Sign-ins detected as high risk SHALL be blocked" + PolicyId := "MS.AAD.3.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -765,7 +750,7 @@ test_UserGroupExclusionNoExempt_Incorrect if { } ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -773,8 +758,7 @@ test_UserGroupExclusionNoExempt_Incorrect if { } test_UserGroupExclusionUserExemptOnly_Incorrect if { - ControlNumber := "AAD 2.3" - Requirement := "Sign-ins detected as high risk SHALL be blocked" + PolicyId := "MS.AAD.3.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -819,7 +803,7 @@ test_UserGroupExclusionUserExemptOnly_Incorrect if { } } } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -827,8 +811,7 @@ test_UserGroupExclusionUserExemptOnly_Incorrect if { } test_UserGroupExclusionGroupExemptOnly_Incorrect if { - ControlNumber := "AAD 2.3" - Requirement := "Sign-ins detected as high risk SHALL be blocked" + PolicyId := "MS.AAD.3.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -873,7 +856,7 @@ test_UserGroupExclusionGroupExemptOnly_Incorrect if { } } } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -881,8 +864,7 @@ test_UserGroupExclusionGroupExemptOnly_Incorrect if { } test_UserGroupExclusionTooFewUserExempts_Incorrect if { - ControlNumber := "AAD 2.3" - Requirement := "Sign-ins detected as high risk SHALL be blocked" + PolicyId := "MS.AAD.3.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -927,7 +909,7 @@ test_UserGroupExclusionTooFewUserExempts_Incorrect if { } } } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -936,8 +918,7 @@ test_UserGroupExclusionTooFewUserExempts_Incorrect if { # Other Conditions test_Conditions_Correct if { - ControlNumber := "AAD 2.3" - Requirement := "Sign-ins detected as high risk SHALL be blocked" + PolicyId := "MS.AAD.3.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -973,7 +954,7 @@ test_Conditions_Correct if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -981,8 +962,7 @@ test_Conditions_Correct if { } test_IncludeApplications_Incorrect if { - ControlNumber := "AAD 2.3" - Requirement := "Sign-ins detected as high risk SHALL be blocked" + PolicyId := "MS.AAD.3.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -1018,7 +998,7 @@ test_IncludeApplications_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -1026,8 +1006,7 @@ test_IncludeApplications_Incorrect if { } test_IncludeUsers_Incorrect if { - ControlNumber := "AAD 2.3" - Requirement := "Sign-ins detected as high risk SHALL be blocked" + PolicyId := "MS.AAD.3.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -1063,7 +1042,7 @@ test_IncludeUsers_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -1071,8 +1050,7 @@ test_IncludeUsers_Incorrect if { } test_ExcludeUsers_Incorrect if { - ControlNumber := "AAD 2.3" - Requirement := "Sign-ins detected as high risk SHALL be blocked" + PolicyId := "MS.AAD.3.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -1108,7 +1086,7 @@ test_ExcludeUsers_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -1116,8 +1094,7 @@ test_ExcludeUsers_Incorrect if { } test_ExcludeGroups_Incorrect if { - ControlNumber := "AAD 2.3" - Requirement := "Sign-ins detected as high risk SHALL be blocked" + PolicyId := "MS.AAD.3.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -1154,7 +1131,7 @@ test_ExcludeGroups_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -1162,8 +1139,7 @@ test_ExcludeGroups_Incorrect if { } test_ExcludeRoles_Incorrect if { - ControlNumber := "AAD 2.3" - Requirement := "Sign-ins detected as high risk SHALL be blocked" + PolicyId := "MS.AAD.3.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -1200,7 +1176,7 @@ test_ExcludeRoles_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -1208,8 +1184,7 @@ test_ExcludeRoles_Incorrect if { } test_SignInRiskLevels_Incorrect if { - ControlNumber := "AAD 2.3" - Requirement := "Sign-ins detected as high risk SHALL be blocked" + PolicyId := "MS.AAD.3.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -1245,7 +1220,7 @@ test_SignInRiskLevels_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -1253,8 +1228,7 @@ test_SignInRiskLevels_Incorrect if { } test_BuiltInControls_Incorrect if { - ControlNumber := "AAD 2.3" - Requirement := "Sign-ins detected as high risk SHALL be blocked" + PolicyId := "MS.AAD.3.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -1290,7 +1264,7 @@ test_BuiltInControls_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -1298,8 +1272,7 @@ test_BuiltInControls_Incorrect if { } test_State_Incorrect if { - ControlNumber := "AAD 2.3" - Requirement := "Sign-ins detected as high risk SHALL be blocked" + PolicyId := "MS.AAD.3.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -1335,7 +1308,7 @@ test_State_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet diff --git a/Testing/Unit/Rego/AAD/AADConfig2_04_test.rego b/Testing/Unit/Rego/AAD/AADConfig_04_test.rego similarity index 82% rename from Testing/Unit/Rego/AAD/AADConfig2_04_test.rego rename to Testing/Unit/Rego/AAD/AADConfig_04_test.rego index 0a7824b44d..d28d58ecca 100644 --- a/Testing/Unit/Rego/AAD/AADConfig2_04_test.rego +++ b/Testing/Unit/Rego/AAD/AADConfig_04_test.rego @@ -1,14 +1,13 @@ package aad import future.keywords - +import data.report.utils.NotCheckedDetails # # Policy 1 #-- test_NoExclusionsConditions_Correct if { - ControlNumber := "AAD 2.4" - Requirement := "MFA SHALL be required for all users" + PolicyId := "MS.AAD.4.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -32,7 +31,7 @@ test_NoExclusionsConditions_Correct if { } ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -40,8 +39,7 @@ test_NoExclusionsConditions_Correct if { } test_NoExclusionsExemptUsers_Correct if { - ControlNumber := "AAD 2.4" - Requirement := "MFA SHALL be required for all users" + PolicyId := "MS.AAD.4.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -77,7 +75,7 @@ test_NoExclusionsExemptUsers_Correct if { } } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -85,8 +83,7 @@ test_NoExclusionsExemptUsers_Correct if { } test_NoExclusionsExemptGroups_Correct if { - ControlNumber := "AAD 2.4" - Requirement := "MFA SHALL be required for all users" + PolicyId := "MS.AAD.4.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -122,7 +119,7 @@ test_NoExclusionsExemptGroups_Correct if { } } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -131,8 +128,7 @@ test_NoExclusionsExemptGroups_Correct if { # User exclusions test test_UserExclusionNoExempt_Incorrect if { - ControlNumber := "AAD 2.4" - Requirement := "MFA SHALL be required for all users" + PolicyId := "MS.AAD.4.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -156,7 +152,7 @@ test_UserExclusionNoExempt_Incorrect if { } ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -164,8 +160,7 @@ test_UserExclusionNoExempt_Incorrect if { } test_UserExclusionConditions_Correct if { - ControlNumber := "AAD 2.4" - Requirement := "MFA SHALL be required for all users" + PolicyId := "MS.AAD.4.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -201,7 +196,7 @@ test_UserExclusionConditions_Correct if { } } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -209,8 +204,7 @@ test_UserExclusionConditions_Correct if { } test_UserExclusionsNoExempt_Incorrect if { - ControlNumber := "AAD 2.4" - Requirement := "MFA SHALL be required for all users" + PolicyId := "MS.AAD.4.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -234,7 +228,7 @@ test_UserExclusionsNoExempt_Incorrect if { } ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -242,8 +236,7 @@ test_UserExclusionsNoExempt_Incorrect if { } test_UserExclusionsSingleExempt_Incorrect if { - ControlNumber := "AAD 2.4" - Requirement := "MFA SHALL be required for all users" + PolicyId := "MS.AAD.4.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -279,7 +272,7 @@ test_UserExclusionsSingleExempt_Incorrect if { } } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -287,8 +280,7 @@ test_UserExclusionsSingleExempt_Incorrect if { } test_MultiUserExclusionsConditions_Correct if { - ControlNumber := "AAD 2.4" - Requirement := "MFA SHALL be required for all users" + PolicyId := "MS.AAD.4.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -324,7 +316,7 @@ test_MultiUserExclusionsConditions_Correct if { } } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -333,8 +325,7 @@ test_MultiUserExclusionsConditions_Correct if { # Group Exclusion tests test_GroupExclusionNoExempt_Incorrect if { - ControlNumber := "AAD 2.4" - Requirement := "MFA SHALL be required for all users" + PolicyId := "MS.AAD.4.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -358,7 +349,7 @@ test_GroupExclusionNoExempt_Incorrect if { } ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -366,8 +357,7 @@ test_GroupExclusionNoExempt_Incorrect if { } test_GroupExclusionsConditions_Correct if { - ControlNumber := "AAD 2.4" - Requirement := "MFA SHALL be required for all users" + PolicyId := "MS.AAD.4.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -402,7 +392,7 @@ test_GroupExclusionsConditions_Correct if { } } } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -410,8 +400,7 @@ test_GroupExclusionsConditions_Correct if { } test_GroupExclusionsNoExempt_Incorrect if { - ControlNumber := "AAD 2.4" - Requirement := "MFA SHALL be required for all users" + PolicyId := "MS.AAD.4.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -435,7 +424,7 @@ test_GroupExclusionsNoExempt_Incorrect if { } ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -443,8 +432,7 @@ test_GroupExclusionsNoExempt_Incorrect if { } test_GroupExclusionsSingleExempt_Incorrect if { - ControlNumber := "AAD 2.4" - Requirement := "MFA SHALL be required for all users" + PolicyId := "MS.AAD.4.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -479,7 +467,7 @@ test_GroupExclusionsSingleExempt_Incorrect if { } } } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -487,8 +475,7 @@ test_GroupExclusionsSingleExempt_Incorrect if { } test_MultiGroupExclusionsConditions_Correct if { - ControlNumber := "AAD 2.4" - Requirement := "MFA SHALL be required for all users" + PolicyId := "MS.AAD.4.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -523,7 +510,7 @@ test_MultiGroupExclusionsConditions_Correct if { } } } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -532,8 +519,7 @@ test_MultiGroupExclusionsConditions_Correct if { # User and group exclusions tests test_UserGroupExclusionConditions_Correct if { - ControlNumber := "AAD 2.4" - Requirement := "MFA SHALL be required for all users" + PolicyId := "MS.AAD.4.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -567,7 +553,7 @@ test_UserGroupExclusionConditions_Correct if { } } } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -575,8 +561,7 @@ test_UserGroupExclusionConditions_Correct if { } test_UserGroupExclusionNoExempt_Incorrect if { - ControlNumber := "AAD 2.4" - Requirement := "MFA SHALL be required for all users" + PolicyId := "MS.AAD.4.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -600,7 +585,7 @@ test_UserGroupExclusionNoExempt_Incorrect if { } ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -608,8 +593,7 @@ test_UserGroupExclusionNoExempt_Incorrect if { } test_UserGroupExclusionUserExemptOnly_Incorrect if { - ControlNumber := "AAD 2.4" - Requirement := "MFA SHALL be required for all users" + PolicyId := "MS.AAD.4.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -643,7 +627,7 @@ test_UserGroupExclusionUserExemptOnly_Incorrect if { } } } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -651,8 +635,7 @@ test_UserGroupExclusionUserExemptOnly_Incorrect if { } test_UserGroupExclusionGroupExemptOnly_Incorrect if { - ControlNumber := "AAD 2.4" - Requirement := "MFA SHALL be required for all users" + PolicyId := "MS.AAD.4.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -686,7 +669,7 @@ test_UserGroupExclusionGroupExemptOnly_Incorrect if { } } } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -694,8 +677,7 @@ test_UserGroupExclusionGroupExemptOnly_Incorrect if { } test_UserGroupExclusionTooFewUserExempts_Incorrect if { - ControlNumber := "AAD 2.4" - Requirement := "MFA SHALL be required for all users" + PolicyId := "MS.AAD.4.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -729,7 +711,7 @@ test_UserGroupExclusionTooFewUserExempts_Incorrect if { } } } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -738,8 +720,7 @@ test_UserGroupExclusionTooFewUserExempts_Incorrect if { # Other conditions test_ConditionalAccessPolicies_Correct if { - ControlNumber := "AAD 2.4" - Requirement := "MFA SHALL be required for all users" + PolicyId := "MS.AAD.4.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -764,7 +745,7 @@ test_ConditionalAccessPolicies_Correct if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput)>= 1 RuleOutput[0].RequirementMet @@ -772,8 +753,7 @@ test_ConditionalAccessPolicies_Correct if { } test_IncludeApplications_Incorrect if { - ControlNumber := "AAD 2.4" - Requirement := "MFA SHALL be required for all users" + PolicyId := "MS.AAD.4.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -798,7 +778,7 @@ test_IncludeApplications_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -806,8 +786,8 @@ test_IncludeApplications_Incorrect if { } test_IncludeUsers_Incorrect if { - ControlNumber := "AAD 2.4" - Requirement := "MFA SHALL be required for all users" + PolicyId := "MS.AAD.4.1v1" + Output := tests with input as { "conditional_access_policies": [ { @@ -831,7 +811,7 @@ test_IncludeUsers_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -839,8 +819,7 @@ test_IncludeUsers_Incorrect if { } test_ExcludeUsers_Incorrect if { - ControlNumber := "AAD 2.4" - Requirement := "MFA SHALL be required for all users" + PolicyId := "MS.AAD.4.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -865,7 +844,7 @@ test_ExcludeUsers_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -873,8 +852,7 @@ test_ExcludeUsers_Incorrect if { } test_ExcludeGroups_Incorrect if { - ControlNumber := "AAD 2.4" - Requirement := "MFA SHALL be required for all users" + PolicyId := "MS.AAD.4.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -899,7 +877,7 @@ test_ExcludeGroups_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -907,8 +885,7 @@ test_ExcludeGroups_Incorrect if { } test_ExcludeRoles_Incorrect if { - ControlNumber := "AAD 2.4" - Requirement := "MFA SHALL be required for all users" + PolicyId := "MS.AAD.4.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -933,7 +910,7 @@ test_ExcludeRoles_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -941,8 +918,7 @@ test_ExcludeRoles_Incorrect if { } test_BuiltInControls_Incorrect if { - ControlNumber := "AAD 2.4" - Requirement := "MFA SHALL be required for all users" + PolicyId := "MS.AAD.4.1v1" Output := tests with input as { @@ -968,7 +944,7 @@ test_BuiltInControls_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -976,8 +952,7 @@ test_BuiltInControls_Incorrect if { } test_State_Incorrect if { - ControlNumber := "AAD 2.4" - Requirement := "MFA SHALL be required for all users" + PolicyId := "MS.AAD.4.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -1002,7 +977,7 @@ test_State_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -1013,46 +988,43 @@ test_State_Incorrect if { # Policy 2 #-- test_NotImplemented_Correct_V1 if { - ControlNumber := "AAD 2.4" - Requirement := "Phishing-resistant MFA SHALL be used for all users" + PolicyId := "MS.AAD.4.2v1" Output := tests with input as { } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Currently cannot be checked automatically. See Azure Active Directory Secure Configuration Baseline policy 2.4 for instructions on manual check" + RuleOutput[0].ReportDetails == NotCheckedDetails(PolicyId) } # # Policy 3 #-- test_NotImplemented_Correct_V2 if { - ControlNumber := "AAD 2.4" - Requirement := "If phishing-resistant MFA cannot be used, an MFA method from the list [see AAD baseline 2.4] SHALL be used in the interim" + PolicyId := "MS.AAD.4.3v1" Output := tests with input as { } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Currently cannot be checked automatically. See Azure Active Directory Secure Configuration Baseline policy 2.4 for instructions on manual check" + RuleOutput[0].ReportDetails == NotCheckedDetails(PolicyId) } # # Policy 4 #-- test_NotImplemented_Correct_V3 if { - ControlNumber := "AAD 2.4" - Requirement := "SMS or Voice as the MFA method SHALL NOT be used" + PolicyId := "MS.AAD.4.4v1" Output := tests with input as { } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Currently cannot be checked automatically. See Azure Active Directory Secure Configuration Baseline policy 2.4 for instructions on manual check" + RuleOutput[0].ReportDetails == NotCheckedDetails(PolicyId) } \ No newline at end of file diff --git a/Testing/Unit/Rego/AAD/AADConfig_05_test.rego b/Testing/Unit/Rego/AAD/AADConfig_05_test.rego new file mode 100644 index 0000000000..a6dc3b0e18 --- /dev/null +++ b/Testing/Unit/Rego/AAD/AADConfig_05_test.rego @@ -0,0 +1,29 @@ +package aad +import future.keywords +import data.report.utils.NotCheckedDetails + +#-- +test_NotImplemented_Correct_V1 if { + PolicyId := "MS.AAD.5.1v1" + + Output := tests with input as { } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == NotCheckedDetails(PolicyId) +} + +#-- +test_NotImplemented_Correct_V2 if { + PolicyId := "MS.AAD.5.4v1" + + Output := tests with input as { } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == NotCheckedDetails(PolicyId) +} \ No newline at end of file diff --git a/Testing/Unit/Rego/AAD/AADConfig2_06_test.rego b/Testing/Unit/Rego/AAD/AADConfig_06_test.rego similarity index 73% rename from Testing/Unit/Rego/AAD/AADConfig2_06_test.rego rename to Testing/Unit/Rego/AAD/AADConfig_06_test.rego index 432dd18435..77b3ed12c7 100644 --- a/Testing/Unit/Rego/AAD/AADConfig2_06_test.rego +++ b/Testing/Unit/Rego/AAD/AADConfig_06_test.rego @@ -6,8 +6,7 @@ import future.keywords # Policy 1 #-- test_AllowedToCreateApps_Correct if { - ControlNumber := "AAD 2.6" - Requirement := "Only administrators SHALL be allowed to register third-party applications" + PolicyId := "MS.AAD.6.1v1" Output := tests with input as { "authorization_policies": [ @@ -22,7 +21,7 @@ test_AllowedToCreateApps_Correct if { # filter for just the output produced by the specific rule by # checking 1) the control number and 2) the requirement string - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] # Each rule should produce exactly 1 line of output in the report count(RuleOutput) == 1 @@ -31,8 +30,7 @@ test_AllowedToCreateApps_Correct if { } test_AllowedToCreateApps_Incorrect_V1 if { - ControlNumber := "AAD 2.6" - Requirement := "Only administrators SHALL be allowed to register third-party applications" + PolicyId := "MS.AAD.6.1v1" Output := tests with input as { "authorization_policies": [ @@ -45,7 +43,7 @@ test_AllowedToCreateApps_Incorrect_V1 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -53,8 +51,7 @@ test_AllowedToCreateApps_Incorrect_V1 if { } test_AllowedToCreateApps_Incorrect_V2 if { - ControlNumber := "AAD 2.6" - Requirement := "Only administrators SHALL be allowed to register third-party applications" + PolicyId := "MS.AAD.6.1v1" Output := tests with input as { "authorization_policies": [ @@ -73,7 +70,7 @@ test_AllowedToCreateApps_Incorrect_V2 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet diff --git a/Testing/Unit/Rego/AAD/AADConfig2_07_test.rego b/Testing/Unit/Rego/AAD/AADConfig_07_test.rego similarity index 68% rename from Testing/Unit/Rego/AAD/AADConfig2_07_test.rego rename to Testing/Unit/Rego/AAD/AADConfig_07_test.rego index d6801ce356..2084cff188 100644 --- a/Testing/Unit/Rego/AAD/AADConfig2_07_test.rego +++ b/Testing/Unit/Rego/AAD/AADConfig_07_test.rego @@ -6,8 +6,7 @@ import future.keywords # Policy 1 #-- test_PermissionGrantPolicyIdsAssignedToDefaultUserRole_Correct if { - ControlNumber := "AAD 2.7" - Requirement := "Only administrators SHALL be allowed to consent to third-party applications" + PolicyId := "MS.AAD.7.1v1" Output := tests with input as { "authorization_policies": [ @@ -18,7 +17,7 @@ test_PermissionGrantPolicyIdsAssignedToDefaultUserRole_Correct if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -26,8 +25,7 @@ test_PermissionGrantPolicyIdsAssignedToDefaultUserRole_Correct if { } test_PermissionGrantPolicyIdsAssignedToDefaultUserRole_Incorrect_V1 if { - ControlNumber := "AAD 2.7" - Requirement := "Only administrators SHALL be allowed to consent to third-party applications" + PolicyId := "MS.AAD.7.1v1" Output := tests with input as { "authorization_policies": [ @@ -38,7 +36,7 @@ test_PermissionGrantPolicyIdsAssignedToDefaultUserRole_Incorrect_V1 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] print(RuleOutput) count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -46,8 +44,7 @@ test_PermissionGrantPolicyIdsAssignedToDefaultUserRole_Incorrect_V1 if { } test_PermissionGrantPolicyIdsAssignedToDefaultUserRole_Incorrect_V2 if { - ControlNumber := "AAD 2.7" - Requirement := "Only administrators SHALL be allowed to consent to third-party applications" + PolicyId := "MS.AAD.7.1v1" Output := tests with input as { "authorization_policies": [ @@ -62,7 +59,7 @@ test_PermissionGrantPolicyIdsAssignedToDefaultUserRole_Incorrect_V2 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] print(RuleOutput) count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -74,8 +71,7 @@ test_PermissionGrantPolicyIdsAssignedToDefaultUserRole_Incorrect_V2 if { # Policy 2 #-- test_IsEnabled_Correct if { - ControlNumber := "AAD 2.7" - Requirement := "An admin consent workflow SHALL be configured" + PolicyId := "MS.AAD.7.2v1" Output := tests with input as { "admin_consent_policies": [ @@ -86,7 +82,7 @@ test_IsEnabled_Correct if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -94,8 +90,7 @@ test_IsEnabled_Correct if { } test_IsEnabled_Incorrect if { - ControlNumber := "AAD 2.7" - Requirement := "An admin consent workflow SHALL be configured" + PolicyId := "MS.AAD.7.2v1" Output := tests with input as { "admin_consent_policies": [ @@ -106,7 +101,7 @@ test_IsEnabled_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -117,8 +112,7 @@ test_IsEnabled_Incorrect if { # Policy 3 #-- test_Value_Correct if { - ControlNumber := "AAD 2.7" - Requirement := "Group owners SHALL NOT be allowed to consent to third-party applications" + PolicyId := "MS.AAD.7.3v1" Output := tests with input as { "directory_settings": [ @@ -134,7 +128,7 @@ test_Value_Correct if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -142,8 +136,7 @@ test_Value_Correct if { } test_Value_Incorrect if { - ControlNumber := "AAD 2.7" - Requirement := "Group owners SHALL NOT be allowed to consent to third-party applications" + PolicyId := "MS.AAD.7.3v1" Output := tests with input as { "directory_settings": [ @@ -159,7 +152,7 @@ test_Value_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet diff --git a/Testing/Unit/Rego/AAD/AADConfig_08_test.rego b/Testing/Unit/Rego/AAD/AADConfig_08_test.rego new file mode 100644 index 0000000000..4bb3296bc8 --- /dev/null +++ b/Testing/Unit/Rego/AAD/AADConfig_08_test.rego @@ -0,0 +1,18 @@ +package aad +import future.keywords +import data.report.utils.NotCheckedDetails + +# +# Policy 1 +#-- +test_NotImplemented_Correct if { + PolicyId := "MS.AAD.8.1v1" + + Output := tests with input as { } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == NotCheckedDetails(PolicyId) +} \ No newline at end of file diff --git a/Testing/Unit/Rego/AAD/AADConfig2_09_test.rego b/Testing/Unit/Rego/AAD/AADConfig_09_test.rego similarity index 84% rename from Testing/Unit/Rego/AAD/AADConfig2_09_test.rego rename to Testing/Unit/Rego/AAD/AADConfig_09_test.rego index 8a3c172d93..f543240071 100644 --- a/Testing/Unit/Rego/AAD/AADConfig2_09_test.rego +++ b/Testing/Unit/Rego/AAD/AADConfig_09_test.rego @@ -7,8 +7,7 @@ import future.keywords # User exclusions test test_UserExclusionNoExempt_Incorrect if { - ControlNumber := "AAD 2.9" - Requirement := "Sign-in frequency SHALL be configured to 12 hours" + PolicyId := "MS.AAD.9.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -36,7 +35,7 @@ test_UserExclusionNoExempt_Incorrect if { } ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -44,8 +43,7 @@ test_UserExclusionNoExempt_Incorrect if { } test_UserExclusionConditions_Correct if { - ControlNumber := "AAD 2.9" - Requirement := "Sign-in frequency SHALL be configured to 12 hours" + PolicyId := "MS.AAD.9.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -85,7 +83,7 @@ test_UserExclusionConditions_Correct if { } } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -93,8 +91,7 @@ test_UserExclusionConditions_Correct if { } test_UserExclusionsNoExempt_Incorrect if { - ControlNumber := "AAD 2.9" - Requirement := "Sign-in frequency SHALL be configured to 12 hours" + PolicyId := "MS.AAD.9.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -122,7 +119,7 @@ test_UserExclusionsNoExempt_Incorrect if { } ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -130,8 +127,7 @@ test_UserExclusionsNoExempt_Incorrect if { } test_UserExclusionsSingleExempt_Incorrect if { - ControlNumber := "AAD 2.9" - Requirement := "Sign-in frequency SHALL be configured to 12 hours" + PolicyId := "MS.AAD.9.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -171,7 +167,7 @@ test_UserExclusionsSingleExempt_Incorrect if { } } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -179,8 +175,7 @@ test_UserExclusionsSingleExempt_Incorrect if { } test_MultiUserExclusionsConditions_Correct if { - ControlNumber := "AAD 2.9" - Requirement := "Sign-in frequency SHALL be configured to 12 hours" + PolicyId := "MS.AAD.9.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -220,7 +215,7 @@ test_MultiUserExclusionsConditions_Correct if { } } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -229,8 +224,7 @@ test_MultiUserExclusionsConditions_Correct if { # Group Exclusion tests test_GroupExclusionNoExempt_Incorrect if { - ControlNumber := "AAD 2.9" - Requirement := "Sign-in frequency SHALL be configured to 12 hours" + PolicyId := "MS.AAD.9.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -258,7 +252,7 @@ test_GroupExclusionNoExempt_Incorrect if { } ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -266,8 +260,7 @@ test_GroupExclusionNoExempt_Incorrect if { } test_GroupExclusionsConditions_Correct if { - ControlNumber := "AAD 2.9" - Requirement := "Sign-in frequency SHALL be configured to 12 hours" + PolicyId := "MS.AAD.9.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -306,7 +299,7 @@ test_GroupExclusionsConditions_Correct if { } } } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -314,8 +307,7 @@ test_GroupExclusionsConditions_Correct if { } test_GroupExclusionsNoExempt_Incorrect if { - ControlNumber := "AAD 2.9" - Requirement := "Sign-in frequency SHALL be configured to 12 hours" + PolicyId := "MS.AAD.9.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -343,7 +335,7 @@ test_GroupExclusionsNoExempt_Incorrect if { } ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -351,8 +343,7 @@ test_GroupExclusionsNoExempt_Incorrect if { } test_GroupExclusionsSingleExempt_Incorrect if { - ControlNumber := "AAD 2.9" - Requirement := "Sign-in frequency SHALL be configured to 12 hours" + PolicyId := "MS.AAD.9.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -391,7 +382,7 @@ test_GroupExclusionsSingleExempt_Incorrect if { } } } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -399,8 +390,7 @@ test_GroupExclusionsSingleExempt_Incorrect if { } test_MultiGroupExclusionsConditions_Correct if { - ControlNumber := "AAD 2.9" - Requirement := "Sign-in frequency SHALL be configured to 12 hours" + PolicyId := "MS.AAD.9.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -439,7 +429,7 @@ test_MultiGroupExclusionsConditions_Correct if { } } } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -448,8 +438,7 @@ test_MultiGroupExclusionsConditions_Correct if { # User and group exclusions tests test_UserGroupExclusionConditions_Correct if { - ControlNumber := "AAD 2.9" - Requirement := "Sign-in frequency SHALL be configured to 12 hours" + PolicyId := "MS.AAD.9.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -487,7 +476,7 @@ test_UserGroupExclusionConditions_Correct if { } } } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -495,8 +484,7 @@ test_UserGroupExclusionConditions_Correct if { } test_UserGroupExclusionNoExempt_Incorrect if { - ControlNumber := "AAD 2.9" - Requirement := "Sign-in frequency SHALL be configured to 12 hours" + PolicyId := "MS.AAD.9.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -524,7 +512,7 @@ test_UserGroupExclusionNoExempt_Incorrect if { } ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -532,8 +520,7 @@ test_UserGroupExclusionNoExempt_Incorrect if { } test_UserGroupExclusionUserExemptOnly_Incorrect if { - ControlNumber := "AAD 2.9" - Requirement := "Sign-in frequency SHALL be configured to 12 hours" + PolicyId := "MS.AAD.9.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -571,7 +558,7 @@ test_UserGroupExclusionUserExemptOnly_Incorrect if { } } } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -579,8 +566,7 @@ test_UserGroupExclusionUserExemptOnly_Incorrect if { } test_UserGroupExclusionGroupExemptOnly_Incorrect if { - ControlNumber := "AAD 2.9" - Requirement := "Sign-in frequency SHALL be configured to 12 hours" + PolicyId := "MS.AAD.9.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -618,7 +604,7 @@ test_UserGroupExclusionGroupExemptOnly_Incorrect if { } } } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -626,8 +612,7 @@ test_UserGroupExclusionGroupExemptOnly_Incorrect if { } test_UserGroupExclusionTooFewUserExempts_Incorrect if { - ControlNumber := "AAD 2.9" - Requirement := "Sign-in frequency SHALL be configured to 12 hours" + PolicyId := "MS.AAD.9.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -665,7 +650,7 @@ test_UserGroupExclusionTooFewUserExempts_Incorrect if { } } } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -674,8 +659,7 @@ test_UserGroupExclusionTooFewUserExempts_Incorrect if { # Other conditions test_ConditionalAccessPolicies_Correct if { - ControlNumber := "AAD 2.9" - Requirement := "Sign-in frequency SHALL be configured to 12 hours" + PolicyId := "MS.AAD.9.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -704,7 +688,7 @@ test_ConditionalAccessPolicies_Correct if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -712,8 +696,7 @@ test_ConditionalAccessPolicies_Correct if { } test_IncludeApplications_Incorrect if { - ControlNumber := "AAD 2.9" - Requirement := "Sign-in frequency SHALL be configured to 12 hours" + PolicyId := "MS.AAD.9.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -742,7 +725,7 @@ test_IncludeApplications_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -750,8 +733,7 @@ test_IncludeApplications_Incorrect if { } test_IncludeUsers_Incorrect if { - ControlNumber := "AAD 2.9" - Requirement := "Sign-in frequency SHALL be configured to 12 hours" + PolicyId := "MS.AAD.9.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -780,7 +762,7 @@ test_IncludeUsers_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -788,8 +770,7 @@ test_IncludeUsers_Incorrect if { } test_ExcludeUsers_Incorrect if { - ControlNumber := "AAD 2.9" - Requirement := "Sign-in frequency SHALL be configured to 12 hours" + PolicyId := "MS.AAD.9.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -818,7 +799,7 @@ test_ExcludeUsers_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -826,8 +807,7 @@ test_ExcludeUsers_Incorrect if { } test_ExcludeGroups_Incorrect if { - ControlNumber := "AAD 2.9" - Requirement := "Sign-in frequency SHALL be configured to 12 hours" + PolicyId := "MS.AAD.9.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -856,7 +836,7 @@ test_ExcludeGroups_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -864,8 +844,7 @@ test_ExcludeGroups_Incorrect if { } test_ExcludeRoles_Incorrect if { - ControlNumber := "AAD 2.9" - Requirement := "Sign-in frequency SHALL be configured to 12 hours" + PolicyId := "MS.AAD.9.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -894,7 +873,7 @@ test_ExcludeRoles_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -902,8 +881,7 @@ test_ExcludeRoles_Incorrect if { } test_IsEnabled_Incorrect if { - ControlNumber := "AAD 2.9" - Requirement := "Sign-in frequency SHALL be configured to 12 hours" + PolicyId := "MS.AAD.9.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -932,7 +910,7 @@ test_IsEnabled_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -940,8 +918,7 @@ test_IsEnabled_Incorrect if { } test_Type_Incorrect if { - ControlNumber := "AAD 2.9" - Requirement := "Sign-in frequency SHALL be configured to 12 hours" + PolicyId := "MS.AAD.9.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -970,7 +947,7 @@ test_Type_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -978,8 +955,7 @@ test_Type_Incorrect if { } test_Value_Incorrect if { - ControlNumber := "AAD 2.9" - Requirement := "Sign-in frequency SHALL be configured to 12 hours" + PolicyId := "MS.AAD.9.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -1008,7 +984,7 @@ test_Value_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -1016,8 +992,7 @@ test_Value_Incorrect if { } test_State_Incorrect if { - ControlNumber := "AAD 2.9" - Requirement := "Sign-in frequency SHALL be configured to 12 hours" + PolicyId := "MS.AAD.9.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -1046,7 +1021,7 @@ test_State_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet diff --git a/Testing/Unit/Rego/AAD/AADConfig2_10_test.rego b/Testing/Unit/Rego/AAD/AADConfig_10_test.rego similarity index 85% rename from Testing/Unit/Rego/AAD/AADConfig2_10_test.rego rename to Testing/Unit/Rego/AAD/AADConfig_10_test.rego index e7bf1e4216..55ef33f402 100644 --- a/Testing/Unit/Rego/AAD/AADConfig2_10_test.rego +++ b/Testing/Unit/Rego/AAD/AADConfig_10_test.rego @@ -7,8 +7,7 @@ import future.keywords #-- # User exclusions test test_UserExclusionNoExempt_Incorrect if { - ControlNumber := "AAD 2.10" - Requirement := "Browser sessions SHALL not be persistent" + PolicyId := "MS.AAD.10.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -35,7 +34,7 @@ test_UserExclusionNoExempt_Incorrect if { } ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -43,8 +42,7 @@ test_UserExclusionNoExempt_Incorrect if { } test_UserExclusionConditions_Correct if { - ControlNumber := "AAD 2.10" - Requirement := "Browser sessions SHALL not be persistent" + PolicyId := "MS.AAD.10.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -83,7 +81,7 @@ test_UserExclusionConditions_Correct if { } } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -91,8 +89,7 @@ test_UserExclusionConditions_Correct if { } test_UserExclusionsNoExempt_Incorrect if { - ControlNumber := "AAD 2.10" - Requirement := "Browser sessions SHALL not be persistent" + PolicyId := "MS.AAD.10.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -119,7 +116,7 @@ test_UserExclusionsNoExempt_Incorrect if { } ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -127,8 +124,7 @@ test_UserExclusionsNoExempt_Incorrect if { } test_UserExclusionsSingleExempt_Incorrect if { - ControlNumber := "AAD 2.10" - Requirement := "Browser sessions SHALL not be persistent" + PolicyId := "MS.AAD.10.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -167,7 +163,7 @@ test_UserExclusionsSingleExempt_Incorrect if { } } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -175,8 +171,7 @@ test_UserExclusionsSingleExempt_Incorrect if { } test_MultiUserExclusionsConditions_Correct if { - ControlNumber := "AAD 2.10" - Requirement := "Browser sessions SHALL not be persistent" + PolicyId := "MS.AAD.10.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -215,7 +210,7 @@ test_MultiUserExclusionsConditions_Correct if { } } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -224,8 +219,7 @@ test_MultiUserExclusionsConditions_Correct if { # Group Exclusion tests test_GroupExclusionNoExempt_Incorrect if { - ControlNumber := "AAD 2.10" - Requirement := "Browser sessions SHALL not be persistent" + PolicyId := "MS.AAD.10.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -252,7 +246,7 @@ test_GroupExclusionNoExempt_Incorrect if { } ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -260,8 +254,7 @@ test_GroupExclusionNoExempt_Incorrect if { } test_GroupExclusionsConditions_Correct if { - ControlNumber := "AAD 2.10" - Requirement := "Browser sessions SHALL not be persistent" + PolicyId := "MS.AAD.10.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -299,7 +292,7 @@ test_GroupExclusionsConditions_Correct if { } } } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -307,8 +300,7 @@ test_GroupExclusionsConditions_Correct if { } test_GroupExclusionsNoExempt_Incorrect if { - ControlNumber := "AAD 2.10" - Requirement := "Browser sessions SHALL not be persistent" + PolicyId := "MS.AAD.10.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -335,7 +327,7 @@ test_GroupExclusionsNoExempt_Incorrect if { } ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -343,8 +335,7 @@ test_GroupExclusionsNoExempt_Incorrect if { } test_GroupExclusionsSingleExempt_Incorrect if { - ControlNumber := "AAD 2.10" - Requirement := "Browser sessions SHALL not be persistent" + PolicyId := "MS.AAD.10.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -382,7 +373,7 @@ test_GroupExclusionsSingleExempt_Incorrect if { } } } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -390,8 +381,7 @@ test_GroupExclusionsSingleExempt_Incorrect if { } test_MultiGroupExclusionsConditions_Correct if { - ControlNumber := "AAD 2.10" - Requirement := "Browser sessions SHALL not be persistent" + PolicyId := "MS.AAD.10.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -429,7 +419,7 @@ test_MultiGroupExclusionsConditions_Correct if { } } } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -438,8 +428,7 @@ test_MultiGroupExclusionsConditions_Correct if { # User and group exclusions tests test_UserGroupExclusionConditions_Correct if { - ControlNumber := "AAD 2.10" - Requirement := "Browser sessions SHALL not be persistent" + PolicyId := "MS.AAD.10.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -476,7 +465,7 @@ test_UserGroupExclusionConditions_Correct if { } } } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -484,8 +473,7 @@ test_UserGroupExclusionConditions_Correct if { } test_UserGroupExclusionNoExempt_Incorrect if { - ControlNumber := "AAD 2.10" - Requirement := "Browser sessions SHALL not be persistent" + PolicyId := "MS.AAD.10.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -512,7 +500,7 @@ test_UserGroupExclusionNoExempt_Incorrect if { } ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -520,8 +508,7 @@ test_UserGroupExclusionNoExempt_Incorrect if { } test_UserGroupExclusionUserExemptOnly_Incorrect if { - ControlNumber := "AAD 2.10" - Requirement := "Browser sessions SHALL not be persistent" + PolicyId := "MS.AAD.10.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -558,7 +545,7 @@ test_UserGroupExclusionUserExemptOnly_Incorrect if { } } } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -566,8 +553,7 @@ test_UserGroupExclusionUserExemptOnly_Incorrect if { } test_UserGroupExclusionGroupExemptOnly_Incorrect if { - ControlNumber := "AAD 2.10" - Requirement := "Browser sessions SHALL not be persistent" + PolicyId := "MS.AAD.10.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -604,7 +590,7 @@ test_UserGroupExclusionGroupExemptOnly_Incorrect if { } } } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -612,8 +598,7 @@ test_UserGroupExclusionGroupExemptOnly_Incorrect if { } test_UserGroupExclusionTooFewUserExempts_Incorrect if { - ControlNumber := "AAD 2.10" - Requirement := "Browser sessions SHALL not be persistent" + PolicyId := "MS.AAD.10.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -650,7 +635,7 @@ test_UserGroupExclusionTooFewUserExempts_Incorrect if { } } } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -659,8 +644,7 @@ test_UserGroupExclusionTooFewUserExempts_Incorrect if { # Other conditions test_ConditionalAccessPolicies_Correct if { - ControlNumber := "AAD 2.10" - Requirement := "Browser sessions SHALL not be persistent" + PolicyId := "MS.AAD.10.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -688,7 +672,7 @@ test_ConditionalAccessPolicies_Correct if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -696,8 +680,7 @@ test_ConditionalAccessPolicies_Correct if { } test_IncludeApplications_Incorrect if { - ControlNumber := "AAD 2.10" - Requirement := "Browser sessions SHALL not be persistent" + PolicyId := "MS.AAD.10.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -725,7 +708,7 @@ test_IncludeApplications_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -733,8 +716,7 @@ test_IncludeApplications_Incorrect if { } test_IncludeUsers_Incorrect if { - ControlNumber := "AAD 2.10" - Requirement := "Browser sessions SHALL not be persistent" + PolicyId := "MS.AAD.10.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -762,7 +744,7 @@ test_IncludeUsers_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -770,8 +752,7 @@ test_IncludeUsers_Incorrect if { } test_ExcludeUsers_Incorrect if { - ControlNumber := "AAD 2.10" - Requirement := "Browser sessions SHALL not be persistent" + PolicyId := "MS.AAD.10.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -799,7 +780,7 @@ test_ExcludeUsers_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -807,8 +788,7 @@ test_ExcludeUsers_Incorrect if { } test_ExcludeGroups_Incorrect if { - ControlNumber := "AAD 2.10" - Requirement := "Browser sessions SHALL not be persistent" + PolicyId := "MS.AAD.10.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -836,7 +816,7 @@ test_ExcludeGroups_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -844,8 +824,7 @@ test_ExcludeGroups_Incorrect if { } test_ExcludeRoles_Incorrect if { - ControlNumber := "AAD 2.10" - Requirement := "Browser sessions SHALL not be persistent" + PolicyId := "MS.AAD.10.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -873,7 +852,7 @@ test_ExcludeRoles_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -881,8 +860,7 @@ test_ExcludeRoles_Incorrect if { } test_IsEnabled_Incorrect if { - ControlNumber := "AAD 2.10" - Requirement := "Browser sessions SHALL not be persistent" + PolicyId := "MS.AAD.10.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -910,7 +888,7 @@ test_IsEnabled_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -918,8 +896,7 @@ test_IsEnabled_Incorrect if { } test_Mode_Incorrect if { - ControlNumber := "AAD 2.10" - Requirement := "Browser sessions SHALL not be persistent" + PolicyId := "MS.AAD.10.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -947,7 +924,7 @@ test_Mode_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -955,8 +932,7 @@ test_Mode_Incorrect if { } test_State_Incorrect if { - ControlNumber := "AAD 2.10" - Requirement := "Browser sessions SHALL not be persistent" + PolicyId := "MS.AAD.10.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -984,7 +960,7 @@ test_State_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet diff --git a/Testing/Unit/Rego/AAD/AADConfig2_11_test.rego b/Testing/Unit/Rego/AAD/AADConfig_11_test.rego similarity index 71% rename from Testing/Unit/Rego/AAD/AADConfig2_11_test.rego rename to Testing/Unit/Rego/AAD/AADConfig_11_test.rego index 829d5cd5e1..c2cee717c1 100644 --- a/Testing/Unit/Rego/AAD/AADConfig2_11_test.rego +++ b/Testing/Unit/Rego/AAD/AADConfig_11_test.rego @@ -6,8 +6,7 @@ import future.keywords # Policy 1 #-- test_PrivilegedUsers_Correct if { - ControlNumber := "AAD 2.11" - Requirement := "A minimum of two users and a maximum of four users SHALL be provisioned with the Global Administrator role" + PolicyId := "MS.AAD.11.1v1" Output := tests with input as { "privileged_users" : { @@ -22,7 +21,7 @@ test_PrivilegedUsers_Correct if { } } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -30,8 +29,7 @@ test_PrivilegedUsers_Correct if { } test_PrivilegedUsers_Incorrect_V1 if { - ControlNumber := "AAD 2.11" - Requirement := "A minimum of two users and a maximum of four users SHALL be provisioned with the Global Administrator role" + PolicyId := "MS.AAD.11.1v1" Output := tests with input as { "privileged_users" : { @@ -42,7 +40,7 @@ test_PrivilegedUsers_Incorrect_V1 if { } } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -50,8 +48,7 @@ test_PrivilegedUsers_Incorrect_V1 if { } test_PrivilegedUsers_Incorrect_V2 if { - ControlNumber := "AAD 2.11" - Requirement := "A minimum of two users and a maximum of four users SHALL be provisioned with the Global Administrator role" + PolicyId := "MS.AAD.11.1v1" Output := tests with input as { "privileged_users" : { @@ -78,7 +75,7 @@ test_PrivilegedUsers_Incorrect_V2 if { } } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet diff --git a/Testing/Unit/Rego/AAD/AADConfig2_12_test.rego b/Testing/Unit/Rego/AAD/AADConfig_12_test.rego similarity index 63% rename from Testing/Unit/Rego/AAD/AADConfig2_12_test.rego rename to Testing/Unit/Rego/AAD/AADConfig_12_test.rego index 9a774d1136..0360a2a054 100644 --- a/Testing/Unit/Rego/AAD/AADConfig2_12_test.rego +++ b/Testing/Unit/Rego/AAD/AADConfig_12_test.rego @@ -6,9 +6,8 @@ import future.keywords # Policy 1 #-- test_OnPremisesImmutableId_Correct if { - ControlNumber := "AAD 2.12" - Requirement := "Users that need to be assigned to highly privileged Azure AD roles SHALL be provisioned cloud-only accounts that are separate from the on-premises directory or other federated identity providers" - + PolicyId := "MS.AAD.12.1v1" + Output := tests with input as { "privileged_users": { "User1": { @@ -23,7 +22,7 @@ test_OnPremisesImmutableId_Correct if { } } } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -31,8 +30,7 @@ test_OnPremisesImmutableId_Correct if { } test_OnPremisesImmutableId_Incorrect_V1 if { - ControlNumber := "AAD 2.12" - Requirement := "Users that need to be assigned to highly privileged Azure AD roles SHALL be provisioned cloud-only accounts that are separate from the on-premises directory or other federated identity providers" + PolicyId := "MS.AAD.12.1v1" Output := tests with input as { "privileged_users": { @@ -44,7 +42,7 @@ test_OnPremisesImmutableId_Incorrect_V1 if { } } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -52,9 +50,8 @@ test_OnPremisesImmutableId_Incorrect_V1 if { } test_OnPremisesImmutableId_Incorrect_V2 if { - ControlNumber := "AAD 2.12" - Requirement := "Users that need to be assigned to highly privileged Azure AD roles SHALL be provisioned cloud-only accounts that are separate from the on-premises directory or other federated identity providers" - + PolicyId := "MS.AAD.12.1v1" + Output := tests with input as { "privileged_users": { "User1": { @@ -70,7 +67,7 @@ test_OnPremisesImmutableId_Incorrect_V2 if { } } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet diff --git a/Testing/Unit/Rego/AAD/AADConfig2_13_test.rego b/Testing/Unit/Rego/AAD/AADConfig_13_test.rego similarity index 83% rename from Testing/Unit/Rego/AAD/AADConfig2_13_test.rego rename to Testing/Unit/Rego/AAD/AADConfig_13_test.rego index 4ccd7a8118..0871803157 100644 --- a/Testing/Unit/Rego/AAD/AADConfig2_13_test.rego +++ b/Testing/Unit/Rego/AAD/AADConfig_13_test.rego @@ -6,8 +6,7 @@ import future.keywords # Policy 1 #-- test_ConditionalAccessPolicies_Correct if { - ControlNumber := "AAD 2.13" - Requirement := "MFA SHALL be required for user access to highly privileged roles" + PolicyId := "MS.AAD.13.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -40,7 +39,7 @@ test_ConditionalAccessPolicies_Correct if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -48,8 +47,7 @@ test_ConditionalAccessPolicies_Correct if { } test_IncludeApplications_Incorrect if { - ControlNumber := "AAD 2.13" - Requirement := "MFA SHALL be required for user access to highly privileged roles" + PolicyId := "MS.AAD.13.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -82,7 +80,7 @@ test_IncludeApplications_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -90,8 +88,7 @@ test_IncludeApplications_Incorrect if { } test_BuiltInControls_Incorrect if { - ControlNumber := "AAD 2.13" - Requirement := "MFA SHALL be required for user access to highly privileged roles" + PolicyId := "MS.AAD.13.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -124,7 +121,7 @@ test_BuiltInControls_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -132,8 +129,7 @@ test_BuiltInControls_Incorrect if { } test_State_Incorrect if { - ControlNumber := "AAD 2.13" - Requirement := "MFA SHALL be required for user access to highly privileged roles" + PolicyId := "MS.AAD.13.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -166,7 +162,7 @@ test_State_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -174,8 +170,7 @@ test_State_Incorrect if { } test_IncludeRoles_Incorrect_V1 if { - ControlNumber := "AAD 2.13" - Requirement := "MFA SHALL be required for user access to highly privileged roles" + PolicyId := "MS.AAD.13.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -208,7 +203,7 @@ test_IncludeRoles_Incorrect_V1 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -216,8 +211,7 @@ test_IncludeRoles_Incorrect_V1 if { } test_IncludeRoles_Incorrect_V2 if { - ControlNumber := "AAD 2.13" - Requirement := "MFA SHALL be required for user access to highly privileged roles" + PolicyId := "MS.AAD.13.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -246,7 +240,7 @@ test_IncludeRoles_Incorrect_V2 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -254,8 +248,7 @@ test_IncludeRoles_Incorrect_V2 if { } test_ExcludeRoles_Incorrect if { - ControlNumber := "AAD 2.13" - Requirement := "MFA SHALL be required for user access to highly privileged roles" + PolicyId := "MS.AAD.13.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -284,7 +277,7 @@ test_ExcludeRoles_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet diff --git a/Testing/Unit/Rego/AAD/AADConfig2_14_test.rego b/Testing/Unit/Rego/AAD/AADConfig_14_test.rego similarity index 77% rename from Testing/Unit/Rego/AAD/AADConfig2_14_test.rego rename to Testing/Unit/Rego/AAD/AADConfig_14_test.rego index 5e8df833a3..10b67485aa 100644 --- a/Testing/Unit/Rego/AAD/AADConfig2_14_test.rego +++ b/Testing/Unit/Rego/AAD/AADConfig_14_test.rego @@ -6,9 +6,8 @@ import future.keywords # Policy 1 #-- test_AdditionalProperties_Correct if { - ControlNumber := "AAD 2.14" - Requirement := "Permanent active role assignments SHALL NOT be allowed for highly privileged roles. Active assignments SHALL have an expiration period." - + PolicyId := "MS.AAD.14.1v1" + Output := tests with input as { "privileged_roles": [ { @@ -34,7 +33,7 @@ test_AdditionalProperties_Correct if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -42,8 +41,7 @@ test_AdditionalProperties_Correct if { } test_AdditionalProperties_Incorrect_V1 if { - ControlNumber := "AAD 2.14" - Requirement := "Permanent active role assignments SHALL NOT be allowed for highly privileged roles. Active assignments SHALL have an expiration period." + PolicyId := "MS.AAD.14.1v1" Output := tests with input as { "privileged_roles": [ @@ -70,7 +68,7 @@ test_AdditionalProperties_Incorrect_V1 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -78,8 +76,7 @@ test_AdditionalProperties_Incorrect_V1 if { } test_AdditionalProperties_Incorrect_V2 if { - ControlNumber := "AAD 2.14" - Requirement := "Permanent active role assignments SHALL NOT be allowed for highly privileged roles. Active assignments SHALL have an expiration period." + PolicyId := "MS.AAD.14.1v1" Output := tests with input as { "privileged_roles": [ @@ -106,7 +103,7 @@ test_AdditionalProperties_Incorrect_V2 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -117,8 +114,7 @@ test_AdditionalProperties_Incorrect_V2 if { # Policy 2 #-- test_Assignments_Correct if { - ControlNumber := "AAD 2.14" - Requirement := "Provisioning of users to highly privileged roles SHALL NOT occur outside of a PAM system, such as the Azure AD PIM service, because this bypasses the controls the PAM system provides" + PolicyId := "MS.AAD.14.2v1" Output := tests with input as { "privileged_roles": [ @@ -150,7 +146,7 @@ test_Assignments_Correct if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -158,8 +154,7 @@ test_Assignments_Correct if { } test_Assignments_Incorrect if { - ControlNumber := "AAD 2.14" - Requirement := "Provisioning of users to highly privileged roles SHALL NOT occur outside of a PAM system, such as the Azure AD PIM service, because this bypasses the controls the PAM system provides" + PolicyId := "MS.AAD.14.2v1" Output := tests with input as { "privileged_roles": [ @@ -191,7 +186,7 @@ test_Assignments_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet diff --git a/Testing/Unit/Rego/AAD/AADConfig2_15_test.rego b/Testing/Unit/Rego/AAD/AADConfig_15_test.rego similarity index 82% rename from Testing/Unit/Rego/AAD/AADConfig2_15_test.rego rename to Testing/Unit/Rego/AAD/AADConfig_15_test.rego index ad64ed79ea..14cc57dc87 100644 --- a/Testing/Unit/Rego/AAD/AADConfig2_15_test.rego +++ b/Testing/Unit/Rego/AAD/AADConfig_15_test.rego @@ -6,8 +6,7 @@ import future.keywords # Policy 1 #-- test_AdditionalProperties_Correct if { - ControlNumber := "AAD 2.15" - Requirement := "Activation of highly privileged roles SHOULD require approval" + PolicyId := "MS.AAD.15.1v1" Output := tests with input as { "privileged_roles": [ @@ -35,7 +34,7 @@ test_AdditionalProperties_Correct if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -43,8 +42,7 @@ test_AdditionalProperties_Correct if { } test_AdditionalProperties_Incorrect if { - ControlNumber := "AAD 2.15" - Requirement := "Activation of highly privileged roles SHOULD require approval" + PolicyId := "MS.AAD.15.1v1" Output := tests with input as { "privileged_roles": [ @@ -72,7 +70,7 @@ test_AdditionalProperties_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet diff --git a/Testing/Unit/Rego/AAD/AADConfig2_16_test.rego b/Testing/Unit/Rego/AAD/AADConfig_16_test.rego similarity index 83% rename from Testing/Unit/Rego/AAD/AADConfig2_16_test.rego rename to Testing/Unit/Rego/AAD/AADConfig_16_test.rego index 9f39cb47a5..f40652fc13 100644 --- a/Testing/Unit/Rego/AAD/AADConfig2_16_test.rego +++ b/Testing/Unit/Rego/AAD/AADConfig_16_test.rego @@ -6,8 +6,7 @@ import future.keywords # Policy 1 #-- test_notificationRecipients_Correct if { - ControlNumber := "AAD 2.16" - Requirement := "Eligible and Active highly privileged role assignments SHALL trigger an alert" + PolicyId := "MS.AAD.16.1v1" Output := tests with input as { "privileged_roles": [ @@ -40,7 +39,7 @@ test_notificationRecipients_Correct if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -48,8 +47,7 @@ test_notificationRecipients_Correct if { } test_notificationRecipients_Incorrect_V1 if { - ControlNumber := "AAD 2.16" - Requirement := "Eligible and Active highly privileged role assignments SHALL trigger an alert" + PolicyId := "MS.AAD.16.1v1" Output := tests with input as { "privileged_roles": [ @@ -82,7 +80,7 @@ test_notificationRecipients_Incorrect_V1 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -90,8 +88,7 @@ test_notificationRecipients_Incorrect_V1 if { } test_notificationRecipients_Incorrect_V2 if { - ControlNumber := "AAD 2.16" - Requirement := "Eligible and Active highly privileged role assignments SHALL trigger an alert" + PolicyId := "MS.AAD.16.1v1" Output := tests with input as { "privileged_roles": [ @@ -124,7 +121,7 @@ test_notificationRecipients_Incorrect_V2 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -132,8 +129,7 @@ test_notificationRecipients_Incorrect_V2 if { } test_notificationRecipients_Incorrect_V3 if { - ControlNumber := "AAD 2.16" - Requirement := "Eligible and Active highly privileged role assignments SHALL trigger an alert" + PolicyId := "MS.AAD.16.1v1" Output := tests with input as { "privileged_roles": [ @@ -166,7 +162,7 @@ test_notificationRecipients_Incorrect_V3 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -174,8 +170,7 @@ test_notificationRecipients_Incorrect_V3 if { } test_Id_Correct_V1 if { - ControlNumber := "AAD 2.16" - Requirement := "User activation of the Global Administrator role SHALL trigger an alert" + PolicyId := "MS.AAD.16.2v1" Output := tests with input as { "privileged_roles": [ @@ -203,7 +198,7 @@ test_Id_Correct_V1 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -211,8 +206,7 @@ test_Id_Correct_V1 if { } test_Id_Correct_V2 if { - ControlNumber := "AAD 2.16" - Requirement := "User activation of the Global Administrator role SHALL trigger an alert" + PolicyId := "MS.AAD.16.2v1" Output := tests with input as { "privileged_roles": [ @@ -240,7 +234,7 @@ test_Id_Correct_V2 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -248,8 +242,7 @@ test_Id_Correct_V2 if { } test_Id_Incorrect if { - ControlNumber := "AAD 2.16" - Requirement := "User activation of the Global Administrator role SHALL trigger an alert" + PolicyId := "MS.AAD.16.2v1" Output := tests with input as { "privileged_roles": [ @@ -277,7 +270,7 @@ test_Id_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -285,8 +278,7 @@ test_Id_Incorrect if { } test_DisplayName_Correct if { - ControlNumber := "AAD 2.16" - Requirement := "User activation of other highly privileged roles SHOULD trigger an alert" + PolicyId := "MS.AAD.16.3v1" Output := tests with input as { "privileged_roles": [ @@ -314,7 +306,7 @@ test_DisplayName_Correct if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -322,8 +314,7 @@ test_DisplayName_Correct if { } test_DisplayName_Incorrect if { - ControlNumber := "AAD 2.16" - Requirement := "User activation of other highly privileged roles SHOULD trigger an alert" + PolicyId := "MS.AAD.16.3v1" Output := tests with input as { "privileged_roles": [ @@ -351,7 +342,7 @@ test_DisplayName_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet diff --git a/Testing/Unit/Rego/AAD/AADConfig2_17_test.rego b/Testing/Unit/Rego/AAD/AADConfig_17_test.rego similarity index 79% rename from Testing/Unit/Rego/AAD/AADConfig2_17_test.rego rename to Testing/Unit/Rego/AAD/AADConfig_17_test.rego index 957d786761..84c87e31dd 100644 --- a/Testing/Unit/Rego/AAD/AADConfig2_17_test.rego +++ b/Testing/Unit/Rego/AAD/AADConfig_17_test.rego @@ -6,8 +6,7 @@ import future.keywords # Policy 1 #-- test_ConditionalAccessPolicies_Correct if { - ControlNumber := "AAD 2.17" - Requirement := "Managed devices SHOULD be required for authentication" + PolicyId := "MS.AAD.17.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -29,7 +28,7 @@ test_ConditionalAccessPolicies_Correct if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -37,8 +36,7 @@ test_ConditionalAccessPolicies_Correct if { } test_BuiltInControls_Correct if { - ControlNumber := "AAD 2.17" - Requirement := "Managed devices SHOULD be required for authentication" + PolicyId := "MS.AAD.17.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -60,7 +58,7 @@ test_BuiltInControls_Correct if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -68,8 +66,7 @@ test_BuiltInControls_Correct if { } test_IncludeApplications_Incorrect if { - ControlNumber := "AAD 2.17" - Requirement := "Managed devices SHOULD be required for authentication" + PolicyId := "MS.AAD.17.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -91,7 +88,7 @@ test_IncludeApplications_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -99,8 +96,7 @@ test_IncludeApplications_Incorrect if { } test_IncludeUsers_Incorrect if { - ControlNumber := "AAD 2.17" - Requirement := "Managed devices SHOULD be required for authentication" + PolicyId := "MS.AAD.17.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -122,7 +118,7 @@ test_IncludeUsers_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -130,8 +126,7 @@ test_IncludeUsers_Incorrect if { } test_BuiltInControls_Incorrect if { - ControlNumber := "AAD 2.17" - Requirement := "Managed devices SHOULD be required for authentication" + PolicyId := "MS.AAD.17.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -153,7 +148,7 @@ test_BuiltInControls_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -161,8 +156,7 @@ test_BuiltInControls_Incorrect if { } test_State_Incorrect if { - ControlNumber := "AAD 2.17" - Requirement := "Managed devices SHOULD be required for authentication" + PolicyId := "MS.AAD.17.1v1" Output := tests with input as { "conditional_access_policies": [ @@ -184,7 +178,7 @@ test_State_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet diff --git a/Testing/Unit/Rego/AAD/AADConfig2_18_test.rego b/Testing/Unit/Rego/AAD/AADConfig_18_test.rego similarity index 56% rename from Testing/Unit/Rego/AAD/AADConfig2_18_test.rego rename to Testing/Unit/Rego/AAD/AADConfig_18_test.rego index 061059c8d2..0455c806cf 100644 --- a/Testing/Unit/Rego/AAD/AADConfig2_18_test.rego +++ b/Testing/Unit/Rego/AAD/AADConfig_18_test.rego @@ -1,13 +1,12 @@ package aad import future.keywords - +import data.report.utils.NotCheckedDetails # # Policy 1 #-- test_AllowInvitesFrom_Correct if { - ControlNumber := "AAD 2.18" - Requirement := "Only users with the Guest Inviter role SHOULD be able to invite guest users" + PolicyId := "MS.AAD.18.1v1" Output := tests with input as { "authorization_policies": [ @@ -18,7 +17,7 @@ test_AllowInvitesFrom_Correct if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -26,8 +25,7 @@ test_AllowInvitesFrom_Correct if { } test_AllowInvitesFrom_Incorrect if { - ControlNumber := "AAD 2.18" - Requirement := "Only users with the Guest Inviter role SHOULD be able to invite guest users" + PolicyId := "MS.AAD.18.1v1" Output := tests with input as { "authorization_policies": [ @@ -38,7 +36,7 @@ test_AllowInvitesFrom_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -49,24 +47,21 @@ test_AllowInvitesFrom_Incorrect if { # Policy 2 #-- test_NotImplemented_Correct if { - ControlNumber := "AAD 2.18" - Requirement := "Guest invites SHOULD only be allowed to specific external domains that have been authorized by the agency for legitimate business purposes" - + PolicyId := "MS.AAD.18.2v1" Output := tests with input as { } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Currently cannot be checked automatically. See Azure Active Directory Secure Configuration Baseline policy 2.18 for instructions on manual check" + RuleOutput[0].ReportDetails == NotCheckedDetails(PolicyId) } # # Policy 3 #-- test_GuestUserRoleId_Correct_V1 if { - ControlNumber := "AAD 2.18" - Requirement := "Guest users SHOULD have limited access to Azure AD directory objects" + PolicyId := "MS.AAD.18.3v1" Output := tests with input as { "authorization_policies": [ @@ -77,7 +72,7 @@ test_GuestUserRoleId_Correct_V1 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -85,8 +80,7 @@ test_GuestUserRoleId_Correct_V1 if { } test_GuestUserRoleId_Correct_V2 if { - ControlNumber := "AAD 2.18" - Requirement := "Guest users SHOULD have limited access to Azure AD directory objects" + PolicyId := "MS.AAD.18.3v1" Output := tests with input as { "authorization_policies": [ @@ -97,7 +91,7 @@ test_GuestUserRoleId_Correct_V2 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -105,8 +99,7 @@ test_GuestUserRoleId_Correct_V2 if { } test_GuestUserRoleId_Incorrect_V1 if { - ControlNumber := "AAD 2.18" - Requirement := "Guest users SHOULD have limited access to Azure AD directory objects" + PolicyId := "MS.AAD.18.3v1" Output := tests with input as { "authorization_policies": [ @@ -117,7 +110,7 @@ test_GuestUserRoleId_Incorrect_V1 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -125,8 +118,7 @@ test_GuestUserRoleId_Incorrect_V1 if { } test_GuestUserRoleId_Incorrect_V2 if { - ControlNumber := "AAD 2.18" - Requirement := "Guest users SHOULD have limited access to Azure AD directory objects" + PolicyId := "MS.AAD.18.3v1" Output := tests with input as { "authorization_policies": [ @@ -137,7 +129,7 @@ test_GuestUserRoleId_Incorrect_V2 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -145,8 +137,7 @@ test_GuestUserRoleId_Incorrect_V2 if { } test_GuestUserRoleId_Incorrect_V3 if { - ControlNumber := "AAD 2.18" - Requirement := "Guest users SHOULD have limited access to Azure AD directory objects" + PolicyId := "MS.AAD.18.3v1" Output := tests with input as { "authorization_policies": [ @@ -161,14 +152,8 @@ test_GuestUserRoleId_Incorrect_V3 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet - - # Can't make any assumptions about the order of the output in the string, - # hence the contains functions instead of a simple == - startswith(RuleOutput[0].ReportDetails, "Permission level set to ") - contains(RuleOutput[0].ReportDetails, "\"Unknown\" (policy 1)") - contains(RuleOutput[0].ReportDetails, "\"Restricted access\" (policy 2)") } \ No newline at end of file diff --git a/Testing/Unit/Rego/Defender/DefenderConfig2_01_test.rego b/Testing/Unit/Rego/Defender/DefenderConfig2_01_test.rego deleted file mode 100644 index c3e9dbcacf..0000000000 --- a/Testing/Unit/Rego/Defender/DefenderConfig2_01_test.rego +++ /dev/null @@ -1,119 +0,0 @@ -package defender -import future.keywords - - -# -# Policy 1 -#-- -test_Identity_Correct_V1 if { - ControlNumber := "Defender 2.1" - Requirement := "Standard Preset security profiles SHOULD NOT be used" - - Output := tests with input as { - "protection_policy_rules" : [] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_Identity_Correct_V2 if { - ControlNumber := "Defender 2.1" - Requirement := "Standard Preset security profiles SHOULD NOT be used" - - Output := tests with input as { - "protection_policy_rules" : [ - { - "Identity" : "Standard Preset Security Policy", - "State" : "Disabled" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_Identity_Incorrect_V1 if { - ControlNumber := "Defender 2.1" - Requirement := "Standard Preset security profiles SHOULD NOT be used" - - Output := tests with input as { - "protection_policy_rules" : [ - { - "Identity" : "Standard Preset Security Policy", - "State" : "Enabled" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "The Standard Preset Security Policy is present and not disabled" -} - -# -# Policy 2 -#-- -test_Identity_Correct_V1 if { - ControlNumber := "Defender 2.1" - Requirement := "Strict Preset security profiles SHOULD NOT be used" - - Output := tests with input as { - "protection_policy_rules" : [] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_Identity_Correct_V2 if { - ControlNumber := "Defender 2.1" - Requirement := "Strict Preset security profiles SHOULD NOT be used" - - Output := tests with input as { - "protection_policy_rules" : [ - { - "Identity" : "Strict Preset Security Policy", - "State" : "Disabled" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_Identity_Incorrect_V2 if { - ControlNumber := "Defender 2.1" - Requirement := "Strict Preset security profiles SHOULD NOT be used" - - Output := tests with input as { - "protection_policy_rules" : [ - { - "Identity" : "Strict Preset Security Policy", - "State" : "Enabled" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "The Strict Preset Security Policy is present and not disabled" -} \ No newline at end of file diff --git a/Testing/Unit/Rego/Defender/DefenderConfig2_02_test.rego b/Testing/Unit/Rego/Defender/DefenderConfig2_02_test.rego deleted file mode 100644 index f24e91dfab..0000000000 --- a/Testing/Unit/Rego/Defender/DefenderConfig2_02_test.rego +++ /dev/null @@ -1,1028 +0,0 @@ -package defender -import future.keywords - - -# -# Policy 1 -#-- -test_ContentContainsSensitiveInformation_Correct_V1 if { - ControlNumber := "Defender 2.2" - Requirement := "A custom policy SHALL be configured to protect PII and sensitive information, as defined by the agency: U.S. Social Security Number (SSN)" - - Output := tests with input as { - "dlp_compliance_rules": [ - { - "ContentContainsSensitiveInformation": [ - {"name": "U.S. Social Security Number (SSN)"} - ], - "Name": "Baseline Rule", - "Disabled" : false, - "ParentPolicyName": "Default Office 365 DLP policy", - "BlockAccess": true, - "BlockAccessScope": "All", - "NotifyUser": [ - "SiteAdmin", - "LastModifier", - "Owner" - ], - "NotifyUserType": "NotSet" - } - ], - "dlp_compliance_policies": [ - { - "Name": "Default Office 365 DLP policy", - "Mode": "Enable", - "Enabled": true - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_ContentContainsSensitiveInformation_Incorrect_V1 if { - ControlNumber := "Defender 2.2" - Requirement := "A custom policy SHALL be configured to protect PII and sensitive information, as defined by the agency: U.S. Social Security Number (SSN)" - - Output := tests with input as { - "dlp_compliance_rules": [ - { - "ContentContainsSensitiveInformation": [ - {"name": "U.S. Individual Taxpayer Identification Number (ITIN)"}, - {"name": "Credit Card Number"} - ], - "Name": "Baseline Rule", - "Disabled" : false, - "ParentPolicyName": "Default Office 365 DLP policy", - "BlockAccess": true, - "BlockAccessScope": "All", - "NotifyUser": [ - "SiteAdmin", - "LastModifier", - "Owner" - ], - "NotifyUserType": "NotSet" - } - ], - "dlp_compliance_policies": [ - { - "Name": "Default Office 365 DLP policy", - "Mode": "Enable", - "Enabled": true - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "No matching rule found for U.S. Social Security Number (SSN)" -} - -test_ContentContainsSensitiveInformation_Correct_V2 if { - ControlNumber := "Defender 2.2" - Requirement := "A custom policy SHALL be configured to protect PII and sensitive information, as defined by the agency: U.S. Individual Taxpayer Identification Number (ITIN)" - - Output := tests with input as { - "dlp_compliance_rules": [ - { - "ContentContainsSensitiveInformation": [ - {"name": "U.S. Individual Taxpayer Identification Number (ITIN)"} - ], - "Name": "Baseline Rule", - "Disabled" : false, - "ParentPolicyName": "Default Office 365 DLP policy", - "BlockAccess": true, - "BlockAccessScope": "All", - "NotifyUser": [ - "SiteAdmin", - "LastModifier", - "Owner" - ], - "NotifyUserType": "NotSet" - } - ], - "dlp_compliance_policies": [ - { - "Name": "Default Office 365 DLP policy", - "Mode": "Enable", - "Enabled": true - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_ContentContainsSensitiveInformation_Incorrect_V2 if { - ControlNumber := "Defender 2.2" - Requirement := "A custom policy SHALL be configured to protect PII and sensitive information, as defined by the agency: U.S. Individual Taxpayer Identification Number (ITIN)" - - Output := tests with input as { - "dlp_compliance_rules": [ - { - "ContentContainsSensitiveInformation": [ - {"name": "Credit Card Number"}, - {"name": "U.S. Social Security Number (SSN)"} - ], - "Name": "Baseline Rule", - "Disabled" : false, - "ParentPolicyName": "Default Office 365 DLP policy", - "BlockAccess": true, - "BlockAccessScope": "All", - "NotifyUser": [ - "SiteAdmin", - "LastModifier", - "Owner" - ], - "NotifyUserType": "NotSet" - } - ], - "dlp_compliance_policies": [ - { - "Name": "Default Office 365 DLP policy", - "Mode": "Enable", - "Enabled": true - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "No matching rule found for U.S. Individual Taxpayer Identification Number (ITIN)" -} - -test_ContentContainsSensitiveInformation_Correct_V3 if { - ControlNumber := "Defender 2.2" - Requirement := "A custom policy SHALL be configured to protect PII and sensitive information, as defined by the agency: Credit Card Number" - - Output := tests with input as { - "dlp_compliance_rules": [ - { - "ContentContainsSensitiveInformation": [ - {"name": "Credit Card Number"} - ], - "Name": "Baseline Rule", - "Disabled" : false, - "ParentPolicyName": "Default Office 365 DLP policy", - "BlockAccess": true, - "BlockAccessScope": "All", - "NotifyUser": [ - "SiteAdmin", - "LastModifier", - "Owner" - ], - "NotifyUserType": "NotSet" - } - ], - "dlp_compliance_policies": [ - { - "Name": "Default Office 365 DLP policy", - "Mode": "Enable", - "Enabled": true - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_ContentContainsSensitiveInformation_Incorrect_V3 if { - ControlNumber := "Defender 2.2" - Requirement := "A custom policy SHALL be configured to protect PII and sensitive information, as defined by the agency: Credit Card Number" - - Output := tests with input as { - "dlp_compliance_rules": [ - { - "ContentContainsSensitiveInformation": [ - {"name": "U.S. Individual Taxpayer Identification Number (ITIN)"}, - {"name": "U.S. Social Security Number (SSN)"} - ], - "Name": "Baseline Rule", - "Disabled" : false, - "ParentPolicyName": "Default Office 365 DLP policy", - "BlockAccess": true, - "BlockAccessScope": "All", - "NotifyUser": [ - "SiteAdmin", - "LastModifier", - "Owner" - ], - "NotifyUserType": "NotSet" - } - ], - "dlp_compliance_policies": [ - { - "Name": "Default Office 365 DLP policy", - "Mode": "Enable", - "Enabled": true - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "No matching rule found for Credit Card Number" -} - -# -# Policy 2 -#-- -test_Exchange_Correct if { - ControlNumber := "Defender 2.2" - Requirement := "The custom policy SHOULD be applied in Exchange" - - Output := tests with input as { - "dlp_compliance_rules": [ - { - "ContentContainsSensitiveInformation": [ - {"name": "U.S. Individual Taxpayer Identification Number (ITIN)"}, - {"name": "Credit Card Number"}, - {"name": "U.S. Social Security Number (SSN)"} - ], - "Name": "Baseline Rule", - "Disabled" : false, - "ParentPolicyName": "Default Office 365 DLP policy", - "BlockAccess": true, - "BlockAccessScope": "All", - "NotifyUser": [ - "SiteAdmin", - "LastModifier", - "Owner" - ], - "NotifyUserType": "NotSet" - } - ], - "dlp_compliance_policies": [ - { - "ExchangeLocation": ["All"], - "Workload": "Exchange", - "Name": "Default Office 365 DLP policy", - "Mode": "Enable", - "Enabled": true - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_ExchangeLocation_Incorrect if { - ControlNumber := "Defender 2.2" - Requirement := "The custom policy SHOULD be applied in Exchange" - - Output := tests with input as { - "dlp_compliance_rules": [ - { - "ContentContainsSensitiveInformation": [ - {"name": "U.S. Individual Taxpayer Identification Number (ITIN)"}, - {"name": "Credit Card Number"}, - {"name": "U.S. Social Security Number (SSN)"} - ], - "Name": "Baseline Rule", - "Disabled" : false, - "ParentPolicyName": "Default Office 365 DLP policy", - "BlockAccess": true, - "BlockAccessScope": "All", - "NotifyUser": [ - "SiteAdmin", - "LastModifier", - "Owner" - ], - "NotifyUserType": "NotSet" - } - ], - "dlp_compliance_policies": [ - { - "ExchangeLocation": [""], - "Workload": "Exchange", - "Name": "Default Office 365 DLP policy", - "Mode": "Enable", - "Enabled": true - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "No policy found that applies to Exchange." -} - -test_Workload_Incorrect_V1 if { - ControlNumber := "Defender 2.2" - Requirement := "The custom policy SHOULD be applied in Exchange" - - Output := tests with input as { - "dlp_compliance_rules": [ - { - "ContentContainsSensitiveInformation": [ - {"name": "U.S. Individual Taxpayer Identification Number (ITIN)"}, - {"name": "Credit Card Number"}, - {"name": "U.S. Social Security Number (SSN)"} - ], - "Name": "Baseline Rule", - "Disabled" : false, - "ParentPolicyName": "Default Office 365 DLP policy", - "BlockAccess": true, - "BlockAccessScope": "All", - "NotifyUser": [ - "SiteAdmin", - "LastModifier", - "Owner" - ], - "NotifyUserType": "NotSet" - } - ], - "dlp_compliance_policies": [ - { - "ExchangeLocation": ["All"], - "Workload": "", - "Name": "Default Office 365 DLP policy", - "Mode": "Enable", - "Enabled": true - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "No policy found that applies to Exchange." -} - -test_SharePoint_Correct if { - ControlNumber := "Defender 2.2" - Requirement := "The custom policy SHOULD be applied in SharePoint" - - Output := tests with input as { - "dlp_compliance_rules": [ - { - "ContentContainsSensitiveInformation": [ - {"name": "U.S. Individual Taxpayer Identification Number (ITIN)"}, - {"name": "Credit Card Number"}, - {"name": "U.S. Social Security Number (SSN)"} - ], - "Name": "Baseline Rule", - "Disabled" : false, - "ParentPolicyName": "Default Office 365 DLP policy", - "BlockAccess": true, - "BlockAccessScope": "All", - "NotifyUser": [ - "SiteAdmin", - "LastModifier", - "Owner" - ], - "NotifyUserType": "NotSet" - } - ], - "dlp_compliance_policies": [ - { - "SharePointLocation": ["All"], - "Workload": "SharePoint", - "Name": "Default Office 365 DLP policy", - "Mode": "Enable", - "Enabled": true - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_SharePointLocation_Incorrect if { - ControlNumber := "Defender 2.2" - Requirement := "The custom policy SHOULD be applied in SharePoint" - - Output := tests with input as { - "dlp_compliance_rules": [ - { - "ContentContainsSensitiveInformation": [ - {"name": "U.S. Individual Taxpayer Identification Number (ITIN)"}, - {"name": "Credit Card Number"}, - {"name": "U.S. Social Security Number (SSN)"} - ], - "Name": "Baseline Rule", - "Disabled" : false, - "ParentPolicyName": "Default Office 365 DLP policy", - "BlockAccess": true, - "BlockAccessScope": "All", - "NotifyUser": [ - "SiteAdmin", - "LastModifier", - "Owner" - ], - "NotifyUserType": "NotSet" - } - ], - "dlp_compliance_policies": [ - { - "SharePointLocation": [""], - "Workload": "SharePoint", - "Name": "Default Office 365 DLP policy", - "Mode": "Enable", - "Enabled": true - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "No policy found that applies to SharePoint." -} - -test_Workload_Incorrect_V2 if { - ControlNumber := "Defender 2.2" - Requirement := "The custom policy SHOULD be applied in SharePoint" - - Output := tests with input as { - "dlp_compliance_rules": [ - { - "ContentContainsSensitiveInformation": [ - {"name": "U.S. Individual Taxpayer Identification Number (ITIN)"}, - {"name": "Credit Card Number"}, - {"name": "U.S. Social Security Number (SSN)"} - ], - "Name": "Baseline Rule", - "Disabled" : false, - "ParentPolicyName": "Default Office 365 DLP policy", - "BlockAccess": true, - "BlockAccessScope": "All", - "NotifyUser": [ - "SiteAdmin", - "LastModifier", - "Owner" - ], - "NotifyUserType": "NotSet" - } - ], - "dlp_compliance_policies": [ - { - "SharePointLocation": ["All"], - "Workload": "", - "Name": "Default Office 365 DLP policy", - "Mode": "Enable", - "Enabled": true - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "No policy found that applies to SharePoint." -} - -test_OneDrive_Correct if { - ControlNumber := "Defender 2.2" - Requirement := "The custom policy SHOULD be applied in OneDrive" - - Output := tests with input as { - "dlp_compliance_rules": [ - { - "ContentContainsSensitiveInformation": [ - {"name": "U.S. Individual Taxpayer Identification Number (ITIN)"}, - {"name": "Credit Card Number"}, - {"name": "U.S. Social Security Number (SSN)"} - ], - "Name": "Baseline Rule", - "Disabled" : false, - "ParentPolicyName": "Default Office 365 DLP policy", - "BlockAccess": true, - "BlockAccessScope": "All", - "NotifyUser": [ - "SiteAdmin", - "LastModifier", - "Owner" - ], - "NotifyUserType": "NotSet" - } - ], - "dlp_compliance_policies": [ - { - "OneDriveLocation": ["All"], - "Workload": "OneDrivePoint", - "Name": "Default Office 365 DLP policy", - "Mode": "Enable", - "Enabled": true - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_OneDriveLocation_Incorrect if { - ControlNumber := "Defender 2.2" - Requirement := "The custom policy SHOULD be applied in OneDrive" - - Output := tests with input as { - "dlp_compliance_rules": [ - { - "ContentContainsSensitiveInformation": [ - {"name": "U.S. Individual Taxpayer Identification Number (ITIN)"}, - {"name": "Credit Card Number"}, - {"name": "U.S. Social Security Number (SSN)"} - ], - "Name": "Baseline Rule", - "Disabled" : false, - "ParentPolicyName": "Default Office 365 DLP policy", - "BlockAccess": true, - "BlockAccessScope": "All", - "NotifyUser": [ - "SiteAdmin", - "LastModifier", - "Owner" - ], - "NotifyUserType": "NotSet" - } - ], - "dlp_compliance_policies": [ - { - "OneDriveLocation": [""], - "Workload": "OneDrivePoint", - "Name": "Default Office 365 DLP policy", - "Mode": "Enable", - "Enabled": true - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "No policy found that applies to OneDrive." -} - -test_Workload_Incorrect_V3 if { - ControlNumber := "Defender 2.2" - Requirement := "The custom policy SHOULD be applied in OneDrive" - - Output := tests with input as { - "dlp_compliance_rules": [ - { - "ContentContainsSensitiveInformation": [ - {"name": "U.S. Individual Taxpayer Identification Number (ITIN)"}, - {"name": "Credit Card Number"}, - {"name": "U.S. Social Security Number (SSN)"} - ], - "Name": "Baseline Rule", - "Disabled" : false, - "ParentPolicyName": "Default Office 365 DLP policy", - "BlockAccess": true, - "BlockAccessScope": "All", - "NotifyUser": [ - "SiteAdmin", - "LastModifier", - "Owner" - ], - "NotifyUserType": "NotSet" - } - ], - "dlp_compliance_policies": [ - { - "OneDriveLocation": ["All"], - "Workload": "", - "Name": "Default Office 365 DLP policy", - "Mode": "Enable", - "Enabled": true - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "No policy found that applies to OneDrive." -} - -test_Teams_Correct if { - ControlNumber := "Defender 2.2" - Requirement := "The custom policy SHOULD be applied in Teams" - - Output := tests with input as { - "dlp_compliance_rules": [ - { - "ContentContainsSensitiveInformation": [ - {"name": "U.S. Individual Taxpayer Identification Number (ITIN)"}, - {"name": "Credit Card Number"}, - {"name": "U.S. Social Security Number (SSN)"} - ], - "Name": "Baseline Rule", - "Disabled" : false, - "ParentPolicyName": "Default Office 365 DLP policy", - "BlockAccess": true, - "BlockAccessScope": "All", - "NotifyUser": [ - "SiteAdmin", - "LastModifier", - "Owner" - ], - "NotifyUserType": "NotSet" - } - ], - "dlp_compliance_policies": [ - { - "TeamsLocation": ["All"], - "Workload": "Teams", - "Name": "Default Office 365 DLP policy", - "Mode": "Enable", - "Enabled": true - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_TeamsLocation_Incorrect if { - ControlNumber := "Defender 2.2" - Requirement := "The custom policy SHOULD be applied in Teams" - - Output := tests with input as { - "dlp_compliance_rules": [ - { - "ContentContainsSensitiveInformation": [ - {"name": "U.S. Individual Taxpayer Identification Number (ITIN)"}, - {"name": "Credit Card Number"}, - {"name": "U.S. Social Security Number (SSN)"} - ], - "Name": "Baseline Rule", - "Disabled" : false, - "ParentPolicyName": "Default Office 365 DLP policy", - "BlockAccess": true, - "BlockAccessScope": "All", - "NotifyUser": [ - "SiteAdmin", - "LastModifier", - "Owner" - ], - "NotifyUserType": "NotSet" - } - ], - "dlp_compliance_policies": [ - { - "TeamsLocation": [""], - "Workload": "Teams", - "Name": "Default Office 365 DLP policy", - "Mode": "Enable", - "Enabled": true - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "No policy found that applies to Teams." -} - -test_Workload_Incorrect_V4 if { - ControlNumber := "Defender 2.2" - Requirement := "The custom policy SHOULD be applied in Teams" - - Output := tests with input as { - "dlp_compliance_rules": [ - { - "ContentContainsSensitiveInformation": [ - {"name": "U.S. Individual Taxpayer Identification Number (ITIN)"}, - {"name": "Credit Card Number"}, - {"name": "U.S. Social Security Number (SSN)"} - ], - "Name": "Baseline Rule", - "Disabled" : false, - "ParentPolicyName": "Default Office 365 DLP policy", - "BlockAccess": true, - "BlockAccessScope": "All", - "NotifyUser": [ - "SiteAdmin", - "LastModifier", - "Owner" - ], - "NotifyUserType": "NotSet" - } - ], - "dlp_compliance_policies": [ - { - "TeamsLocation": ["All"], - "Workload": "", - "Name": "Default Office 365 DLP policy", - "Mode": "Enable", - "Enabled": true - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "No policy found that applies to Teams." -} - -# -# Policy 3 -#-- -test_BlockAccess_Correct if { - ControlNumber := "Defender 2.2" - Requirement := "The action for the DLP policy SHOULD be set to block sharing sensitive information with everyone when DLP conditions are met" - - Output := tests with input as { - "dlp_compliance_rules": [ - { - "ContentContainsSensitiveInformation": [ - {"name": "U.S. Individual Taxpayer Identification Number (ITIN)"} - ], - "Name": "Baseline Rule", - "Disabled" : false, - "ParentPolicyName": "Default Office 365 DLP policy", - "BlockAccess": true, - "BlockAccessScope": "All", - "NotifyUser": [ - "SiteAdmin", - "LastModifier", - "Owner" - ], - "NotifyUserType": "NotSet" - } - ], - "dlp_compliance_policies": [ - { - "Name": "Default Office 365 DLP policy", - "Mode": "Enable", - "Enabled": true - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_BlockAccess_IncorrectV1 if { - ControlNumber := "Defender 2.2" - Requirement := "The action for the DLP policy SHOULD be set to block sharing sensitive information with everyone when DLP conditions are met" - - Output := tests with input as { - "dlp_compliance_rules": [ - { - "ContentContainsSensitiveInformation": [ - {"name": "U.S. Individual Taxpayer Identification Number (ITIN)"} - ], - "Name": "Baseline Rule", - "Disabled" : false, - "ParentPolicyName": "Default Office 365 DLP policy", - "BlockAccess": false, - "BlockAccessScope": "All", - "NotifyUser": [ - "SiteAdmin", - "LastModifier", - "Owner" - ], - "NotifyUserType": "NotSet" - } - ], - "dlp_compliance_policies": [ - { - "Name": "Default Office 365 DLP policy", - "Mode": "Enable", - "Enabled": true - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "1 rule(s) found that do(es) not block access or associated policy not set to enforce block action: Baseline Rule" -} - -test_BlockAccess_IncorrectV2 if { - ControlNumber := "Defender 2.2" - Requirement := "The action for the DLP policy SHOULD be set to block sharing sensitive information with everyone when DLP conditions are met" - - Output := tests with input as { - "dlp_compliance_rules": [ - { - "ContentContainsSensitiveInformation": [ - {"name": "U.S. Individual Taxpayer Identification Number (ITIN)"} - ], - "Name": "Baseline Rule", - "Disabled" : false, - "ParentPolicyName": "Default Office 365 DLP policy", - "BlockAccess": true, - "BlockAccessScope": "All", - "NotifyUser": [ - "SiteAdmin", - "LastModifier", - "Owner" - ], - "NotifyUserType": "NotSet" - } - ], - "dlp_compliance_policies": [ - { - "Name": "Default Office 365 DLP policy", - "Mode": "TestWithNotifications", - "Enabled": true - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "1 rule(s) found that do(es) not block access or associated policy not set to enforce block action: Baseline Rule" -} - -# -# Policy 4 -#-- -test_NotifyUser_Correct_V1 if { - ControlNumber := "Defender 2.2" - Requirement := "Notifications to inform users and help educate them on the proper use of sensitive information SHOULD be enabled" - - Output := tests with input as { - "dlp_compliance_rules": [ - { - "ContentContainsSensitiveInformation": [ - {"name": "U.S. Individual Taxpayer Identification Number (ITIN)"} - ], - "Name": "Baseline Rule", - "Disabled" : false, - "ParentPolicyName": "Default Office 365 DLP policy", - "BlockAccess": true, - "BlockAccessScope": "All", - "NotifyUser": [ - "SiteAdmin" - ], - "NotifyUserType": "NotSet" - } - ], - "dlp_compliance_policies": [ - { - "Name": "Default Office 365 DLP policy", - "Mode": "Enable", - "Enabled": true - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_NotifyUser_Correct_V2 if { - ControlNumber := "Defender 2.2" - Requirement := "Notifications to inform users and help educate them on the proper use of sensitive information SHOULD be enabled" - - Output := tests with input as { - "dlp_compliance_rules": [ - { - "ContentContainsSensitiveInformation": [ - {"name": "U.S. Individual Taxpayer Identification Number (ITIN)"} - ], - "Name": "Baseline Rule", - "Disabled" : false, - "ParentPolicyName": "Default Office 365 DLP policy", - "BlockAccess": true, - "BlockAccessScope": "All", - "NotifyUser": [ - "SiteAdmin", - "LastModifier", - "Owner" - ], - "NotifyUserType": "NotSet" - } - ], - "dlp_compliance_policies": [ - { - "Name": "Default Office 365 DLP policy", - "Mode": "Enable", - "Enabled": true - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_NotifyUser_Incorrect if { - ControlNumber := "Defender 2.2" - Requirement := "Notifications to inform users and help educate them on the proper use of sensitive information SHOULD be enabled" - - Output := tests with input as { - "dlp_compliance_rules": [ - { - "ContentContainsSensitiveInformation": [ - {"name": "U.S. Individual Taxpayer Identification Number (ITIN)"} - ], - "Name": "Baseline Rule", - "Disabled" : false, - "ParentPolicyName": "Default Office 365 DLP policy", - "BlockAccess": true, - "BlockAccessScope": "All", - "NotifyUser": [ ], - "NotifyUserType": "NotSet" - } - ], - "dlp_compliance_policies": [ - { - "Name": "Default Office 365 DLP policy", - "Mode": "Enable", - "Enabled": true - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "1 rule(s) found that do(es) not notify at least one user: Baseline Rule" -} - -# -# Policy 5 -#-- -test_NotImplemented_Correct_V1 if { - ControlNumber := "Defender 2.2" - Requirement := "A list of apps that are not allowed to access files protected by DLP policy SHOULD be defined" - - Output := tests with input as { } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Currently cannot be checked automatically. See Defender Secure Configuration Baseline policy 2.2 for instructions on manual check" -} - -# -# Policy 6 -#-- -test_NotImplemented_Correct_V2 if { - ControlNumber := "Defender 2.2" - Requirement := "A list of browsers that are not allowed to access files protected by DLP policy SHOULD be defined" - - Output := tests with input as { } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Currently cannot be checked automatically. See Defender Secure Configuration Baseline policy 2.2 for instructions on manual check" -} \ No newline at end of file diff --git a/Testing/Unit/Rego/Defender/DefenderConfig2_03_test.rego b/Testing/Unit/Rego/Defender/DefenderConfig2_03_test.rego deleted file mode 100644 index ad1b82b303..0000000000 --- a/Testing/Unit/Rego/Defender/DefenderConfig2_03_test.rego +++ /dev/null @@ -1,198 +0,0 @@ -package defender -import future.keywords - - -# -# Policy 1 -#-- -test_EnableFileFilter_Correct if { - ControlNumber := "Defender 2.3" - Requirement := "The common attachments filter SHALL be enabled in the default anti-malware policy and in all existing policies" - - Output := tests with input as { - "malware_filter_policies": [ - { - "EnableFileFilter" : true, - "Name": "Default" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_EnableFileFilter_Incorrect if { - ControlNumber := "Defender 2.3" - Requirement := "The common attachments filter SHALL be enabled in the default anti-malware policy and in all existing policies" - - Output := tests with input as { - "malware_filter_policies": [ - { - "EnableFileFilter" : false, - "Name": "Default" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "1 malware policy(ies) found that do(es) not have the common attachments filter enabled: Default" -} - -test_EnableFileFilterMultiple_Incorrect if { - ControlNumber := "Defender 2.3" - Requirement := "The common attachments filter SHALL be enabled in the default anti-malware policy and in all existing policies" - - Output := tests with input as { - "malware_filter_policies": [ - { - "EnableFileFilter" : true, - "Name": "Default" - }, - { - "EnableFileFilter" : false, - "Name": "Custom 1" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "1 malware policy(ies) found that do(es) not have the common attachments filter enabled: Custom 1" -} - -# -# Policy 2 -#-- -test_FileTypes_Correct_V1 if { - ControlNumber := "Defender 2.3" - Requirement := "Disallowed file types SHALL be determined and set. At a minimum, click-to-run files SHOULD be blocked: exe files" - - Output := tests with input as { - "malware_filter_policies": [ - { - "FileTypes" : ["exe"], - "EnableFileFilter" : true, - "Name": "Default" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_FileTypes_Incorrect_V1 if { - ControlNumber := "Defender 2.3" - Requirement := "Disallowed file types SHALL be determined and set. At a minimum, click-to-run files SHOULD be blocked: exe files" - - Output := tests with input as { - "malware_filter_policies": [ - { - "FileTypes" : ["cmd", "vbe"], - "EnableFileFilter" : true, - "Name": "Default" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "No malware policies found that block .exe files." -} - -test_FileTypes_Correct_V2 if { - ControlNumber := "Defender 2.3" - Requirement := "Disallowed file types SHALL be determined and set. At a minimum, click-to-run files SHOULD be blocked: cmd files" - - Output := tests with input as { - "malware_filter_policies": [ - { - "FileTypes" : ["cmd"], - "EnableFileFilter" : true, - "Name": "Default" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_FileTypes_Incorrect_V2 if { - ControlNumber := "Defender 2.3" - Requirement := "Disallowed file types SHALL be determined and set. At a minimum, click-to-run files SHOULD be blocked: cmd files" - - Output := tests with input as { - "malware_filter_policies": [ - { - "FileTypes" : ["exe", "vbe"], - "EnableFileFilter" : true, - "Name": "Default" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "No malware policies found that block .cmd files." -} - -test_FileTypes_Correct_V3 if { - ControlNumber := "Defender 2.3" - Requirement := "Disallowed file types SHALL be determined and set. At a minimum, click-to-run files SHOULD be blocked: vbe files" - - Output := tests with input as { - "malware_filter_policies": [ - { - "FileTypes" : ["vbe"], - "EnableFileFilter" : true, - "Name": "Default" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_FileTypes_Incorrect_V3 if { - ControlNumber := "Defender 2.3" - Requirement := "Disallowed file types SHALL be determined and set. At a minimum, click-to-run files SHOULD be blocked: vbe files" - - Output := tests with input as { - "malware_filter_policies": [ - { - "FileTypes" : ["exe", "cmd"], - "EnableFileFilter" : true, - "Name": "Default" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "No malware policies found that block .vbe files." -} \ No newline at end of file diff --git a/Testing/Unit/Rego/Defender/DefenderConfig2_04_test.rego b/Testing/Unit/Rego/Defender/DefenderConfig2_04_test.rego deleted file mode 100644 index 5bc280fd0e..0000000000 --- a/Testing/Unit/Rego/Defender/DefenderConfig2_04_test.rego +++ /dev/null @@ -1,70 +0,0 @@ -package defender -import future.keywords - - -# -# Policy 1 -#-- -test_ZapEnabled_Correct if { - ControlNumber := "Defender 2.4" - Requirement := "Zero-hour Auto Purge (ZAP) for malware SHOULD be enabled in the default anti-malware policy and in all existing custom policies" - - Output := tests with input as { - "malware_filter_policies": [ - { - "ZapEnabled" : true, - "Name": "Default" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_ZapEnabled_Incorrect if { - ControlNumber := "Defender 2.4" - Requirement := "Zero-hour Auto Purge (ZAP) for malware SHOULD be enabled in the default anti-malware policy and in all existing custom policies" - - Output := tests with input as { - "malware_filter_policies": [ - { - "ZapEnabled" : false, - "Name": "Default" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "1 malware policy(ies) found without ZAP for malware enabled: Default" -} - -test_ZapEnabledMultiple_Incorrect if { - ControlNumber := "Defender 2.4" - Requirement := "Zero-hour Auto Purge (ZAP) for malware SHOULD be enabled in the default anti-malware policy and in all existing custom policies" - - Output := tests with input as { - "malware_filter_policies": [ - { - "ZapEnabled" : true, - "Name": "Default" - }, - { - "ZapEnabled" : false, - "Name": "Custom 1" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "1 malware policy(ies) found without ZAP for malware enabled: Custom 1" -} \ No newline at end of file diff --git a/Testing/Unit/Rego/Defender/DefenderConfig2_05_test.rego b/Testing/Unit/Rego/Defender/DefenderConfig2_05_test.rego deleted file mode 100644 index b24ed52f0a..0000000000 --- a/Testing/Unit/Rego/Defender/DefenderConfig2_05_test.rego +++ /dev/null @@ -1,1377 +0,0 @@ -package defender -import future.keywords - - -# -# Policy 1 -#-- -test_TargetedUsers_Correct if { - ControlNumber := "Defender 2.5" - Requirement := "User impersonation protection SHOULD be enabled for key agency leaders" - - Output := tests with input as { - "anti_phish_policies": [ - { - "Name" : "Standard Preset Security Policy1659535429826", - "Enabled" : true, - "EnableTargetedUserProtection" : true, - "TargetedUsersToProtect" : [ - "john doe;jdoe@someemail.com", - "jane doe;jadoe@someemail.com" - ], - "TargetedUserProtectionAction": "Quarantine" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_Enabled_Incorrect if { - ControlNumber := "Defender 2.5" - Requirement := "User impersonation protection SHOULD be enabled for key agency leaders" - - Output := tests with input as { - "anti_phish_policies" : [ - { - "Name" : "Standard Preset Security Policy1659535429826", - "Enabled" : false, - "EnableTargetedUserProtection" : true, - "TargetedUsersToProtect" : [ - "john doe;jdoe@someemail.com", - "jane doe;jadoe@someemail.com" - ], - "TargetedUserProtectionAction" : "Quarantine" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "No users are included for targeted user protection." -} - -test_EnableTargetedUserProtection_Incorrect if { - ControlNumber := "Defender 2.5" - Requirement := "User impersonation protection SHOULD be enabled for key agency leaders" - - Output := tests with input as { - "anti_phish_policies" : [ - { - "Name" : "Standard Preset Security Policy1659535429826", - "Enabled" : true, - "EnableTargetedUserProtection" : false, - "TargetedUsersToProtect" : [ - "john doe;jdoe@someemail.com", - "jane doe;jadoe@someemail.com" - ], - "TargetedUserProtectionAction" : "Quarantine" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "No users are included for targeted user protection." -} - -test_TargetedUsersToProtect_Incorrect if { - ControlNumber := "Defender 2.5" - Requirement := "User impersonation protection SHOULD be enabled for key agency leaders" - - Output := tests with input as { - "anti_phish_policies" : [ - { - "Name" : "Standard Preset Security Policy1659535429826", - "Enabled" : true, - "EnableTargetedUserProtection" : true, - "TargetedUsersToProtect" : [ ], - "TargetedUserProtectionAction" : "Quarantine" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "No users are included for targeted user protection." -} - -# -# Policy 2 -#-- -test_OrganizationDomain_Correct if { - ControlNumber := "Defender 2.5" - Requirement := "Domain impersonation protection SHOULD be enabled for domains owned by the agency" - - Output := tests with input as { - "anti_phish_policies" : [ - { - "Name" : "Standard Preset Security Policy1659535429826", - "Enabled" : true, - "EnableOrganizationDomainsProtection" : true, - "EnableTargetedDomainsProtection" : true, - "TargetedDomainProtectionAction" : "Quarantine", - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_Enabled_Incorrect_V2 if { - ControlNumber := "Defender 2.5" - Requirement := "Domain impersonation protection SHOULD be enabled for domains owned by the agency" - - Output := tests with input as { - "anti_phish_policies" : [ - { - "Name" : "Standard Preset Security Policy1659535429826", - "Enabled" : false, - "EnableOrganizationDomainsProtection" : true, - "EnableTargetedDomainsProtection" : true, - "TargetedDomainProtectionAction" : "Quarantine", - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement not met" -} - -test_EnableOrganizationDomainsProtection_Incorrect if { - ControlNumber := "Defender 2.5" - Requirement := "Domain impersonation protection SHOULD be enabled for domains owned by the agency" - - Output := tests with input as { - "anti_phish_policies" : [ - { - "Name" : "Standard Preset Security Policy1659535429826", - "Enabled" : true, - "EnableOrganizationDomainsProtection" : false, - "EnableTargetedDomainsProtection" : true, - "TargetedDomainProtectionAction" : "Quarantine", - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement not met" -} - -test_EnableTargetedDomainsProtection_Incorrect if { - ControlNumber := "Defender 2.5" - Requirement := "Domain impersonation protection SHOULD be enabled for domains owned by the agency" - - Output := tests with input as { - "anti_phish_policies" : [ - { - "Name" : "Standard Preset Security Policy1659535429826", - "Enabled" : true, - "EnableOrganizationDomainsProtection" : true, - "EnableTargetedDomainsProtection" : false, - "TargetedDomainProtectionAction" : "Quarantine", - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement not met" -} - -# -# Policy 3 -#-- -test_CustomDomains_Correct if { - ControlNumber := "Defender 2.5" - Requirement := "Domain impersonation protection SHOULD be added for frequent partners" - - Output := tests with input as { - "anti_phish_policies" : [ - { - "Name" : "Standard Preset Security Policy1659535429826", - "Enabled" : true, - "EnableTargetedDomainsProtection" : true, - "TargetedDomainsToProtect" : [ "test domain" ], - "TargetedDomainProtectionAction" : "Quarantine" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_Enabled_Incorrect_V3 if { - ControlNumber := "Defender 2.5" - Requirement := "Domain impersonation protection SHOULD be added for frequent partners" - - Output := tests with input as { - "anti_phish_policies" : [ - { - "Name" : "Standard Preset Security Policy1659535429826", - "Enabled" : false, - "EnableTargetedDomainsProtection" : true, - "TargetedDomainsToProtect" : [ "test domain" ], - "TargetedDomainProtectionAction" : "Quarantine" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "The Custom Domains protection policies: Enabled, EnableTargetedDomainsProtection, and TargetedDomainsToProtect are not set correctly" -} - -test_EnableTargetedDomainsProtection_Incorrect if { - ControlNumber := "Defender 2.5" - Requirement := "Domain impersonation protection SHOULD be added for frequent partners" - - Output := tests with input as { - "anti_phish_policies" : [ - { - "Name" : "Standard Preset Security Policy1659535429826", - "Enabled" : true, - "EnableTargetedDomainsProtection" : false, - "TargetedDomainsToProtect" : [ "test domain" ], - "TargetedDomainProtectionAction" : "Quarantine" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "The Custom Domains protection policies: Enabled, EnableTargetedDomainsProtection, and TargetedDomainsToProtect are not set correctly" -} - -test_TargetedDomainsToProtect_Incorrect if { - ControlNumber := "Defender 2.5" - Requirement := "Domain impersonation protection SHOULD be added for frequent partners" - - Output := tests with input as { - "anti_phish_policies" : [ - { - "Name" : "Standard Preset Security Policy1659535429826", - "Enabled" : true, - "EnableTargetedDomainsProtection" : true, - "TargetedDomainsToProtect" : [ ], - "TargetedDomainProtectionAction" : "Quarantine" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "The Custom Domains protection policies: Enabled, EnableTargetedDomainsProtection, and TargetedDomainsToProtect are not set correctly" -} - -# -# Policy 4 -#-- -test_Email_Correct if { - ControlNumber := "Defender 2.5" - Requirement := "Intelligence for impersonation protection SHALL be enabled" - - Output := tests with input as { - "anti_phish_policies" : [ - { - "Name" : "Standard Preset Security Policy1659535429826", - "Enabled" : true, - "EnableMailboxIntelligenceProtection" : true, - "MailboxIntelligenceProtectionAction" : "Quarantine" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_Enabled_Incorrect_V4 if { - ControlNumber := "Defender 2.5" - Requirement := "Intelligence for impersonation protection SHALL be enabled" - - Output := tests with input as { - "anti_phish_policies" : [ - { - "Name" : "Standard Preset Security Policy1659535429826", - "Enabled" : false, - "EnableMailboxIntelligenceProtection" : true, - "MailboxIntelligenceProtectionAction" : "Quarantine" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement not met" -} - -test_EnableMailboxIntelligenceProtection_Incorrect if { - ControlNumber := "Defender 2.5" - Requirement := "Intelligence for impersonation protection SHALL be enabled" - - Output := tests with input as { - "anti_phish_policies" : [ - { - "Name" : "Standard Preset Security Policy1659535429826", - "Enabled" : true, - "EnableMailboxIntelligenceProtection" : false, - "MailboxIntelligenceProtectionAction" : "Quarantine" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement not met" -} - -# -# Policy 5 -#-- -test_TargetedUserProtectionAction_Correct if { - ControlNumber := "Defender 2.5" - Requirement := "Message action SHALL be set to quarantine if the message is detected as impersonated: users default policy" - - Output := tests with input as { - "anti_phish_policies" : [ - { - "TargetedUserProtectionAction" : "Quarantine", - "Identity" : "Office365 AntiPhish Default" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_TargetedUserProtectionAction_Incorrect if { - ControlNumber := "Defender 2.5" - Requirement := "Message action SHALL be set to quarantine if the message is detected as impersonated: users default policy" - - Output := tests with input as { - "anti_phish_policies" : [ - { - "TargetedUserProtectionAction" : "Not Quarantine", - "Identity" : "Office365 AntiPhish Default" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement not met" -} - -test_TargetedUserProtectionActionCustom_Correct if { - ControlNumber := "Defender 2.5" - Requirement := "Message action SHOULD be set to quarantine if the message is detected as impersonated: users non-default policies" - - Output := tests with input as { - "anti_phish_policies" : [ - { - "TargetedUserProtectionAction" : "Quarantine", - "Identity" : "Custom 1" - }, - { - "TargetedUserProtectionAction" : "Not Quarantine", - "Identity" : "Office365 AntiPhish Default" # The default policy should be ignored here - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_TargetedUserProtectionActionCustom_Incorrect if { - ControlNumber := "Defender 2.5" - Requirement := "Message action SHOULD be set to quarantine if the message is detected as impersonated: users non-default policies" - - Output := tests with input as { - "anti_phish_policies" : [ - { - "TargetedUserProtectionAction" : "Quarantine", - "Identity" : "Custom 1" - }, - { - "TargetedUserProtectionAction" : "Not Quarantine", - "Identity" : "Custom 2" - }, - { - "TargetedUserProtectionAction" : "Not Quarantine", - "Identity" : "Office365 AntiPhish Default" # The default policy should be ignored here - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "1 non-default anti phish policy(ies) found where the action for messages detected as user impersonation is not quarantine: Custom 2" -} - - -test_TargetedDomainProtectionAction_Correct if { - ControlNumber := "Defender 2.5" - Requirement := "Message action SHALL be set to quarantine if the message is detected as impersonated: domains default policy" - - Output := tests with input as { - "anti_phish_policies" : [ - { - "TargetedDomainProtectionAction" : "Quarantine", - "Identity" : "Office365 AntiPhish Default" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_TargetedDomainProtectionAction_Incorrect if { - ControlNumber := "Defender 2.5" - Requirement := "Message action SHALL be set to quarantine if the message is detected as impersonated: domains default policy" - - Output := tests with input as { - "anti_phish_policies" : [ - { - "TargetedDomainProtectionAction" : "Not Quarantine", - "Identity" : "Office365 AntiPhish Default" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement not met" -} - -test_TargetedDomainProtectionActionCustom_Correct if { - ControlNumber := "Defender 2.5" - Requirement := "Message action SHOULD be set to quarantine if the message is detected as impersonated: domains non-default policies" - Output := tests with input as { - "anti_phish_policies" : [ - { - "TargetedDomainProtectionAction" : "Quarantine", - "Identity" : "Custom 1" - }, - { - "TargetedDomainProtectionAction" : "Not Quarantine", - "Identity" : "Office365 AntiPhish Default" # The default policy should be ignored here - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_TargetedDomainProtectionActionCustom_Incorrect if { - ControlNumber := "Defender 2.5" - Requirement := "Message action SHOULD be set to quarantine if the message is detected as impersonated: domains non-default policies" - Output := tests with input as { - "anti_phish_policies" : [ - { - "TargetedDomainProtectionAction" : "Quarantine", - "Identity" : "Custom 1" - }, - { - "TargetedDomainProtectionAction" : "Not Quarantine", - "Identity" : "Custom 2" - }, - { - "TargetedDomainProtectionAction" : "Not Quarantine", - "Identity" : "Custom 3" - }, - { - "TargetedDomainProtectionAction" : "Not Quarantine", - "Identity" : "Office365 AntiPhish Default" # The default policy should be ignored here - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - startswith(RuleOutput[0].ReportDetails, "2 non-default anti phish policy(ies) found where the action for messages detected as domain impersonation is not quarantine:") - # I don't think we can assume the order rego will Output these, hence the "includes" check instead of a simple == - contains(RuleOutput[0].ReportDetails, "Custom 2") - contains(RuleOutput[0].ReportDetails, "Custom 3") -} - -test_MailboxIntelligenceProtectionAction_Correct if { - ControlNumber := "Defender 2.5" - Requirement := "Message action SHALL be set to quarantine if the message is detected as impersonated: mailbox default policy" - - Output := tests with input as { - "anti_phish_policies" : [ - { - "MailboxIntelligenceProtectionAction" : "Quarantine", - "Identity" : "Office365 AntiPhish Default" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_MailboxIntelligenceProtectionAction_Incorrect if { - ControlNumber := "Defender 2.5" - Requirement := "Message action SHALL be set to quarantine if the message is detected as impersonated: mailbox default policy" - - Output := tests with input as { - "anti_phish_policies" : [ - { - "MailboxIntelligenceProtectionAction" : "Not Quarantine", - "Identity" : "Office365 AntiPhish Default" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement not met" -} - -test_MailIntProtectionActionCustom_Correct if { - ControlNumber := "Defender 2.5" - Requirement := "Message action SHOULD be set to quarantine if the message is detected as impersonated: mailbox non-default policies" - Output := tests with input as { - "anti_phish_policies" : [ - { - "MailboxIntelligenceProtectionAction" : "Quarantine", - "Identity" : "Custom 1" - }, - { - "MailboxIntelligenceProtectionAction" : "Quarantine", - "Identity" : "Custom 2" - }, - { - "MailboxIntelligenceProtectionAction" : "something else", - "Identity" : "Standard Preset Security Policy314195" # should be ignored - }, - { - "MailboxIntelligenceProtectionAction" : "Not Quarantine", - "Identity" : "Office365 AntiPhish Default" # The default policy should be ignored here - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails = "Requirement met" -} - -test_MailIntProtectionActionCustom_Incorrect if { - ControlNumber := "Defender 2.5" - Requirement := "Message action SHOULD be set to quarantine if the message is detected as impersonated: mailbox non-default policies" - Output := tests with input as { - "anti_phish_policies" : [ - { - "MailboxIntelligenceProtectionAction" : "Quarantine", - "Identity" : "Custom 1" - }, - { - "MailboxIntelligenceProtectionAction" : "Not Quarantine", - "Identity" : "Custom 2" - }, - { - "MailboxIntelligenceProtectionAction" : "something else", - "Identity" : "Standard Preset Security Policy314195" # should be ignored - }, - { - "MailboxIntelligenceProtectionAction" : "Not Quarantine", - "Identity" : "Office365 AntiPhish Default" # The default policy should be ignored here - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails = "1 non-default anti phish policy(ies) found where the action for messages flagged by mailbox intelligence is not quarantine: Custom 2" -} - -# -# Policy 6 -#-- -test_AuthenticationFailAction_Correct if { - ControlNumber := "Defender 2.5" - Requirement := "Mail classified as spoofed SHALL be quarantined: default policy" - - Output := tests with input as { - "anti_phish_policies" : [ - { - "AuthenticationFailAction" : "Quarantine", - "Identity" : "Office365 AntiPhish Default" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_AuthenticationFailAction_Incorrect if { - ControlNumber := "Defender 2.5" - Requirement := "Mail classified as spoofed SHALL be quarantined: default policy" - - Output := tests with input as { - "anti_phish_policies" : [ - { - "AuthenticationFailAction" : "Not Quarantine", - "Identity" : "Office365 AntiPhish Default" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement not met" -} - -test_AuthenticationFailActionNonDefault_Correct if { - ControlNumber := "Defender 2.5" - Requirement := "Mail classified as spoofed SHOULD be quarantined: non-default policies" - - Output := tests with input as { - "anti_phish_policies" : [ - { - "AuthenticationFailAction" : "Quarantine", - "Identity" : "Not Standard Preset SecurityPolicy1659535429826" - }, - { - "AuthenticationFailAction" : "Quarantine", - "Identity" : "Not Standard Preset SecurityPolicy Either" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_AuthenticationFailActionNonDefault_Incorrect if { - ControlNumber := "Defender 2.5" - Requirement := "Mail classified as spoofed SHOULD be quarantined: non-default policies" - - Output := tests with input as { - "anti_phish_policies" : [ - { - "AuthenticationFailAction" : "Not Quarantine", - "Identity" : "Not Standard Preset SecurityPolicy1659535429826" - }, - { - "AuthenticationFailAction" : "Quarantine", - "Identity" : "Not Standard Preset SecurityPolicy Either" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "1 custom anti phish policy(ies) found where the action for spoofed emails is not set to quarantine: Not Standard Preset SecurityPolicy1659535429826" - #Custom anti phish policy(ies) found where the action for spoofed emails is not set to quarantine. -} - -# -# Policy 7 -#-- -test_EnableFirstContactSafetyTipsDefault_Correct if { - ControlNumber := "Defender 2.5" - Requirement := "All safety tips SHALL be enabled: first contact default policy" - - Output := tests with input as { - "anti_phish_policies" : [ - { - "EnableFirstContactSafetyTips" : true, - "Identity" : "Office365 AntiPhish Default" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_EnableFirstContactSafetyTipsDefault_Incorrect if { - ControlNumber := "Defender 2.5" - Requirement := "All safety tips SHALL be enabled: first contact default policy" - - Output := tests with input as { - "anti_phish_policies" : [ - { - "EnableFirstContactSafetyTips" : false, - "Identity" : "Office365 AntiPhish Default" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement not met" -} - -test_EnableFirstContactSafetyTipsNonDefault_Correct if { - ControlNumber := "Defender 2.5" - Requirement := "All safety tips SHOULD be enabled: first contact non-default policies" - - Output := tests with input as { - "anti_phish_policies" : [ - { - "EnableFirstContactSafetyTips" : true, - "Identity" : "Custom policy 1" - }, - { - "EnableFirstContactSafetyTips" : true, - "Identity" : "Custom policy 2" - }, - { - "EnableFirstContactSafetyTips" : true, - "Identity" : "Custom policy 3" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_EnableFirstContactSafetyTipsNonDefault_Incorrect if { - ControlNumber := "Defender 2.5" - Requirement := "All safety tips SHOULD be enabled: first contact non-default policies" - - Output := tests with input as { - "anti_phish_policies" : [ - { - "EnableFirstContactSafetyTips" : true, - "Identity" : "Custom policy 1" - }, - { - "EnableFirstContactSafetyTips" : false, - "Identity" : "Custom policy 2" - }, - { - "EnableFirstContactSafetyTips" : true, - "Identity" : "Custom policy 3" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "1 custom anti phish policy(ies) found where first contact safety tips are not enabled: Custom policy 2" -} - -test_EnableSimilarUsersSafetyTipsDefault_Correct if { - ControlNumber := "Defender 2.5" - Requirement := "All safety tips SHALL be enabled: user impersonation default policy" - - Output := tests with input as { - "anti_phish_policies" : [ - { - "EnableSimilarUsersSafetyTips" : true, - "Identity" : "Office365 AntiPhish Default" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_EnableSimilarUsersSafetyTipsDefault_Incorrect if { - ControlNumber := "Defender 2.5" - Requirement := "All safety tips SHALL be enabled: user impersonation default policy" - - Output := tests with input as { - "anti_phish_policies" : [ - { - "EnableSimilarUsersSafetyTips" : false, - "Identity" : "Office365 AntiPhish Default" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement not met" -} - -test_EnableSimilarUserSafetyTipsNonDefault_Correct if { - ControlNumber := "Defender 2.5" - Requirement := "All safety tips SHOULD be enabled: user impersonation non-default policies" - - Output := tests with input as { - "anti_phish_policies" : [ - { - "EnableSimilarUsersSafetyTips" : true, - "Identity" : "Custom policy 1" - }, - { - "EnableSimilarUsersSafetyTips" : true, - "Identity" : "Custom policy 2" - }, - { - "EnableSimilarUsersSafetyTips" : true, - "Identity" : "Custom policy 3" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_EnableSimilarUserSafetyTipsNonDefault_Incorrect if { - ControlNumber := "Defender 2.5" - Requirement := "All safety tips SHOULD be enabled: user impersonation non-default policies" - - Output := tests with input as { - "anti_phish_policies" : [ - { - "EnableSimilarUsersSafetyTips" : true, - "Identity" : "Custom policy 1" - }, - { - "EnableSimilarUsersSafetyTips" : false, - "Identity" : "Custom policy 2" - }, - { - "EnableSimilarUsersSafetyTips" : true, - "Identity" : "Custom policy 3" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "1 custom anti phish policy(ies) found where similar user safety tips are not enabled: Custom policy 2" -} - -test_EnableSimilarDomainsSafetyTipsDomains_Correct if { - ControlNumber := "Defender 2.5" - Requirement := "All safety tips SHALL be enabled: domain impersonation default policy" - - Output := tests with input as { - "anti_phish_policies" : [ - { - "EnableSimilarDomainsSafetyTips" : true, - "Identity" : "Office365 AntiPhish Default" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_EnableSimilarDomainsSafetyTipsDefault_Incorrect if { - ControlNumber := "Defender 2.5" - Requirement := "All safety tips SHALL be enabled: domain impersonation default policy" - - Output := tests with input as { - "anti_phish_policies" : [ - { - "EnableSimilarDomainsSafetyTips" : false, - "Identity" : "Office365 AntiPhish Default" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement not met" -} - -test_EnableSimilarDomainsSafetyTipsNonDefault_Correct if { - ControlNumber := "Defender 2.5" - Requirement := "All safety tips SHOULD be enabled: domain impersonation non-default policies" - - Output := tests with input as { - "anti_phish_policies" : [ - { - "EnableSimilarDomainsSafetyTips" : true, - "Identity" : "Custom policy 1" - }, - { - "EnableSimilarDomainsSafetyTips" : true, - "Identity" : "Custom policy 2" - }, - { - "EnableSimilarDomainsSafetyTips" : true, - "Identity" : "Custom policy 3" - }, - { - "EnableSimilarDomainsSafetyTips" : false, # The default policy should be ignored - "Identity" : "Office365 AntiPhish Default" - }, - { - "EnableSimilarDomainsSafetyTips" : false, # The preset policy should be ignored too - "Identity" : "Standard Preset Security Policy12345" - }, - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_EnableSimilarDomainsSafetyTipsNonDefault_Incorrect if { - ControlNumber := "Defender 2.5" - Requirement := "All safety tips SHOULD be enabled: domain impersonation non-default policies" - - Output := tests with input as { - "anti_phish_policies" : [ - { - "EnableSimilarDomainsSafetyTips" : true, - "Identity" : "Custom policy 1" - }, - { - "EnableSimilarDomainsSafetyTips" : false, - "Identity" : "Custom policy 2" - }, - { - "EnableSimilarDomainsSafetyTips" : true, - "Identity" : "Custom policy 3" - }, - { - "EnableSimilarDomainsSafetyTips" : false, # The default policy should be ignored - "Identity" : "Office365 AntiPhish Default" - }, - { - "EnableSimilarDomainsSafetyTips" : false, # The preset policy should be ignored too - "Identity" : "Standard Preset Security Policy12345" - }, - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "1 custom anti phish policy(ies) found where similar domains safety tips are not enabled: Custom policy 2" -} - -test_EnableUnusualCharactersSafetyTips_Correct if { - ControlNumber := "Defender 2.5" - Requirement := "All safety tips SHALL be enabled: user impersonation unusual characters default policy" - - Output := tests with input as { - "anti_phish_policies" : [ - { - "EnableUnusualCharactersSafetyTips" : true, - "Identity" : "Office365 AntiPhish Default" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_EnableUnusualCharactersSafetyTips_Incorrect if { - ControlNumber := "Defender 2.5" - Requirement := "All safety tips SHALL be enabled: user impersonation unusual characters default policy" - - Output := tests with input as { - "anti_phish_policies" : [ - { - "EnableUnusualCharactersSafetyTips" : false, - "Identity" : "Office365 AntiPhish Default" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement not met" -} - -test_EnableUnusualCharSafetyTipsNonDefault_Correct if { - ControlNumber := "Defender 2.5" - Requirement := "All safety tips SHOULD be enabled: user impersonation unusual characters non-default policies" - - Output := tests with input as { - "anti_phish_policies" : [ - { - "EnableUnusualCharactersSafetyTips" : true, - "Identity" : "Custom policy 1" - }, - { - "EnableUnusualCharactersSafetyTips" : true, - "Identity" : "Custom policy 2" - }, - { - "EnableUnusualCharactersSafetyTips" : true, - "Identity" : "Custom policy 3" - }, - { - "EnableUnusualCharactersSafetyTips" : false, # The default policy should be ignored - "Identity" : "Office365 AntiPhish Default" - }, - { - "EnableUnusualCharactersSafetyTips" : false, # The preset policy should be ignored too - "Identity" : "Standard Preset Security Policy12345" - }, - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_EnableUnusualCharSafetyTipsNonDefault_Incorrect if { - ControlNumber := "Defender 2.5" - Requirement := "All safety tips SHOULD be enabled: user impersonation unusual characters non-default policies" - - Output := tests with input as { - "anti_phish_policies" : [ - { - "EnableUnusualCharactersSafetyTips" : true, - "Identity" : "Custom policy 1" - }, - { - "EnableUnusualCharactersSafetyTips" : false, - "Identity" : "Custom policy 2" - }, - { - "EnableUnusualCharactersSafetyTips" : true, - "Identity" : "Custom policy 3" - }, - { - "EnableUnusualCharactersSafetyTips" : false, # The default policy should be ignored - "Identity" : "Office365 AntiPhish Default" - }, - { - "EnableUnusualCharactersSafetyTips" : false, # The preset policy should be ignored too - "Identity" : "Standard Preset Security Policy12345" - }, - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "1 custom anti phish policy(ies) found where unusual character safety tips are not enabled: Custom policy 2" -} - -test_EnableViaTagDefault_Correct if { - ControlNumber := "Defender 2.5" - Requirement := "All safety tips SHALL be enabled: \"via\" tag default policy" - - Output := tests with input as { - "anti_phish_policies" : [ - { - "EnableViaTag" : true, - "Identity" : "Office365 AntiPhish Default" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_EnableViaTagDefault_Incorrect if { - ControlNumber := "Defender 2.5" - Requirement := "All safety tips SHALL be enabled: \"via\" tag default policy" - - Output := tests with input as { - "anti_phish_policies" : [ - { - "EnableViaTag" : false, - "Identity" : "Office365 AntiPhish Default" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement not met" -} - -test_EnableViaTagSafetyTipsNonDefault_Correct if { - ControlNumber := "Defender 2.5" - Requirement := "All safety tips SHOULD be enabled: \"via\" tag non-default policies" - - Output := tests with input as { - "anti_phish_policies" : [ - { - "EnableViaTag" : true, - "Identity" : "Custom policy 1" - }, - { - "EnableViaTag" : true, - "Identity" : "Custom policy 2" - }, - { - "EnableViaTag" : true, - "Identity" : "Custom policy 3" - }, - { - "EnableViaTag" : false, # The default policy should be ignored - "Identity" : "Office365 AntiPhish Default" - }, - { - "EnableViaTag" : false, # The preset policy should be ignored too - "Identity" : "Standard Preset Security Policy12345" - }, - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_EnableViaTagSafetyTipsNonDefault_Incorrect if { - ControlNumber := "Defender 2.5" - Requirement := "All safety tips SHOULD be enabled: \"via\" tag non-default policies" - - Output := tests with input as { - "anti_phish_policies" : [ - { - "EnableViaTag" : true, - "Identity" : "Custom policy 1" - }, - { - "EnableViaTag" : false, - "Identity" : "Custom policy 2" - }, - { - "EnableViaTag" : true, - "Identity" : "Custom policy 3" - }, - { - "EnableViaTag" : false, # The default policy should be ignored - "Identity" : "Office365 AntiPhish Default" - }, - { - "EnableViaTag" : false, # The preset policy should be ignored too - "Identity" : "Standard Preset Security Policy12345" - }, - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "1 custom anti phish policy(ies) found where via tag is not enabled: Custom policy 2" -} - -test_EnableUnauthenticatedSenderDefault_Correct if { - ControlNumber := "Defender 2.5" - Requirement := "All safety tips SHALL be enabled: \"?\" for unauthenticated senders for spoof default policy" - - Output := tests with input as { - "anti_phish_policies" : [ - { - "EnableUnauthenticatedSender" : true, - "Identity" : "Office365 AntiPhish Default" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_EnableUnauthenticatedSenderDefault_Incorrect if { - ControlNumber := "Defender 2.5" - Requirement := "All safety tips SHALL be enabled: \"?\" for unauthenticated senders for spoof default policy" - - Output := tests with input as { - "anti_phish_policies" : [ - { - "EnableUnauthenticatedSender" : false, - "Identity" : "Office365 AntiPhish Default" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement not met" -} - -test_EnableUnauthSenderTipsNonDefault_Correct if { - ControlNumber := "Defender 2.5" - Requirement := "All safety tips SHOULD be enabled: \"?\" for unauthenticated senders for spoof non-default policies" - - Output := tests with input as { - "anti_phish_policies" : [ - { - "EnableUnauthenticatedSender" : true, - "Identity" : "Custom policy 1" - }, - { - "EnableUnauthenticatedSender" : true, - "Identity" : "Custom policy 2" - }, - { - "EnableUnauthenticatedSender" : true, - "Identity" : "Custom policy 3" - }, - { - "EnableUnauthenticatedSender" : false, # The default policy should be ignored - "Identity" : "Office365 AntiPhish Default" - }, - { - "EnableUnauthenticatedSender" : false, # The preset policy should be ignored too - "Identity" : "Standard Preset Security Policy12345" - }, - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_EnableUnauthSenderTipsNonDefault_Incorrect if { - ControlNumber := "Defender 2.5" - Requirement := "All safety tips SHOULD be enabled: \"?\" for unauthenticated senders for spoof non-default policies" - - Output := tests with input as { - "anti_phish_policies" : [ - { - "EnableUnauthenticatedSender" : true, - "Identity" : "Custom policy 1" - }, - { - "EnableUnauthenticatedSender" : false, - "Identity" : "Custom policy 2" - }, - { - "EnableUnauthenticatedSender" : true, - "Identity" : "Custom policy 3" - }, - { - "EnableUnauthenticatedSender" : false, # The default policy should be ignored - "Identity" : "Office365 AntiPhish Default" - }, - { - "EnableUnauthenticatedSender" : false, # The preset policy should be ignored too - "Identity" : "Standard Preset Security Policy12345" - }, - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "1 custom anti phish policy(ies) found where '?' for unauthenticated sender is not enabled: Custom policy 2" -} \ No newline at end of file diff --git a/Testing/Unit/Rego/Defender/DefenderConfig2_06_test.rego b/Testing/Unit/Rego/Defender/DefenderConfig2_06_test.rego deleted file mode 100644 index 47394b771c..0000000000 --- a/Testing/Unit/Rego/Defender/DefenderConfig2_06_test.rego +++ /dev/null @@ -1,1278 +0,0 @@ -package defender -import future.keywords - - -# -# Policy 1 -#-- -test_BulkThreshold_Correct if { - ControlNumber := "Defender 2.6" - Requirement := "The bulk complaint level (BCL) threshold SHOULD be set to six or lower: default policy" - - Output := tests with input as { - "hosted_content_filter_policies": [ - { - "BulkThreshold": 6, - "Identity" : "Default" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_BulkThreshold_CorrectV2 if { - ControlNumber := "Defender 2.6" - Requirement := "The bulk complaint level (BCL) threshold SHOULD be set to six or lower: default policy" - - Output := tests with input as { - "hosted_content_filter_policies": [ - { - "BulkThreshold": 5, - "Identity" : "Default" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_BulkThreshold_Incorrect if { - ControlNumber := "Defender 2.6" - Requirement := "The bulk complaint level (BCL) threshold SHOULD be set to six or lower: default policy" - - Output := tests with input as { - "hosted_content_filter_policies": [ - { - "BulkThreshold": 7, - "Identity" : "Default" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement not met" -} - -### - -test_NonDefBulkThreshold_Correct if { - ControlNumber := "Defender 2.6" - Requirement := "The bulk complaint level (BCL) threshold SHOULD be set to six or lower: non-default policies" - - Output := tests with input as { - "hosted_content_filter_policies": [ - { - "BulkThreshold": 6, - "Identity":"Not Default" - }, - { - "BulkThreshold": 6, - "Identity":"Default" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_NonDefBulkThreshold_CorrectV2 if { - ControlNumber := "Defender 2.6" - Requirement := "The bulk complaint level (BCL) threshold SHOULD be set to six or lower: non-default policies" - - Output := tests with input as { - "hosted_content_filter_policies": [ - { - "BulkThreshold": 5, - "Identity":"Not Default" - }, - { - "BulkThreshold": 5, - "Identity":"Default" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_NonDefBulkThreshold_Incorrect if { - ControlNumber := "Defender 2.6" - Requirement := "The bulk complaint level (BCL) threshold SHOULD be set to six or lower: non-default policies" - - Output := tests with input as { - "hosted_content_filter_policies": [ - { - "BulkThreshold": 7, - "Identity":"Not Default" - }, - { - "BulkThreshold": 7, - "Identity":"Default" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "1 custom anti-spam policy(ies) found where bulk complaint level threshold is set to 7 or more: Not Default" -} - -# -# Policy 2 -#-- -test_SpamAction_Correct if { - ControlNumber := "Defender 2.6" - Requirement := "Spam SHALL be moved to either the junk email folder or the quarantine folder: default policy" - - Output := tests with input as { - "hosted_content_filter_policies": [ - { - "SpamAction": "Quarantine", - "Identity": "Default" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_SpamAction_CorrectV2 if { - ControlNumber := "Defender 2.6" - Requirement := "Spam SHALL be moved to either the junk email folder or the quarantine folder: default policy" - - Output := tests with input as { - "hosted_content_filter_policies": [ - { - "SpamAction": "MoveToJmf", - "Identity": "Default" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_SpamAction_Incorrect if { - ControlNumber := "Defender 2.6" - Requirement := "Spam SHALL be moved to either the junk email folder or the quarantine folder: default policy" - - Output := tests with input as { - "hosted_content_filter_policies": [ - { - "SpamAction": "Not MoveToJmf", - "Identity": "Default" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement not met" -} - -test_SpamAction_Incorrect_V2 if { - ControlNumber := "Defender 2.6" - Requirement := "Spam SHALL be moved to either the junk email folder or the quarantine folder: default policy" - - Output := tests with input as { - "hosted_content_filter_policies": [ - { - "SpamAction": "Not Quarantine", - "Identity": "Default" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement not met" -} - -test_HighConfSpamAction_Correct if { - ControlNumber := "Defender 2.6" - Requirement := "High confidence spam SHALL be moved to either the junk email folder or the quarantine folder: default policy" - - Output := tests with input as { - "hosted_content_filter_policies": [ - { - "HighConfidenceSpamAction": "Quarantine", - "Identity": "Default" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_HighConfSpamAction_CorrectV2 if { - ControlNumber := "Defender 2.6" - Requirement := "High confidence spam SHALL be moved to either the junk email folder or the quarantine folder: default policy" - - Output := tests with input as { - "hosted_content_filter_policies": [ - { - "HighConfidenceSpamAction": "MoveToJmf", - "Identity": "Default" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_HighConfSpamAction_Incorrect if { - ControlNumber := "Defender 2.6" - Requirement := "High confidence spam SHALL be moved to either the junk email folder or the quarantine folder: default policy" - - Output := tests with input as { - "hosted_content_filter_policies": [ - { - "HighConfidenceSpamAction": "Not MoveToJmf", - "Identity": "Default" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement not met" -} - -test_HighConfSpamAction_Incorrect_V2 if { - ControlNumber := "Defender 2.6" - Requirement := "High confidence spam SHALL be moved to either the junk email folder or the quarantine folder: default policy" - - Output := tests with input as { - "hosted_content_filter_policies": [ - { - "HighConfidenceSpamAction": "Not Quarantine", - "Identity": "Default" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement not met" -} - -test_Non_Def_SpamAction_Correct if { - ControlNumber := "Defender 2.6" - Requirement := "Spam SHOULD be moved to either the junk email folder or the quarantine folder: non-default policies" - - Output := tests with input as { - "hosted_content_filter_policies": [ - { - "SpamAction": "Quarantine", - "Identity": "Not Default" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_Non_Def_SpamAction_CorrectV2 if { - ControlNumber := "Defender 2.6" - Requirement := "Spam SHOULD be moved to either the junk email folder or the quarantine folder: non-default policies" - - Output := tests with input as { - "hosted_content_filter_policies": [ - { - "SpamAction": "MoveToJmf", - "Identity": "Not Default" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_Non_Def_SpamAction_Incorrect if { - ControlNumber := "Defender 2.6" - Requirement := "Spam SHOULD be moved to either the junk email folder or the quarantine folder: non-default policies" - - Output := tests with input as { - "hosted_content_filter_policies": [ - { - "SpamAction": "Not MoveToJmf", - "Identity": "Not Default" - }, - { - "SpamAction": "Not MoveToJmf", - "Identity": "Default" - } ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "1 custom anti-spam policy(ies) found where spam is not being sent to the Quarantine folder or the Junk Mail Folder: Not Default" -} - -test_Non_Def_SpamAction_Incorrect_V2 if { - ControlNumber := "Defender 2.6" - Requirement := "Spam SHOULD be moved to either the junk email folder or the quarantine folder: non-default policies" - - Output := tests with input as { - "hosted_content_filter_policies": [ - { - "SpamAction": "Not Quarantine", - "Identity": "Not Default" - }, - { - "SpamAction": "Not Quarantine", - "Identity": "Default" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "1 custom anti-spam policy(ies) found where spam is not being sent to the Quarantine folder or the Junk Mail Folder: Not Default" -} - -test_Non_Def_HighConfSpamAction_Correct if { - ControlNumber := "Defender 2.6" - Requirement := "High confidence spam SHOULD be moved to either the junk email folder or the quarantine folder: non-default policies" - - Output := tests with input as { - "hosted_content_filter_policies": [ - { - "HighConfidenceSpamAction": "Quarantine", - "Identity": "Not Default" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_Non_Def_HighConfSpamAction_CorrectV2 if { - ControlNumber := "Defender 2.6" - Requirement := "High confidence spam SHOULD be moved to either the junk email folder or the quarantine folder: non-default policies" - - Output := tests with input as { - "hosted_content_filter_policies": [ - { - "HighConfidenceSpamAction": "MoveToJmf", - "Identity": "Not Default" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_Non_Def_HighConfSpamAction_Incorrect if { - ControlNumber := "Defender 2.6" - Requirement := "High confidence spam SHOULD be moved to either the junk email folder or the quarantine folder: non-default policies" - - Output := tests with input as { - "hosted_content_filter_policies": [ - { - "HighConfidenceSpamAction": "Not MoveToJmf", - "Identity": "Not Default" - }, - { - "HighConfidenceSpamAction": "Not MoveToJmf", - "Identity": "Default" - } ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "1 custom anti-spam policy(ies) found where high confidence spam is not being sent to the Quarantine folder or the Junk Mail Folder: Not Default"} - -test_Non_Def_HighConfSpamAction_Incorrect_V2 if { - ControlNumber := "Defender 2.6" - Requirement := "High confidence spam SHOULD be moved to either the junk email folder or the quarantine folder: non-default policies" - - Output := tests with input as { - "hosted_content_filter_policies": [ - { - "HighConfidenceSpamAction": "Not Quarantine", - "Identity": "Not Default" - }, - { - "HighConfidenceSpamAction": "Not Quarantine", - "Identity": "Default" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "1 custom anti-spam policy(ies) found where high confidence spam is not being sent to the Quarantine folder or the Junk Mail Folder: Not Default"} - -# -# Policy 3 -#-- -test_PhishingSpamAction_Correct if { - ControlNumber := "Defender 2.6" - Requirement := "Phishing SHALL be quarantined: default policy" - - Output := tests with input as { - "hosted_content_filter_policies": [ - { - "PhishSpamAction": "Quarantine", - "Identity": "Default" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_PhishingSpamAction_Incorrect if { - ControlNumber := "Defender 2.6" - Requirement := "Phishing SHALL be quarantined: default policy" - - Output := tests with input as { - "hosted_content_filter_policies": [ - { - "PhishSpamAction": "Not Quarantine", - "Identity": "Default" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement not met" -} - -test_HighConfidencePhishAction_Correct if { - ControlNumber := "Defender 2.6" - Requirement := "High confidence phishing SHALL be quarantined: default policy" - - Output := tests with input as { - "hosted_content_filter_policies": [ - { - "HighConfidencePhishAction": "Quarantine", - "Identity": "Default" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_HighConfidencePhishAction_Incorrect if { - ControlNumber := "Defender 2.6" - Requirement := "High confidence phishing SHALL be quarantined: default policy" - - Output := tests with input as { - "hosted_content_filter_policies": [ - { - "HighConfidencePhishAction": "Not Quarantine", - "Identity": "Default" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement not met" -} - -test_Non_Def_PhishingSpamAction_Correct if { - ControlNumber := "Defender 2.6" - Requirement := "Phishing SHOULD be quarantined: non-default policies" - - Output := tests with input as { - "hosted_content_filter_policies": [ - { - "PhishSpamAction": "Quarantine", - "Identity": "Not Default" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_Non_Def_PhishingSpamAction_Incorrect if { - ControlNumber := "Defender 2.6" - Requirement := "Phishing SHOULD be quarantined: non-default policies" - - Output := tests with input as { - "hosted_content_filter_policies": [ - { - "PhishSpamAction": "Not Quarantine", - "Identity": "Not Default" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "1 custom anti-spam policy(ies) found where phishing isn't moved to the quarantine folder: Not Default" -} - -test_Non_Def_HighConfidencePhishAction_Correct if { - ControlNumber := "Defender 2.6" - Requirement := "High confidence phishing SHOULD be quarantined: non-default policies" - - Output := tests with input as { - "hosted_content_filter_policies": [ - { - "HighConfidencePhishAction": "Quarantine", - "Identity": "Not Default" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_Non_Def_HighConfidencePhishAction_Incorrect if { - ControlNumber := "Defender 2.6" - Requirement := "High confidence phishing SHOULD be quarantined: non-default policies" - - Output := tests with input as { - "hosted_content_filter_policies": [ - { - "HighConfidencePhishAction": "Not Quarantine", - "Identity": "Not Default" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "1 custom anti-spam policy(ies) found where high-confidence phishing isn't moved to quarantine folder: Not Default" -} - -# -# Policy 4 -#-- -test_BulkSpamAction_Correct if { - ControlNumber := "Defender 2.6" - Requirement := "Bulk email SHOULD be moved to either the junk email folder or the quarantine folder: default policy" - - Output := tests with input as { - "hosted_content_filter_policies": [ - { - "BulkSpamAction": "Quarantine", - "Identity": "Default" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_BulkSpamAction_CorrectV2 if { - ControlNumber := "Defender 2.6" - Requirement := "Bulk email SHOULD be moved to either the junk email folder or the quarantine folder: default policy" - - Output := tests with input as { - "hosted_content_filter_policies": [ - { - "BulkSpamAction": "MoveToJmf", - "Identity": "Default" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_BulkSpamAction_Incorrect if { - ControlNumber := "Defender 2.6" - Requirement := "Bulk email SHOULD be moved to either the junk email folder or the quarantine folder: default policy" - - Output := tests with input as { - "hosted_content_filter_policies": [ - { - "BulkSpamAction": "Not Quarantine", - "Identity": "Default" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement not met" -} - -test_BulkSpamAction_Incorrect_V2 if { - ControlNumber := "Defender 2.6" - Requirement := "Bulk email SHOULD be moved to either the junk email folder or the quarantine folder: default policy" - - Output := tests with input as { - "hosted_content_filter_policies": [ - { - "BulkSpamAction": "Not MoveToJmf", - "Identity": "Default" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement not met" -} - -# -# Policy 5 -#-- -test_QuarantineRetentionPeriod_Correct if { - ControlNumber := "Defender 2.6" - Requirement := "Spam in quarantine SHOULD be retained for at least 30 days: default policy" - - Output := tests with input as { - "hosted_content_filter_policies": [ - { - "QuarantineRetentionPeriod": 30, - "Identity": "Default" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_QuarantineRetentionPeriod_Incorrect if { - ControlNumber := "Defender 2.6" - Requirement := "Spam in quarantine SHOULD be retained for at least 30 days: default policy" - - Output := tests with input as { - "hosted_content_filter_policies": [ - { - "QuarantineRetentionPeriod": 31, - "Identity": "Default" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement not met" -} - -test_QuarantineRetentionPeriod_Incorrect_V2 if { - ControlNumber := "Defender 2.6" - Requirement := "Spam in quarantine SHOULD be retained for at least 30 days: default policy" - - Output := tests with input as { - "hosted_content_filter_policies": [ - { - "QuarantineRetentionPeriod": 29, - "Identity": "Default" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement not met" -} - -test_QuarantineRetentionPeriodCustom_Correct if { - ControlNumber := "Defender 2.6" - Requirement := "Spam in quarantine SHOULD be retained for at least 30 days: non-default policies" - - Output := tests with input as { - "hosted_content_filter_policies": [ - { - "QuarantineRetentionPeriod": 30, - "Identity": "Custom 1" - }, - { - "QuarantineRetentionPeriod": 3, - "Identity": "Default" # This policy should be ignored - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_QuarantineRetentionPeriodCustom_Incorrect if { - ControlNumber := "Defender 2.6" - Requirement := "Spam in quarantine SHOULD be retained for at least 30 days: non-default policies" - - Output := tests with input as { - "hosted_content_filter_policies": [ - { - "QuarantineRetentionPeriod": 30, - "Identity": "Custom 1" - }, - { - "QuarantineRetentionPeriod": 29, - "Identity": "Custom 2" - }, - { - "QuarantineRetentionPeriod": 3, - "Identity": "Default" # This policy should be ignored - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "1 custom anti-spam policy(ies) found where spam in quarantine isn't retained for 30 days: Custom 2" -} - -# -# Policy 6 -#-- -test_InlineSafetyTipsEnabled_Correct if { - ControlNumber := "Defender 2.6" - Requirement := "Spam safety tips SHOULD be turned on: default policy" - - Output := tests with input as { - "hosted_content_filter_policies": [ - { - "InlineSafetyTipsEnabled": true, - "Identity": "Default" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_InlineSafetyTipsEnabled_Incorrect if { - ControlNumber := "Defender 2.6" - Requirement := "Spam safety tips SHOULD be turned on: default policy" - - Output := tests with input as { - "hosted_content_filter_policies": [ - { - "InlineSafetyTipsEnabled": false, - "Identity": "Default" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement not met" -} - -test_InlineSafetyTipsEnabledCustom_Correct if { - ControlNumber := "Defender 2.6" - Requirement := "Spam safety tips SHOULD be turned on: non-default policies" - - Output := tests with input as { - "hosted_content_filter_policies": [ - { - "InlineSafetyTipsEnabled": false, - "Identity": "Default" # should be ignored - }, - { - "InlineSafetyTipsEnabled": true, - "Identity": "Custom 1" - }, - { - "InlineSafetyTipsEnabled": true, - "Identity": "Custom 2" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_InlineSafetyTipsEnabledCustom_Incorrect if { - ControlNumber := "Defender 2.6" - Requirement := "Spam safety tips SHOULD be turned on: non-default policies" - - Output := tests with input as { - "hosted_content_filter_policies": [ - { - "InlineSafetyTipsEnabled": false, - "Identity": "Default" # should be ignored - }, - { - "InlineSafetyTipsEnabled": false, - "Identity": "Custom 1" - }, - { - "InlineSafetyTipsEnabled": true, - "Identity": "Custom 2" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "1 custom anti-spam policy(ies) found where spam safety tips is disabled: Custom 1" -} - -# -# Policy 7 -#-- -test_ZapEnabled_Correct if { - ControlNumber := "Defender 2.6" - Requirement := "Zero-hour auto purge (ZAP) SHALL be enabled: default policy" - - Output := tests with input as { - "hosted_content_filter_policies": [ - { - "ZapEnabled": true, - "Identity": "Default" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_ZapEnabled_Incorrect if { - ControlNumber := "Defender 2.6" - Requirement := "Zero-hour auto purge (ZAP) SHALL be enabled: default policy" - - Output := tests with input as { - "hosted_content_filter_policies": [ - { - "ZapEnabled": false, - "Identity": "Default" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement not met" -} - -test_SpamZapEnabled_Correct if { - ControlNumber := "Defender 2.6" - Requirement := "Zero-hour auto purge (ZAP) SHALL be enabled for spam messages: default policy" - - Output := tests with input as { - "hosted_content_filter_policies": [ - { - "SpamZapEnabled": true, - "Identity": "Default" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_SpamZapEnabled_Incorrect if { - ControlNumber := "Defender 2.6" - Requirement := "Zero-hour auto purge (ZAP) SHALL be enabled for spam messages: default policy" - - Output := tests with input as { - "hosted_content_filter_policies": [ - { - "SpamZapEnabled": false, - "Identity": "Default" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement not met" -} - -test_PhishZapEnabled_Correct if { - ControlNumber := "Defender 2.6" - Requirement := "Zero-hour auto purge (ZAP) SHALL be enabled for phishing: default policy" - - Output := tests with input as { - "hosted_content_filter_policies": [ - { - "PhishZapEnabled": true, - "Identity": "Default" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_PhishZapEnabled_Incorrect if { - ControlNumber := "Defender 2.6" - Requirement := "Zero-hour auto purge (ZAP) SHALL be enabled for phishing: default policy" - - Output := tests with input as { - "hosted_content_filter_policies": [ - { - "PhishZapEnabled": false, - "Identity": "Default" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement not met" -} - -test_ZapEnabledCustom_Correct if { - ControlNumber := "Defender 2.6" - Requirement := "Zero-hour auto purge (ZAP) SHOULD be enabled: non-default" - - Output := tests with input as { - "hosted_content_filter_policies": [ - { - "ZapEnabled": true, - "Identity": "Not Default" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_ZapEnabledCustom_Incorrect if { - ControlNumber := "Defender 2.6" - Requirement := "Zero-hour auto purge (ZAP) SHOULD be enabled: non-default" - - Output := tests with input as { - "hosted_content_filter_policies": [ - { - "ZapEnabled": false, - "Identity": "Not Default" - }, - { - "ZapEnabled": false, - "Identity": "Default" # SHOULD be ignored - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "1 custom anti-spam policies found where Zero-hour auto purge is disabled: Not Default" -} - -test_SpamZapEnabled_Correct if { - ControlNumber := "Defender 2.6" - Requirement := "Zero-hour auto purge (ZAP) SHOULD be enabled for Spam: non-default" - - Output := tests with input as { - "hosted_content_filter_policies": [ - { - "SpamZapEnabled": true, - "Identity": "Not Default" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_SpamZapEnabledCustom_Incorrect if { - ControlNumber := "Defender 2.6" - Requirement := "Zero-hour auto purge (ZAP) SHOULD be enabled for Spam: non-default" - - Output := tests with input as { - "hosted_content_filter_policies": [ - { - "SpamZapEnabled": false, - "Identity": "Not Default" - }, - { - "SpamZapEnabled": false, # should be ignored - "Identity": "Default" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "1 custom anti-spam policies found where Zero-hour auto purge for spam is disabled: Not Default" -} - -test_PhishZapEnabledCustom_Correct if { - ControlNumber := "Defender 2.6" - Requirement := "Zero-hour auto purge (ZAP) SHOULD be enabled for phishing: non-default" - - Output := tests with input as { - "hosted_content_filter_policies": [ - { - "PhishZapEnabled": true, - "Identity": "Not Default" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_PhishZapEnabledCustom_Incorrect if { - ControlNumber := "Defender 2.6" - Requirement := "Zero-hour auto purge (ZAP) SHOULD be enabled for phishing: non-default" - - Output := tests with input as { - "hosted_content_filter_policies": [ - { - "PhishZapEnabled": false, - "Identity": "Not Default" - }, - { - "PhishZapEnabled": false, # should be ignored - "Identity": "Default" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "1 custom anti-spam policy(ies) found where Zero-hour auto purge for phishing is disabled: Not Default" -} - -# -# Policy 8 -#-- -test_AllowedSenderDomainsNotEmpty_Correct if { - ControlNumber := "Defender 2.6" - Requirement := "Allowed senders MAY be added but allowed domains SHALL NOT be added: default policy" - - Output := tests with input as { - "hosted_content_filter_policies": [ - { - "AllowedSenderDomains": [], - "Identity": "Default" - } - ] - } - - - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_AllowedSenderDomainsNotEmpty_Incorrect if { - ControlNumber := "Defender 2.6" - Requirement := "Allowed senders MAY be added but allowed domains SHALL NOT be added: default policy" - - Output := tests with input as { - "hosted_content_filter_policies": [ - { - "AllowedSenderDomains": [""], - "Identity": "Default" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "1 custom anti-spam policy(ies) found where there is at least one allowed sender domain: Default" -} - -test_AllowedSenderDomainsNotEmptyCustom_Correct if { - ControlNumber := "Defender 2.6" - Requirement := "Allowed senders MAY be added but allowed domains SHOULD NOT be added: non-default" - - Output := tests with input as { - "hosted_content_filter_policies": [ - { - "AllowedSenderDomains": [], - "Identity": "Not Default" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_AllowedSenderDomainsNotEmptyCustom_Incorrect if { - ControlNumber := "Defender 2.6" - Requirement := "Allowed senders MAY be added but allowed domains SHOULD NOT be added: non-default" - - Output := tests with input as { - "hosted_content_filter_policies": [ - { - "AllowedSenderDomains": [""], - "Identity": "Not Default" - }, - { - "AllowedSenderDomains": [""], - "Identity": "Default" - } - ] - } - - - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - print(RuleOutput) - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "1 custom policy(ies) found where there is at least one allowed sender domain: Not Default" -} \ No newline at end of file diff --git a/Testing/Unit/Rego/Defender/DefenderConfig2_07_test.rego b/Testing/Unit/Rego/Defender/DefenderConfig2_07_test.rego deleted file mode 100644 index c92e2e4399..0000000000 --- a/Testing/Unit/Rego/Defender/DefenderConfig2_07_test.rego +++ /dev/null @@ -1,1412 +0,0 @@ -package defender -import future.keywords - - -# -# Policy 1 -#-- -test_Domains_Correct if { - ControlNumber := "Defender 2.7" - Requirement := "The Safe Links Policy SHALL include all agency domains-and by extension-all users" - - Output := tests with input as { - "safe_links_rules" : [ - { - "RecipientDomainIs": ["Test Domain"], - "Identity" : "Test Policy Rule", - "SafeLinksPolicy": "Test Policy", - "State" : "Enabled" - } - ], - "all_domains" : [ - { - "DomainName" : "Test Domain" - } - ], - "defender_license" : true - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_DomainName_Incorrect_V1 if { - ControlNumber := "Defender 2.7" - Requirement := "The Safe Links Policy SHALL include all agency domains-and by extension-all users" - - Output := tests with input as { - "safe_links_rules" : [ - { - "RecipientDomainIs": [""], - "Identity" : "Test Policy", - "SafeLinksPolicy": "Test Policy", - "State" : "Enabled" - } - ], - "all_domains" : [ - { - "DomainName" : "Test Domain" - } - ], - "defender_license" : true - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "No policy found that applies to all domains: Test Domain" -} - -test_DomainName_Incorrect_V2 if { - ControlNumber := "Defender 2.7" - Requirement := "The Safe Links Policy SHALL include all agency domains-and by extension-all users" - - Output := tests with input as { - "safe_links_rules" : [ - { - "RecipientDomainIs": ["Test Domain2"], - "Identity" : "Test Policy", - "SafeLinksPolicy": "Test Policy", - "State" : "Enabled" - } - ], - "all_domains" : [ - { - "DomainName" : "Test Domain" - } - ], - "defender_license" : true - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "No policy found that applies to all domains: Test Domain" -} - -test_Domains_Incorrect_v3 if { - ControlNumber := "Defender 2.7" - Requirement := "The Safe Links Policy SHALL include all agency domains-and by extension-all users" - - Output := tests with input as { - "safe_links_rules" : [ - { - "RecipientDomainIs": ["Test Domain"], - "Identity" : "Test Policy", - "SafeLinksPolicy": "Test Policy", - "State" : "Disabled" - } - ], - "all_domains" : [ - { - "DomainName" : "Test Domain" - } - ], - "defender_license" : true - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "No policy found that applies to all domains: Test Domain" -} - -test_Domains_Incorrect_V4 if { - # If no defender license is present, the provider will output "safe_links_rules" - # and "safe_links_policies" as empty lists - ControlNumber := "Defender 2.7" - Requirement := "The Safe Links Policy SHALL include all agency domains-and by extension-all users" - - Output := tests with input as { - "safe_links_rules": [], - "safe_links_policies": [], - "all_domains" : [ - { - "DomainName" : "Test Domain" - } - ], - "defender_license" : false - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement not met **NOTE: Either you do not have sufficient permissions or your tenant does not have a license for Microsoft Defender for Office 365 Plan 1, which is required for this feature.**" -} - -# -# Policy 2 -#-- -test_EnableSafeLinksForEmail_Correct_V1 if { - ControlNumber := "Defender 2.7" - Requirement := "URL rewriting and malicious link click checking SHALL be enabled" - - Output := tests with input as { - "safe_links_rules": [ - { - "State" : "Enabled", - "SafeLinksPolicy": "a", - "Identity" : "a" - }, - { - "State" : "Enabled", - "SafeLinksPolicy": "b", - "Identity" : "b rule" - } - ], - "safe_links_policies": [ - { - "EnableSafeLinksForEmail" : true, - "Identity": "a" - }, - { - "EnableSafeLinksForEmail" : false, - "Identity": "b" - }, - ], - "defender_license" : true - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_EnableSafeLinksForEmail_Correct_V2 if { - ControlNumber := "Defender 2.7" - Requirement := "URL rewriting and malicious link click checking SHALL be enabled" - - Output := tests with input as { - "safe_links_rules": [ - { - "State" : "Enabled", - "SafeLinksPolicy": "b", - "Identity" : "a" - }, - { - "State" : "Disabled", - "SafeLinksPolicy": "b", - "Identity" : "b rule" - } - ], - "safe_links_policies": [ - { - "EnableSafeLinksForEmail" : true, - "Identity": "a" - }, - { - "EnableSafeLinksForEmail" : true, - "Identity": "b" - } - ], - "defender_license" : true - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_EnableSafeLinksForEmail_Incorrect_V1 if { - ControlNumber := "Defender 2.7" - Requirement := "URL rewriting and malicious link click checking SHALL be enabled" - - Output := tests with input as { - "safe_links_rules": [ - { - "Identity" : "Default Rule", - "SafeLinksPolicy": "Default", - "State" : "Enabled" - } - ], - "safe_links_policies": [ - { - "EnableSafeLinksForEmail" : false, - "Identity": "Default" - } - ], - "defender_license" : true - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement not met" -} - -test_EnableSafeLinksForEmail_Incorrect_V2 if { - ControlNumber := "Defender 2.7" - Requirement := "URL rewriting and malicious link click checking SHALL be enabled" - - Output := tests with input as { - "safe_links_rules": [ - { - "Identity" : "Default Rule", - "SafeLinksPolicy": "Default", - "State" : "Disabled" - } - ], - "safe_links_policies": [ - { - "EnableSafeLinksForEmail" : true, - "Identity": "Default" - } - ], - "defender_license" : true - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement not met" -} - -test_EnableSafeLinksForEmail_Incorrect_V3 if { - # If no defender license is present, the provider will output "safe_links_rules" - # and "safe_links_policies" as empty lists - ControlNumber := "Defender 2.7" - Requirement := "URL rewriting and malicious link click checking SHALL be enabled" - - Output := tests with input as { - "safe_links_rules" : [], - "safe_links_policies" : [], - "defender_license" : false - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement not met **NOTE: Either you do not have sufficient permissions or your tenant does not have a license for Microsoft Defender for Office 365 Plan 1, which is required for this feature.**" -} - -# -# Policy 3 -#-- -test_EnableSafeLinksForTeams_Correct_V1 if { - ControlNumber := "Defender 2.7" - Requirement := "Malicious link click checking SHALL be enabled with Microsoft Teams" - - Output := tests with input as { - "safe_links_rules": [ - { - "State" : "Enabled", - "SafeLinksPolicy": "a", - "Identity" : "a rule" - }, - { - "State" : "Enabled", - "SafeLinksPolicy": "b", - "Identity" : "a" - } - ], - "safe_links_policies": [ - { - "EnableSafeLinksForTeams" : true, - "Identity": "a" - }, - { - "EnableSafeLinksForTeams" : false, - "Identity": "b" - } - ], - "defender_license" : true - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_EnableSafeLinksForTeams_Correct_V2 if { - ControlNumber := "Defender 2.7" - Requirement := "Malicious link click checking SHALL be enabled with Microsoft Teams" - - Output := tests with input as { - "safe_links_rules": [ - { - "State" : "Disabled", - "Identity" : "a", - "SafeLinksPolicy": "a" - }, - { - "State" : "Enabled", - "Identity" : "b rule", - "SafeLinksPolicy": "b" - } - ], - "safe_links_policies": [ - { - "EnableSafeLinksForTeams" : true, - "Identity": "a" - }, - { - "EnableSafeLinksForTeams" : true, - "Identity": "b" - } - ], - "defender_license" : true - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_EnableSafeLinksForTeams_Incorrect_V1 if { - ControlNumber := "Defender 2.7" - Requirement := "Malicious link click checking SHALL be enabled with Microsoft Teams" - - Output := tests with input as { - "safe_links_rules": [ - { - "Identity" : "Default", - "SafeLinksPolicy": "Default", - "State" : "Enabled" - } - ], - "safe_links_policies": [ - { - "EnableSafeLinksForTeams" : false, - "Identity": "Default" - } - ], - "defender_license" : true - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement not met" -} - -test_EnableSafeLinksForTeams_Incorrect_V2 if { - ControlNumber := "Defender 2.7" - Requirement := "Malicious link click checking SHALL be enabled with Microsoft Teams" - - Output := tests with input as { - "safe_links_rules": [ - { - "Identity" : "Default", - "SafeLinksPolicy": "Default", - "State" : "Disabled" - } - ], - "safe_links_policies": [ - { - "EnableSafeLinksForTeams" : false, - "Identity": "Default" - } - ], - "defender_license" : true - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement not met" -} - -test_EnableSafeLinksForTeams_Incorrect_V3 if { - # If no defender license is present, the provider will output "safe_links_rules" - # and "safe_links_policies" as empty lists - ControlNumber := "Defender 2.7" - Requirement := "Malicious link click checking SHALL be enabled with Microsoft Teams" - - Output := tests with input as { - "safe_links_rules" : [], - "safe_links_policies" : [], - "defender_license" : false - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement not met **NOTE: Either you do not have sufficient permissions or your tenant does not have a license for Microsoft Defender for Office 365 Plan 1, which is required for this feature.**" -} - -# -# Policy 4 -#-- -test_ScanUrls_Correct_V1 if { - ControlNumber := "Defender 2.7" - Requirement := "Real-time suspicious URL and file-link scanning SHALL be enabled" - - Output := tests with input as { - "safe_links_rules": [ - { - "State" : "Enabled", - "SafeLinksPolicy": "a", - "Identity" : "a" - }, - { - "State" : "Enabled", - "SafeLinksPolicy": "b", - "Identity" : "b" - } - ], - "safe_links_policies": [ - { - "ScanUrls" : false, - "Identity": "a" - }, - { - "ScanUrls" : true, - "Identity": "b" - } - ], - "defender_license" : true - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_ScanUrls_Correct_V2 if { - ControlNumber := "Defender 2.7" - Requirement := "Real-time suspicious URL and file-link scanning SHALL be enabled" - - Output := tests with input as { - "safe_links_rules": [ - { - "State" : "Disabled", - "SafeLinksPolicy": "a", - "Identity" : "a" - }, - { - "State" : "Enabled", - "SafeLinksPolicy": "b", - "Identity" : "b" - } - ], - "safe_links_policies": [ - { - "ScanUrls" : true, - "Identity": "a" - }, - { - "ScanUrls" : true, - "Identity": "b" - } - ], - "defender_license" : true - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_ScanUrls_Incorrect_V1 if { - ControlNumber := "Defender 2.7" - Requirement := "Real-time suspicious URL and file-link scanning SHALL be enabled" - - Output := tests with input as { - "safe_links_rules": [ - { - "Identity" : "Default", - "SafeLinksPolicy": "Default", - "State" : "Enabled" - } - ], - "safe_links_policies": [ - { - "ScanUrls" : false, - "Identity": "Default" - } - ], - "defender_license" : true - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement not met" -} - -test_ScanUrls_Incorrect_V2 if { - ControlNumber := "Defender 2.7" - Requirement := "Real-time suspicious URL and file-link scanning SHALL be enabled" - - Output := tests with input as { - "safe_links_rules": [ - { - "Identity" : "Default", - "SafeLinksPolicy": "Default", - "State" : "Disabled" - } - ], - "safe_links_policies": [ - { - "ScanUrls" : false, - "Identity": "Default" - } - ], - "defender_license" : true - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement not met" -} - -test_ScanUrls_Incorrect_V3 if { - # If no defender license is present, the provider will output "safe_links_rules" - # and "safe_links_policies" as empty lists - ControlNumber := "Defender 2.7" - Requirement := "Real-time suspicious URL and file-link scanning SHALL be enabled" - - Output := tests with input as { - "safe_links_rules" : [], - "safe_links_policies" : [], - "defender_license" : false - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement not met **NOTE: Either you do not have sufficient permissions or your tenant does not have a license for Microsoft Defender for Office 365 Plan 1, which is required for this feature.**" -} - -# -# Policy 5 -#-- -test_DeliverMessageAfterScan_Correct_V1 if { - ControlNumber := "Defender 2.7" - Requirement := "URLs SHALL be scanned completely before message delivery" - - Output := tests with input as { - "safe_links_rules": [ - { - "State" : "Enabled", - "SafeLinksPolicy": "a", - "Identity" : "a rule" - }, - { - "State" : "Enabled", - "SafeLinksPolicy": "b", - "Identity" : "b" - } - ], - "safe_links_policies": [ - { - "DeliverMessageAfterScan" : true, - "Identity": "a" - }, - { - "DeliverMessageAfterScan" : false, - "Identity": "b" - } - ], - "defender_license" : true - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_DeliverMessageAfterScan_Correct_V2 if { - ControlNumber := "Defender 2.7" - Requirement := "URLs SHALL be scanned completely before message delivery" - - Output := tests with input as { - "safe_links_rules": [ - { - "State" : "Enabled", - "SafeLinksPolicy": "a", - "Identity" : "a" - }, - { - "State" : "Disabled", - "SafeLinksPolicy": "b", - "Identity" : "b rule" - } - ], - "safe_links_policies": [ - { - "DeliverMessageAfterScan" : true, - "Identity": "a" - }, - { - "DeliverMessageAfterScan" : true, - "Identity": "b" - } - ], - "defender_license" : true - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_DeliverMessageAfterScan_Incorrect_V1 if { - ControlNumber := "Defender 2.7" - Requirement := "URLs SHALL be scanned completely before message delivery" - - Output := tests with input as { - "safe_links_rules": [ - { - "Identity" : "Default", - "SafeLinksPolicy": "Default", - "State" : "Enabled" - } - ], - "safe_links_policies": [ - { - "DeliverMessageAfterScan" : false, - "Identity": "Default" - } - ], - "defender_license" : true - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement not met" -} - -test_DeliverMessageAfterScan_Incorrect_V2 if { - ControlNumber := "Defender 2.7" - Requirement := "URLs SHALL be scanned completely before message delivery" - - Output := tests with input as { - "safe_links_rules": [ - { - "Identity" : "Default", - "SafeLinksPolicy": "Default", - "State" : "Disabled" - } - ], - "safe_links_policies": [ - { - "DeliverMessageAfterScan" : false, - "Identity": "Default" - } - ], - "defender_license" : true - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement not met" -} - -test_DeliverMessageAfterScan_Incorrect_V3 if { - # If no defender license is present, the provider will output "safe_links_rules" - # and "safe_links_policies" as empty lists - ControlNumber := "Defender 2.7" - Requirement := "URLs SHALL be scanned completely before message delivery" - - Output := tests with input as { - "safe_links_rules" : [], - "safe_links_policies" : [], - "defender_license" : false - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement not met **NOTE: Either you do not have sufficient permissions or your tenant does not have a license for Microsoft Defender for Office 365 Plan 1, which is required for this feature.**" -} - -# -# Policy 6 -#-- -test_EnableForInternalSenders_Correct_V1 if { - ControlNumber := "Defender 2.7" - Requirement := "Internal agency email messages SHALL have safe links enabled" - - Output := tests with input as { - "safe_links_rules": [ - { - "State" : "Enabled", - "SafeLinksPolicy": "a", - "Identity" : "a" - }, - { - "State" : "Enabled", - "SafeLinksPolicy": "b", - "Identity" : "b" - } - ], - "safe_links_policies": [ - { - "Identity" : "a", - "EnableForInternalSenders" : false - }, - { - "Identity" : "b", - "EnableForInternalSenders" : true - } - ], - "defender_license" : true - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_EnableForInternalSenders_Correct_V2 if { - ControlNumber := "Defender 2.7" - Requirement := "Internal agency email messages SHALL have safe links enabled" - - Output := tests with input as { - "safe_links_rules": [ - { - "State" : "Disabled", - "SafeLinksPolicy": "a", - "Identity" : "a" - }, - { - "State" : "Enabled", - "SafeLinksPolicy": "b", - "Identity" : "b rule" - } - ], - "safe_links_policies": [ - { - "Identity" : "a", - "EnableForInternalSenders" : true - }, - { - "Identity" : "b", - "EnableForInternalSenders" : true - } - ], - "defender_license" : true - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_EnableForInternalSenders_Incorrect_V1 if { - ControlNumber := "Defender 2.7" - Requirement := "Internal agency email messages SHALL have safe links enabled" - - Output := tests with input as { - "safe_links_rules": [ - { - "Identity" : "Default", - "SafeLinksPolicy": "Default", - "State" : "Enabled" - } - ], - "safe_links_policies": [ - { - "Identity" : "Not Built-in Protection Policy", - "EnableForInternalSenders" : false - } - ], - "defender_license" : true - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement not met" -} - -test_EnableForInternalSenders_Incorrect_V2 if { - ControlNumber := "Defender 2.7" - Requirement := "Internal agency email messages SHALL have safe links enabled" - - Output := tests with input as { - "safe_links_rules": [ - { - "Identity" : "Default", - "SafeLinksPolicy": "Default", - "State" : "Disabled" - } - ], - "safe_links_policies": [ - { - "Identity" : "Not Built-in Protection Policy", - "EnableForInternalSenders" : false - } - ], - "defender_license" : true - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement not met" -} - -test_EnableForInternalSenders_Incorrect_V3 if { - # If no defender license is present, the provider will output "safe_links_rules" - # and "safe_links_policies" as empty lists - ControlNumber := "Defender 2.7" - Requirement := "Internal agency email messages SHALL have safe links enabled" - - Output := tests with input as { - "safe_links_rules" : [], - "safe_links_policies" : [], - "defender_license" : false - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement not met **NOTE: Either you do not have sufficient permissions or your tenant does not have a license for Microsoft Defender for Office 365 Plan 1, which is required for this feature.**" -} - -# -# Policy 7 -#-- -test_TrackClicks_Correct_V1 if { - ControlNumber := "Defender 2.7" - Requirement := "User click tracking SHALL be enabled" - - Output := tests with input as { - "safe_links_rules": [ - { - "State" : "Enabled", - "SafeLinksPolicy": "a", - "Identity" : "a" - }, - { - "State" : "Enabled", - "SafeLinksPolicy": "b", - "Identity" : "b" - } - ], - "safe_links_policies": [ - { - "TrackClicks" : false, - "Identity": "a" - }, - { - "TrackClicks" : true, - "Identity": "b" - } - ], - "defender_license" : true - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_TrackClicks_Correct_V2 if { - ControlNumber := "Defender 2.7" - Requirement := "User click tracking SHALL be enabled" - - Output := tests with input as { - "safe_links_rules": [ - { - "State" : "Enabled", - "SafeLinksPolicy": "a", - "Identity" : "a" - }, - { - "State" : "Disabled", - "SafeLinksPolicy": "b", - "Identity" : "b" - } - ], - "safe_links_policies": [ - { - "TrackClicks" : true, - "Identity": "a" - }, - { - "TrackClicks" : true, - "Identity": "b" - } - ], - "defender_license" : true - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_TrackClicks_Incorrect_V1 if { - ControlNumber := "Defender 2.7" - Requirement := "User click tracking SHALL be enabled" - - Output := tests with input as { - "safe_links_rules": [ - { - "Identity" : "Default", - "State" : "Enabled", - "SafeLinksPolicy": "Default" - } - ], - "safe_links_policies": [ - { - "TrackClicks" : false, - "Identity": "Default" - } - ], - "defender_license" : true - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement not met" -} - -test_TrackClicks_Incorrect_V2 if { - ControlNumber := "Defender 2.7" - Requirement := "User click tracking SHALL be enabled" - - Output := tests with input as { - "safe_links_rules": [ - { - "Identity" : "Default", - "State" : "Disabled", - "SafeLinksPolicy": "Default" - } - ], - "safe_links_policies": [ - { - "TrackClicks" : false, - "Identity": "Default" - } - ], - "defender_license" : true - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement not met" -} - -test_TrackClicks_Incorrect_V3 if { - # If no defender license is present, the provider will output "safe_links_rules" - # and "safe_links_policies" as empty lists - ControlNumber := "Defender 2.7" - Requirement := "User click tracking SHALL be enabled" - - Output := tests with input as { - "safe_links_rules" : [], - "safe_links_policies" : [], - "defender_license" : false - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement not met **NOTE: Either you do not have sufficient permissions or your tenant does not have a license for Microsoft Defender for Office 365 Plan 1, which is required for this feature.**" -} - -# -# Policy 8 -#-- -test_EnableSafeLinksForOffice_Correct_V1 if { - ControlNumber := "Defender 2.7" - Requirement := "Safe Links in Office 365 apps SHALL be turned on" - - Output := tests with input as { - "safe_links_rules": [ - { - "Identity" : "a rule", - "SafeLinksPolicy": "a", - "State" : "Enabled" - }, - { - "Identity" : "b", - "SafeLinksPolicy": "b", - "State" : "Enabled" - } - ], - "safe_links_policies": [ - { - "EnableSafeLinksForOffice" : true, - "Identity" : "a" - }, - { - # Only one policy needs to be true. - "EnableSafeLinksForOffice" : false, - "Identity" : "b" - } - ], - "defender_license" : true - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_EnableSafeLinksForOffice_Correct_V2 if { - ControlNumber := "Defender 2.7" - Requirement := "Safe Links in Office 365 apps SHALL be turned on" - - Output := tests with input as { - "safe_links_rules": [ - { - "Identity" : "a rule", - "SafeLinksPolicy": "a", - "State" : "Enabled" - }, - { - # Only one policy needs to be true. - "Identity" : "b", - "SafeLinksPolicy": "b", - "State" : "Disabled" - } - ], - "safe_links_policies": [ - { - "EnableSafeLinksForOffice" : true, - "Identity" : "a" - }, - { - "EnableSafeLinksForOffice" : true, - "Identity" : "b" - } - ], - "defender_license" : true - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_EnableSafeLinksForOffice_Incorrect_V1 if { - ControlNumber := "Defender 2.7" - Requirement := "Safe Links in Office 365 apps SHALL be turned on" - - Output := tests with input as { - "safe_links_rules": [ - { - "State" : "Disabled", - "SafeLinksPolicy": "a", - "Identity" : "a" - } - ], - "safe_links_policies": [ - { - "EnableSafeLinksForOffice" : false, - "Identity" : "a" - } - ], - "defender_license" : true - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement not met" -} - -test_EnableSafeLinksForOffice_Incorrect_V2 if { - ControlNumber := "Defender 2.7" - Requirement := "Safe Links in Office 365 apps SHALL be turned on" - - Output := tests with input as { - "safe_links_rules": [ - { - "State" : "Disabled", - "SafeLinksPolicy": "a", - "Identity" : "a" - } - ], - "safe_links_policies": [ - { - "EnableSafeLinksForOffice" : true, - "Identity" : "a" - } - ], - "defender_license" : true - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement not met" -} - -test_EnableSafeLinksForOffice_Incorrect_V3 if { - ControlNumber := "Defender 2.7" - Requirement := "Safe Links in Office 365 apps SHALL be turned on" - - Output := tests with input as { - "safe_links_rules": [ - { - "State" : "Enabled", - "SafeLinksPolicy": "a", - "Identity" : "a" - } - ], - "safe_links_policies": [ - { - "EnableSafeLinksForOffice" : false, - "Identity" : "a" - } - ], - "defender_license" : true - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement not met" -} - -test_EnableSafeLinksForOffice_Incorrect_V4 if { - # If no defender license is present, the provider will output "safe_links_rules" - # and "safe_links_policies" as empty lists - ControlNumber := "Defender 2.7" - Requirement := "Safe Links in Office 365 apps SHALL be turned on" - - Output := tests with input as { - "safe_links_rules" : [], - "safe_links_policies" : [], - "defender_license" : false - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement not met **NOTE: Either you do not have sufficient permissions or your tenant does not have a license for Microsoft Defender for Office 365 Plan 1, which is required for this feature.**" -} - -# -# Policy 9 -#-- -test_AllowClickThrough_Correct_V1 if { - ControlNumber := "Defender 2.7" - Requirement := "Users SHALL NOT be enabled to click through to the original URL" - - Output := tests with input as { - "safe_links_rules": [ - { - "State" : "Enabled", - "SafeLinksPolicy": "a", - "Identity" : "a rule" - }, - { - "State" : "Enabled", - "SafeLinksPolicy": "b", - "Identity" : "b" - } - ], - "safe_links_policies": [ - { - "AllowClickThrough" : false, - "Identity" : "a" - }, - { - "AllowClickThrough" : true, - "Identity" : "b" - } - ], - "defender_license" : true - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_AllowClickThrough_Correct_V2 if { - ControlNumber := "Defender 2.7" - Requirement := "Users SHALL NOT be enabled to click through to the original URL" - - Output := tests with input as { - "safe_links_rules": [ - { - "State" : "Enabled", - "SafeLinksPolicy": "a", - "Identity" : "a rule" - }, - { - "State" : "Disabled", - "SafeLinksPolicy": "b", - "Identity" : "b" - } - ], - "safe_links_policies": [ - { - "AllowClickThrough" : false, - "Identity" : "a" - }, - { - "AllowClickThrough" : false, - "Identity" : "b" - } - ], - "defender_license" : true - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_AllowClickThrough_Incorrect_V1 if { - ControlNumber := "Defender 2.7" - Requirement := "Users SHALL NOT be enabled to click through to the original URL" - - Output := tests with input as { - "safe_links_rules": [ - { - "State" : "Disabled", - "SafeLinksPolicy": "a", - "Identity" : "a" - } - ], - "safe_links_policies": [ - { - "AllowClickThrough" : true, - "Identity" : "a" - } - ], - "defender_license" : true - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement not met" -} - -test_AllowClickThrough_Incorrect_V2 if { - ControlNumber := "Defender 2.7" - Requirement := "Users SHALL NOT be enabled to click through to the original URL" - - Output := tests with input as { - "safe_links_rules": [ - { - "State" : "Disabled", - "SafeLinksPolicy": "a", - "Identity" : "a" - } - ], - "safe_links_policies": [ - { - "AllowClickThrough" : false, - "Identity" : "a" - } - ], - "defender_license" : true - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement not met" -} - -test_AllowClickThrough_Incorrect_V3 if { - ControlNumber := "Defender 2.7" - Requirement := "Users SHALL NOT be enabled to click through to the original URL" - - Output := tests with input as { - "safe_links_rules": [ - { - "State" : "Enabled", - "SafeLinksPolicy": "a", - "Identity" : "a" - } - ], - "safe_links_policies": [ - { - "AllowClickThrough" : true, - "Identity" : "a" - } - ], - "defender_license" : true - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement not met" -} - -test_AllowClickThrough_Incorrect_V4 if { - # If no defender license is present, the provider will output "safe_links_rules" - # and "safe_links_policies" as empty lists - ControlNumber := "Defender 2.7" - Requirement := "Users SHALL NOT be enabled to click through to the original URL" - - Output := tests with input as { - "safe_links_rules" : [], - "safe_links_policies" : [], - "defender_license" : false - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement not met **NOTE: Either you do not have sufficient permissions or your tenant does not have a license for Microsoft Defender for Office 365 Plan 1, which is required for this feature.**" -} diff --git a/Testing/Unit/Rego/Defender/DefenderConfig2_08_test.rego b/Testing/Unit/Rego/Defender/DefenderConfig2_08_test.rego deleted file mode 100644 index 237657a8eb..0000000000 --- a/Testing/Unit/Rego/Defender/DefenderConfig2_08_test.rego +++ /dev/null @@ -1,466 +0,0 @@ -package defender -import future.keywords - - -# -# Policy 1 -#-- -test_Domains_Correct if { - ControlNumber := "Defender 2.8" - Requirement := "At least one Safe Attachments Policy SHALL include all agency domains-and by extension-all users" - - Output := tests with input as { - "safe_attachment_rules" : [ - { - "RecipientDomainIs": ["Test Domain"], - "SafeAttachmentPolicy": "Test Policy", - "Identity" : "Test Policy Rule" - } - ], - "all_domains" : [ - { - "DomainName" : "Test Domain" - } - ], - "defender_license" : true - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_DomainName_Incorrect_V1 if { - ControlNumber := "Defender 2.8" - Requirement := "At least one Safe Attachments Policy SHALL include all agency domains-and by extension-all users" - - Output := tests with input as { - "safe_attachment_rules" : [ - { - "RecipientDomainIs": [""], - "SafeAttachmentPolicy": "Test Policy", - "Identity" : "Test Policy Rule" - } - ], - "all_domains" : [ - { - "DomainName" : "Test Domain" - } - ], - "defender_license" : true - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "No policy found that applies to all domains: Test Domain" -} - -test_DomainName_Incorrect_V2 if { - ControlNumber := "Defender 2.8" - Requirement := "At least one Safe Attachments Policy SHALL include all agency domains-and by extension-all users" - - Output := tests with input as { - "safe_attachment_rules" : [ - { - "RecipientDomainIs": ["Test Domain2"], - "SafeAttachmentPolicy": "Test Policy", - "Identity" : "Test Policy Rule" - } - ], - "all_domains" : [ - { - "DomainName" : "Test Domain" - } - ], - "defender_license" : true - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "No policy found that applies to all domains: Test Domain" -} - -test_DomainName_Incorrect_V3 if { - # If no defender license is present, the provider will output "safe_attachment_rules" - # and "safe_attachment_policies" as empty lists - ControlNumber := "Defender 2.8" - Requirement := "At least one Safe Attachments Policy SHALL include all agency domains-and by extension-all users" - - Output := tests with input as { - "safe_attachment_rules" : [], - "all_domains" : [ - { - "DomainName" : "Test Domain" - } - ], - "safe_attachment_policies" : [], - "defender_license" : false - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement not met **NOTE: Either you do not have sufficient permissions or your tenant does not have a license for Microsoft Defender for Office 365 Plan 1, which is required for this feature.**" -} - -# -# Policy 2 -#-- -test_Action_Correct if { - ControlNumber := "Defender 2.8" - Requirement := "The action for malware in email attachments SHALL be set to block" - - Output := tests with input as { - "safe_attachment_rules": [ - { - "RecipientDomainIs": ["Test Domain"], - "SafeAttachmentPolicy": "Test Policy", - "Identity" : "Test Policy Rule" - } - ], - "all_domains" : [ - { - "DomainName" : "Test Domain" - } - ], - "safe_attachment_policies" : [ - { - "Action" : "Block", - "Enable" : true, - "RedirectAddress" : "127.0.0.1", - "Identity" : "Test Policy" - } - ], - "defender_license" : true - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_RecipientDomainIs_Incorrect_V1 if { - ControlNumber := "Defender 2.8" - Requirement := "The action for malware in email attachments SHALL be set to block" - - Output := tests with input as { - "safe_attachment_rules": [ - { - "RecipientDomainIs": [""], - "SafeAttachmentPolicy": "Test Policy", - "Identity" : "Test Policy" - } - ], - "all_domains" : [ - { - "DomainName" : "Test Domain" - } - ], - "safe_attachment_policies" : [ - { - "Action" : "Block", - "Enable" : true, - "RedirectAddress" : "127.0.0.1", - "Identity" : "Test Policy" - } - ], - "defender_license" : true - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "No enabled policy found with action set to block that apply to all domains" -} - -test_RecipientDomainIs_Incorrect_V2 if { - ControlNumber := "Defender 2.8" - Requirement := "The action for malware in email attachments SHALL be set to block" - - Output := tests with input as { - "safe_attachment_rules": [ - { - "RecipientDomainIs": ["Test Domain2"], - "SafeAttachmentPolicy": "Test Policy", - "Identity" : "Test Policy" - } - ], - "all_domains" : [ - { - "DomainName" : "Test Domain" - } - ], - "safe_attachment_policies" : [ - { - "Action" : "Block", - "Enable" : true, - "RedirectAddress" : "127.0.0.1", - "Identity" : "Test Policy" - } - ], - "defender_license" : true - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "No enabled policy found with action set to block that apply to all domains" -} - -test_Action_Incorrect_V1 if { - ControlNumber := "Defender 2.8" - Requirement := "The action for malware in email attachments SHALL be set to block" - - Output := tests with input as { - "safe_attachment_rules": [ - { - "RecipientDomainIs": ["Test Domain"], - "SafeAttachmentPolicy": "Test Policy", - "Identity" : "Test Policy" - } - ], - "all_domains" : [ - { - "DomainName" : "Test Domain" - } - ], - "safe_attachment_policies" : [ - { - "Action" : "Not Block", - "Enable" : true, - "RedirectAddress" : "127.0.0.1", - "Identity" : "Test Policy" - } - ], - "defender_license" : true - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "No enabled policy found with action set to block that apply to all domains" -} - -test_Action_Incorrect_V2 if { - # If no defender license is present, the provider will output "safe_attachment_rules" - # and "safe_attachment_policies" as empty lists - ControlNumber := "Defender 2.8" - Requirement := "The action for malware in email attachments SHALL be set to block" - - Output := tests with input as { - "safe_attachment_rules" : [], - "all_domains" : [ - { - "DomainName" : "Test Domain" - } - ], - "safe_attachment_policies" : [], - "defender_license" : false - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement not met **NOTE: Either you do not have sufficient permissions or your tenant does not have a license for Microsoft Defender for Office 365 Plan 1, which is required for this feature.**" -} - -test_Enable_Incorrect if { - ControlNumber := "Defender 2.8" - Requirement := "The action for malware in email attachments SHALL be set to block" - - Output := tests with input as { - "safe_attachment_rules": [ - { - "RecipientDomainIs": ["Test Domain"], - "SafeAttachmentPolicy": "Test Policy", - "Identity" : "Test Policy " - } - ], - "all_domains" : [ - { - "DomainName" : "Test Domain" - } - ], - "safe_attachment_policies" : [ - { - "Action" : "Block", - "Enable" : false, - "RedirectAddress" : "127.0.0.1", - "Identity" : "Test Policy" - } - ], - "defender_license" : true - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "No enabled policy found with action set to block that apply to all domains" -} - -test_Identity_Incorrect if { - ControlNumber := "Defender 2.8" - Requirement := "The action for malware in email attachments SHALL be set to block" - - Output := tests with input as { - "safe_attachment_rules": [ - { - "RecipientDomainIs": ["Test Domain"], - "SafeAttachmentPolicy": "Test Policy", - "Identity" : "Test Policy" - } - ], - "all_domains" : [ - { - "DomainName" : "Test Domain" - } - ], - "safe_attachment_policies" : [ - { - "Action" : "Block", - "Enable" : true, - "RedirectAddress" : "127.0.0.1", - "Identity" : "" - } - ], - "defender_license" : true - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "No enabled policy found with action set to block that apply to all domains" -} - -# -# Policy 3 -#-- -test_RedirectPolicies_Correct if { - ControlNumber := "Defender 2.8" - Requirement := "Redirect emails with detected attachments to an agency-specified email SHOULD be enabled" - - Output := tests with input as { - "safe_attachment_rules": [ - { - "RecipientDomainIs": ["Test Domain"], - "SafeAttachmentPolicy": "Test Policy", - "Identity" : "Test Policy Rule" - } - ], - "all_domains" : [ - { - "DomainName" : "Test Domain" - } - ], - "safe_attachment_policies" : [ - { - "Action" : "Block", - "Enable" : true, - "RedirectAddress" : "127.0.0.1", - "Identity" : "Test Policy" - } - ], - "defender_license" : true - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_RedirectAddress_Incorrect if { - ControlNumber := "Defender 2.8" - Requirement := "Redirect emails with detected attachments to an agency-specified email SHOULD be enabled" - - Output := tests with input as { - "safe_attachment_rules": [ - { - "RecipientDomainIs": ["Test Domain"], - "SafeAttachmentPolicy": "Test Policy", - "Identity" : "Test Policy Rule" - } - ], - "all_domains" : [ - { - "DomainName" : "Test Domain" - } - ], - "safe_attachment_policies" : [ - { - "Action" : "Block", - "Enable" : true, - "RedirectAddress" : "", - "Identity" : "Test Policy" - } - ], - "defender_license" : true - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "No enabled policy found with action set to block and at least one contact specified" -} - -# -# Policy 4 -#-- -test_Spot_Correct if { - ControlNumber := "Defender 2.8" - Requirement := "Safe attachments SHOULD be enabled for SharePoint, OneDrive, and Microsoft Teams" - - Output := tests with input as { - "atp_policy_for_o365" : [ - { - "EnableATPForSPOTeamsODB" : true, - "Identity" : "Default" - } - ], - "defender_license" : true - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_Spot_Incorrect if { - ControlNumber := "Defender 2.8" - Requirement := "Safe attachments SHOULD be enabled for SharePoint, OneDrive, and Microsoft Teams" - - Output := tests with input as { - "atp_policy_for_o365" : [ - { - "EnableATPForSPOTeamsODB" : false, - "Identity" : "Default" - } - ], - "defender_license" : true - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement not met" -} diff --git a/Testing/Unit/Rego/Defender/DefenderConfig2_09_test.rego b/Testing/Unit/Rego/Defender/DefenderConfig2_09_test.rego deleted file mode 100644 index 0fa1e3e6ca..0000000000 --- a/Testing/Unit/Rego/Defender/DefenderConfig2_09_test.rego +++ /dev/null @@ -1,233 +0,0 @@ -package defender -import future.keywords - - -# -# Policy 1 -#-- -test_Disabled_Correct if { - ControlNumber := "Defender 2.9" - Requirement := "At a minimum, the alerts required by the Exchange Online Minimum Viable Secure Configuration Baseline SHALL be enabled" - - Output := tests with input as { - "protection_alerts": [ - { - "Name": "Suspicious email sending patterns detected", - "Disabled": false - }, - { - "Name": "Unusual increase in email reported as phish", - "Disabled": false - }, - { - "Name": "Suspicious Email Forwarding Activity", - "Disabled": false - }, - { - "Name": "Messages have been delayed", - "Disabled": false - }, - { - "Name": "Tenant restricted from sending unprovisioned email", - "Disabled": false - }, - { - "Name": "User restricted from sending email", - "Disabled": false - }, - { - "Name": "Malware campaign detected after delivery", - "Disabled": false - }, - { - "Name": "A potentially malicious URL click was detected", - "Disabled": false - }, - { - "Name": "Suspicious connector activity", - "Disabled": false - }, - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_Disabled_Correct_V2 if { - # Test having extra alerts enabled that aren't required by the baseline - # SHOULDn't matter - ControlNumber := "Defender 2.9" - Requirement := "At a minimum, the alerts required by the Exchange Online Minimum Viable Secure Configuration Baseline SHALL be enabled" - - Output := tests with input as { - "protection_alerts": [ - { - "Name": "Suspicious email sending patterns detected", - "Disabled": false - }, - { - "Name": "Unusual increase in email reported as phish", - "Disabled": false - }, - { - "Name": "Suspicious Email Forwarding Activity", - "Disabled": false - }, - { - "Name": "Messages have been delayed", - "Disabled": false - }, - { - "Name": "Tenant restricted from sending unprovisioned email", - "Disabled": false - }, - { - "Name": "User restricted from sending email", - "Disabled": false - }, - { - "Name": "Malware campaign detected after delivery", - "Disabled": false - }, - { - "Name": "A potentially malicious URL click was detected", - "Disabled": false - }, - { - "Name": "Suspicious connector activity", - "Disabled": false - }, - { - "Name": "Successful exact data match upload", # Not required - "Disabled": false - }, - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_Disabled_Incorrect if { - ControlNumber := "Defender 2.9" - Requirement := "At a minimum, the alerts required by the Exchange Online Minimum Viable Secure Configuration Baseline SHALL be enabled" - - Output := tests with input as { - "protection_alerts": [ - { - "Name": "Suspicious email sending patterns detected", - "Disabled": true # SHOULD be false - }, - { - "Name": "Unusual increase in email reported as phish", - "Disabled": false - }, - { - "Name": "Suspicious Email Forwarding Activity", - "Disabled": false - }, - { - "Name": "Messages have been delayed", - "Disabled": false - }, - { - "Name": "Tenant restricted from sending unprovisioned email", - "Disabled": false - }, - { - "Name": "User restricted from sending email", - "Disabled": false - }, - { - "Name": "Malware campaign detected after delivery", - "Disabled": false - }, - { - "Name": "A potentially malicious URL click was detected", - "Disabled": false - }, - { - "Name": "Suspicious connector activity", - "Disabled": false - }, - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "1 disabled required alert(s) found: Suspicious email sending patterns detected" -} - -test_Disabled_Incorrect_V2 if { - # What happens if the alert is entirely missing instead of just disabled? - ControlNumber := "Defender 2.9" - Requirement := "At a minimum, the alerts required by the Exchange Online Minimum Viable Secure Configuration Baseline SHALL be enabled" - - Output := tests with input as { - "protection_alerts": [ - { - "Name": "Unusual increase in email reported as phish", - "Disabled": false - }, - { - "Name": "Suspicious Email Forwarding Activity", - "Disabled": false - }, - { - "Name": "Messages have been delayed", - "Disabled": false - }, - { - "Name": "Tenant restricted from sending unprovisioned email", - "Disabled": false - }, - { - "Name": "User restricted from sending email", - "Disabled": false - }, - { - "Name": "Malware campaign detected after delivery", - "Disabled": false - }, - { - "Name": "A potentially malicious URL click was detected", - "Disabled": false - }, - { - "Name": "Suspicious connector activity", - "Disabled": false - }, - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "1 disabled required alert(s) found: Suspicious email sending patterns detected" -} - -# -# Policy 2 -#-- -test_NotImplemented_Correct if { - ControlNumber := "Defender 2.9" - Requirement := "The alerts SHOULD be sent to a monitored address or incorporated into a SIEM" - - Output := tests with input as { } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Currently cannot be checked automatically. See Defender Secure Configuration Baseline policy 2.9 for instructions on manual check" -} \ No newline at end of file diff --git a/Testing/Unit/Rego/Defender/DefenderConfig2_10_test.rego b/Testing/Unit/Rego/Defender/DefenderConfig2_10_test.rego deleted file mode 100644 index d156d109cf..0000000000 --- a/Testing/Unit/Rego/Defender/DefenderConfig2_10_test.rego +++ /dev/null @@ -1,74 +0,0 @@ -package defender -import future.keywords - - -# -# Policy 1 -#-- -test_AdminAuditLogEnabled_Correct if { - ControlNumber := "Defender 2.10" - Requirement := "Unified audit logging SHALL be enabled" - - Output := tests with input as { - "admin_audit_log_config": [{ - "Identity": "Admin Audit Log Settings", - "UnifiedAuditLogIngestionEnabled" : true - }] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_AdminAuditLogEnabled_Incorrect if { - ControlNumber := "Defender 2.10" - Requirement := "Unified audit logging SHALL be enabled" - - Output := tests with input as { - "admin_audit_log_config": [{ - "Identity": "Admin Audit Log Settings", - "UnifiedAuditLogIngestionEnabled" : false - }] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement not met" -} - -# -# Policy 2 -#-- -test_NotImplemented_Correct_V1 if { - ControlNumber := "Defender 2.10" - Requirement := "Advanced audit SHALL be enabled" - - Output := tests with input as { } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Currently cannot be checked automatically. See Defender Secure Configuration Baseline policy 2.10 for instructions on manual check" -} - -# -# Policy 3 -#-- -test_NotImplemented_Correct_V2 if { - ControlNumber := "Defender 2.10" - Requirement := "Audit logs SHALL be maintained for at least the minimum duration dictated by OMB M-21-31" - - Output := tests with input as { } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Currently cannot be checked automatically. See Defender Secure Configuration Baseline policy 2.10 for instructions on manual check" -} diff --git a/Testing/Unit/Rego/Defender/DefenderConfig_01_test.rego b/Testing/Unit/Rego/Defender/DefenderConfig_01_test.rego new file mode 100644 index 0000000000..dc41a21a6c --- /dev/null +++ b/Testing/Unit/Rego/Defender/DefenderConfig_01_test.rego @@ -0,0 +1,113 @@ +package defender +import future.keywords + +# +# Policy 1 +#-- +test_Identity_Correct_V1 if { + PolicyId := "MS.DEFENDER.1.1v1" + + Output := tests with input as { + "protection_policy_rules" : [] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "Requirement met" +} + +test_Identity_Correct_V2 if { + PolicyId := "MS.DEFENDER.1.1v1" + + Output := tests with input as { + "protection_policy_rules" : [ + { + "Identity" : "Standard Preset Security Policy", + "State" : "Disabled" + } + ] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "Requirement met" +} + +test_Identity_Incorrect_V1 if { + PolicyId := "MS.DEFENDER.1.1v1" + + Output := tests with input as { + "protection_policy_rules" : [ + { + "Identity" : "Standard Preset Security Policy", + "State" : "Enabled" + } + ] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "The Standard Preset Security Policy is present and not disabled" +} + +# TODO: Policy Id needs to be resolved +# Policy 2 +#-- +# test_Identity_Correct_V1 if { +# PolicyId := "MS.DEFENDER.TBD" +# #Requirement := "Strict Preset security profiles SHOULD NOT be used" + +# Output := tests with input as { +# "protection_policy_rules" : [] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# TODO: Policy Id needs to be resolved +# test_Identity_Correct_V2 if { +# PolicyId := "MS.DEFENDER.TBD" +# #Requirement := "Strict Preset security profiles SHOULD NOT be used" + +# Output := tests with input as { +# "protection_policy_rules" : [ +# { +# "Identity" : "Strict Preset Security Policy", +# "State" : "Disabled" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# TODO: Policy Id needs to be resolved +# test_Identity_Incorrect_V2 if { +# PolicyId := "MS.DEFENDER.TBD" +# #Requirement := "Strict Preset security profiles SHOULD NOT be used" + +# Output := tests with input as { +# "protection_policy_rules" : [ +# { +# "Identity" : "Strict Preset Security Policy", +# "State" : "Enabled" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] +# } \ No newline at end of file diff --git a/Testing/Unit/Rego/Defender/DefenderConfig_02_test.rego b/Testing/Unit/Rego/Defender/DefenderConfig_02_test.rego new file mode 100644 index 0000000000..7bef12c662 --- /dev/null +++ b/Testing/Unit/Rego/Defender/DefenderConfig_02_test.rego @@ -0,0 +1,1031 @@ +package defender +import future.keywords + +# TODO: Policy Id(s) needs to be resolved + +# +# Policy 1 +#-- +# test_ContentContainsSensitiveInformation_Correct_V1 if { +# ControlNumber := "Defender 2.2" +# Requirement := "A custom policy SHALL be configured to protect PII and sensitive information, as defined by the agency: U.S. Social Security Number (SSN)" + +# Output := tests with input as { +# "dlp_compliance_rules": [ +# { +# "ContentContainsSensitiveInformation": [ +# {"name": "U.S. Social Security Number (SSN)"} +# ], +# "Name": "Baseline Rule", +# "Disabled" : false, +# "ParentPolicyName": "Default Office 365 DLP policy", +# "BlockAccess": true, +# "BlockAccessScope": "All", +# "NotifyUser": [ +# "SiteAdmin", +# "LastModifier", +# "Owner" +# ], +# "NotifyUserType": "NotSet" +# } +# ], +# "dlp_compliance_policies": [ +# { +# "Name": "Default Office 365 DLP policy", +# "Mode": "Enable", +# "Enabled": true +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_ContentContainsSensitiveInformation_Incorrect_V1 if { +# ControlNumber := "Defender 2.2" +# Requirement := "A custom policy SHALL be configured to protect PII and sensitive information, as defined by the agency: U.S. Social Security Number (SSN)" + +# Output := tests with input as { +# "dlp_compliance_rules": [ +# { +# "ContentContainsSensitiveInformation": [ +# {"name": "U.S. Individual Taxpayer Identification Number (ITIN)"}, +# {"name": "Credit Card Number"} +# ], +# "Name": "Baseline Rule", +# "Disabled" : false, +# "ParentPolicyName": "Default Office 365 DLP policy", +# "BlockAccess": true, +# "BlockAccessScope": "All", +# "NotifyUser": [ +# "SiteAdmin", +# "LastModifier", +# "Owner" +# ], +# "NotifyUserType": "NotSet" +# } +# ], +# "dlp_compliance_policies": [ +# { +# "Name": "Default Office 365 DLP policy", +# "Mode": "Enable", +# "Enabled": true +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "No matching rule found for U.S. Social Security Number (SSN)" +# } + +# test_ContentContainsSensitiveInformation_Correct_V2 if { +# ControlNumber := "Defender 2.2" +# Requirement := "A custom policy SHALL be configured to protect PII and sensitive information, as defined by the agency: U.S. Individual Taxpayer Identification Number (ITIN)" + +# Output := tests with input as { +# "dlp_compliance_rules": [ +# { +# "ContentContainsSensitiveInformation": [ +# {"name": "U.S. Individual Taxpayer Identification Number (ITIN)"} +# ], +# "Name": "Baseline Rule", +# "Disabled" : false, +# "ParentPolicyName": "Default Office 365 DLP policy", +# "BlockAccess": true, +# "BlockAccessScope": "All", +# "NotifyUser": [ +# "SiteAdmin", +# "LastModifier", +# "Owner" +# ], +# "NotifyUserType": "NotSet" +# } +# ], +# "dlp_compliance_policies": [ +# { +# "Name": "Default Office 365 DLP policy", +# "Mode": "Enable", +# "Enabled": true +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_ContentContainsSensitiveInformation_Incorrect_V2 if { +# ControlNumber := "Defender 2.2" +# Requirement := "A custom policy SHALL be configured to protect PII and sensitive information, as defined by the agency: U.S. Individual Taxpayer Identification Number (ITIN)" + +# Output := tests with input as { +# "dlp_compliance_rules": [ +# { +# "ContentContainsSensitiveInformation": [ +# {"name": "Credit Card Number"}, +# {"name": "U.S. Social Security Number (SSN)"} +# ], +# "Name": "Baseline Rule", +# "Disabled" : false, +# "ParentPolicyName": "Default Office 365 DLP policy", +# "BlockAccess": true, +# "BlockAccessScope": "All", +# "NotifyUser": [ +# "SiteAdmin", +# "LastModifier", +# "Owner" +# ], +# "NotifyUserType": "NotSet" +# } +# ], +# "dlp_compliance_policies": [ +# { +# "Name": "Default Office 365 DLP policy", +# "Mode": "Enable", +# "Enabled": true +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "No matching rule found for U.S. Individual Taxpayer Identification Number (ITIN)" +# } + +# test_ContentContainsSensitiveInformation_Correct_V3 if { +# ControlNumber := "Defender 2.2" +# Requirement := "A custom policy SHALL be configured to protect PII and sensitive information, as defined by the agency: Credit Card Number" + +# Output := tests with input as { +# "dlp_compliance_rules": [ +# { +# "ContentContainsSensitiveInformation": [ +# {"name": "Credit Card Number"} +# ], +# "Name": "Baseline Rule", +# "Disabled" : false, +# "ParentPolicyName": "Default Office 365 DLP policy", +# "BlockAccess": true, +# "BlockAccessScope": "All", +# "NotifyUser": [ +# "SiteAdmin", +# "LastModifier", +# "Owner" +# ], +# "NotifyUserType": "NotSet" +# } +# ], +# "dlp_compliance_policies": [ +# { +# "Name": "Default Office 365 DLP policy", +# "Mode": "Enable", +# "Enabled": true +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_ContentContainsSensitiveInformation_Incorrect_V3 if { +# ControlNumber := "Defender 2.2" +# Requirement := "A custom policy SHALL be configured to protect PII and sensitive information, as defined by the agency: Credit Card Number" + +# Output := tests with input as { +# "dlp_compliance_rules": [ +# { +# "ContentContainsSensitiveInformation": [ +# {"name": "U.S. Individual Taxpayer Identification Number (ITIN)"}, +# {"name": "U.S. Social Security Number (SSN)"} +# ], +# "Name": "Baseline Rule", +# "Disabled" : false, +# "ParentPolicyName": "Default Office 365 DLP policy", +# "BlockAccess": true, +# "BlockAccessScope": "All", +# "NotifyUser": [ +# "SiteAdmin", +# "LastModifier", +# "Owner" +# ], +# "NotifyUserType": "NotSet" +# } +# ], +# "dlp_compliance_policies": [ +# { +# "Name": "Default Office 365 DLP policy", +# "Mode": "Enable", +# "Enabled": true +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "No matching rule found for Credit Card Number" +# } + +# +# Policy 2 +#-- +# test_Exchange_Correct if { +# ControlNumber := "Defender 2.2" +# Requirement := "The custom policy SHOULD be applied in Exchange" + +# Output := tests with input as { +# "dlp_compliance_rules": [ +# { +# "ContentContainsSensitiveInformation": [ +# {"name": "U.S. Individual Taxpayer Identification Number (ITIN)"}, +# {"name": "Credit Card Number"}, +# {"name": "U.S. Social Security Number (SSN)"} +# ], +# "Name": "Baseline Rule", +# "Disabled" : false, +# "ParentPolicyName": "Default Office 365 DLP policy", +# "BlockAccess": true, +# "BlockAccessScope": "All", +# "NotifyUser": [ +# "SiteAdmin", +# "LastModifier", +# "Owner" +# ], +# "NotifyUserType": "NotSet" +# } +# ], +# "dlp_compliance_policies": [ +# { +# "ExchangeLocation": ["All"], +# "Workload": "Exchange", +# "Name": "Default Office 365 DLP policy", +# "Mode": "Enable", +# "Enabled": true +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_ExchangeLocation_Incorrect if { +# ControlNumber := "Defender 2.2" +# Requirement := "The custom policy SHOULD be applied in Exchange" + +# Output := tests with input as { +# "dlp_compliance_rules": [ +# { +# "ContentContainsSensitiveInformation": [ +# {"name": "U.S. Individual Taxpayer Identification Number (ITIN)"}, +# {"name": "Credit Card Number"}, +# {"name": "U.S. Social Security Number (SSN)"} +# ], +# "Name": "Baseline Rule", +# "Disabled" : false, +# "ParentPolicyName": "Default Office 365 DLP policy", +# "BlockAccess": true, +# "BlockAccessScope": "All", +# "NotifyUser": [ +# "SiteAdmin", +# "LastModifier", +# "Owner" +# ], +# "NotifyUserType": "NotSet" +# } +# ], +# "dlp_compliance_policies": [ +# { +# "ExchangeLocation": [""], +# "Workload": "Exchange", +# "Name": "Default Office 365 DLP policy", +# "Mode": "Enable", +# "Enabled": true +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "No policy found that applies to Exchange." +# } + +# test_Workload_Incorrect_V1 if { +# ControlNumber := "Defender 2.2" +# Requirement := "The custom policy SHOULD be applied in Exchange" + +# Output := tests with input as { +# "dlp_compliance_rules": [ +# { +# "ContentContainsSensitiveInformation": [ +# {"name": "U.S. Individual Taxpayer Identification Number (ITIN)"}, +# {"name": "Credit Card Number"}, +# {"name": "U.S. Social Security Number (SSN)"} +# ], +# "Name": "Baseline Rule", +# "Disabled" : false, +# "ParentPolicyName": "Default Office 365 DLP policy", +# "BlockAccess": true, +# "BlockAccessScope": "All", +# "NotifyUser": [ +# "SiteAdmin", +# "LastModifier", +# "Owner" +# ], +# "NotifyUserType": "NotSet" +# } +# ], +# "dlp_compliance_policies": [ +# { +# "ExchangeLocation": ["All"], +# "Workload": "", +# "Name": "Default Office 365 DLP policy", +# "Mode": "Enable", +# "Enabled": true +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "No policy found that applies to Exchange." +# } + +# test_SharePoint_Correct if { +# ControlNumber := "Defender 2.2" +# Requirement := "The custom policy SHOULD be applied in SharePoint" + +# Output := tests with input as { +# "dlp_compliance_rules": [ +# { +# "ContentContainsSensitiveInformation": [ +# {"name": "U.S. Individual Taxpayer Identification Number (ITIN)"}, +# {"name": "Credit Card Number"}, +# {"name": "U.S. Social Security Number (SSN)"} +# ], +# "Name": "Baseline Rule", +# "Disabled" : false, +# "ParentPolicyName": "Default Office 365 DLP policy", +# "BlockAccess": true, +# "BlockAccessScope": "All", +# "NotifyUser": [ +# "SiteAdmin", +# "LastModifier", +# "Owner" +# ], +# "NotifyUserType": "NotSet" +# } +# ], +# "dlp_compliance_policies": [ +# { +# "SharePointLocation": ["All"], +# "Workload": "SharePoint", +# "Name": "Default Office 365 DLP policy", +# "Mode": "Enable", +# "Enabled": true +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_SharePointLocation_Incorrect if { +# ControlNumber := "Defender 2.2" +# Requirement := "The custom policy SHOULD be applied in SharePoint" + +# Output := tests with input as { +# "dlp_compliance_rules": [ +# { +# "ContentContainsSensitiveInformation": [ +# {"name": "U.S. Individual Taxpayer Identification Number (ITIN)"}, +# {"name": "Credit Card Number"}, +# {"name": "U.S. Social Security Number (SSN)"} +# ], +# "Name": "Baseline Rule", +# "Disabled" : false, +# "ParentPolicyName": "Default Office 365 DLP policy", +# "BlockAccess": true, +# "BlockAccessScope": "All", +# "NotifyUser": [ +# "SiteAdmin", +# "LastModifier", +# "Owner" +# ], +# "NotifyUserType": "NotSet" +# } +# ], +# "dlp_compliance_policies": [ +# { +# "SharePointLocation": [""], +# "Workload": "SharePoint", +# "Name": "Default Office 365 DLP policy", +# "Mode": "Enable", +# "Enabled": true +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "No policy found that applies to SharePoint." +# } + +# test_Workload_Incorrect_V2 if { +# ControlNumber := "Defender 2.2" +# Requirement := "The custom policy SHOULD be applied in SharePoint" + +# Output := tests with input as { +# "dlp_compliance_rules": [ +# { +# "ContentContainsSensitiveInformation": [ +# {"name": "U.S. Individual Taxpayer Identification Number (ITIN)"}, +# {"name": "Credit Card Number"}, +# {"name": "U.S. Social Security Number (SSN)"} +# ], +# "Name": "Baseline Rule", +# "Disabled" : false, +# "ParentPolicyName": "Default Office 365 DLP policy", +# "BlockAccess": true, +# "BlockAccessScope": "All", +# "NotifyUser": [ +# "SiteAdmin", +# "LastModifier", +# "Owner" +# ], +# "NotifyUserType": "NotSet" +# } +# ], +# "dlp_compliance_policies": [ +# { +# "SharePointLocation": ["All"], +# "Workload": "", +# "Name": "Default Office 365 DLP policy", +# "Mode": "Enable", +# "Enabled": true +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "No policy found that applies to SharePoint." +# } + +# test_OneDrive_Correct if { +# ControlNumber := "Defender 2.2" +# Requirement := "The custom policy SHOULD be applied in OneDrive" + +# Output := tests with input as { +# "dlp_compliance_rules": [ +# { +# "ContentContainsSensitiveInformation": [ +# {"name": "U.S. Individual Taxpayer Identification Number (ITIN)"}, +# {"name": "Credit Card Number"}, +# {"name": "U.S. Social Security Number (SSN)"} +# ], +# "Name": "Baseline Rule", +# "Disabled" : false, +# "ParentPolicyName": "Default Office 365 DLP policy", +# "BlockAccess": true, +# "BlockAccessScope": "All", +# "NotifyUser": [ +# "SiteAdmin", +# "LastModifier", +# "Owner" +# ], +# "NotifyUserType": "NotSet" +# } +# ], +# "dlp_compliance_policies": [ +# { +# "OneDriveLocation": ["All"], +# "Workload": "OneDrivePoint", +# "Name": "Default Office 365 DLP policy", +# "Mode": "Enable", +# "Enabled": true +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_OneDriveLocation_Incorrect if { +# ControlNumber := "Defender 2.2" +# Requirement := "The custom policy SHOULD be applied in OneDrive" + +# Output := tests with input as { +# "dlp_compliance_rules": [ +# { +# "ContentContainsSensitiveInformation": [ +# {"name": "U.S. Individual Taxpayer Identification Number (ITIN)"}, +# {"name": "Credit Card Number"}, +# {"name": "U.S. Social Security Number (SSN)"} +# ], +# "Name": "Baseline Rule", +# "Disabled" : false, +# "ParentPolicyName": "Default Office 365 DLP policy", +# "BlockAccess": true, +# "BlockAccessScope": "All", +# "NotifyUser": [ +# "SiteAdmin", +# "LastModifier", +# "Owner" +# ], +# "NotifyUserType": "NotSet" +# } +# ], +# "dlp_compliance_policies": [ +# { +# "OneDriveLocation": [""], +# "Workload": "OneDrivePoint", +# "Name": "Default Office 365 DLP policy", +# "Mode": "Enable", +# "Enabled": true +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "No policy found that applies to OneDrive." +# } + +# test_Workload_Incorrect_V3 if { +# ControlNumber := "Defender 2.2" +# Requirement := "The custom policy SHOULD be applied in OneDrive" + +# Output := tests with input as { +# "dlp_compliance_rules": [ +# { +# "ContentContainsSensitiveInformation": [ +# {"name": "U.S. Individual Taxpayer Identification Number (ITIN)"}, +# {"name": "Credit Card Number"}, +# {"name": "U.S. Social Security Number (SSN)"} +# ], +# "Name": "Baseline Rule", +# "Disabled" : false, +# "ParentPolicyName": "Default Office 365 DLP policy", +# "BlockAccess": true, +# "BlockAccessScope": "All", +# "NotifyUser": [ +# "SiteAdmin", +# "LastModifier", +# "Owner" +# ], +# "NotifyUserType": "NotSet" +# } +# ], +# "dlp_compliance_policies": [ +# { +# "OneDriveLocation": ["All"], +# "Workload": "", +# "Name": "Default Office 365 DLP policy", +# "Mode": "Enable", +# "Enabled": true +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "No policy found that applies to OneDrive." +# } + +# test_Teams_Correct if { +# ControlNumber := "Defender 2.2" +# Requirement := "The custom policy SHOULD be applied in Teams" + +# Output := tests with input as { +# "dlp_compliance_rules": [ +# { +# "ContentContainsSensitiveInformation": [ +# {"name": "U.S. Individual Taxpayer Identification Number (ITIN)"}, +# {"name": "Credit Card Number"}, +# {"name": "U.S. Social Security Number (SSN)"} +# ], +# "Name": "Baseline Rule", +# "Disabled" : false, +# "ParentPolicyName": "Default Office 365 DLP policy", +# "BlockAccess": true, +# "BlockAccessScope": "All", +# "NotifyUser": [ +# "SiteAdmin", +# "LastModifier", +# "Owner" +# ], +# "NotifyUserType": "NotSet" +# } +# ], +# "dlp_compliance_policies": [ +# { +# "TeamsLocation": ["All"], +# "Workload": "Teams", +# "Name": "Default Office 365 DLP policy", +# "Mode": "Enable", +# "Enabled": true +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_TeamsLocation_Incorrect if { +# ControlNumber := "Defender 2.2" +# Requirement := "The custom policy SHOULD be applied in Teams" + +# Output := tests with input as { +# "dlp_compliance_rules": [ +# { +# "ContentContainsSensitiveInformation": [ +# {"name": "U.S. Individual Taxpayer Identification Number (ITIN)"}, +# {"name": "Credit Card Number"}, +# {"name": "U.S. Social Security Number (SSN)"} +# ], +# "Name": "Baseline Rule", +# "Disabled" : false, +# "ParentPolicyName": "Default Office 365 DLP policy", +# "BlockAccess": true, +# "BlockAccessScope": "All", +# "NotifyUser": [ +# "SiteAdmin", +# "LastModifier", +# "Owner" +# ], +# "NotifyUserType": "NotSet" +# } +# ], +# "dlp_compliance_policies": [ +# { +# "TeamsLocation": [""], +# "Workload": "Teams", +# "Name": "Default Office 365 DLP policy", +# "Mode": "Enable", +# "Enabled": true +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "No policy found that applies to Teams." +# } + +# test_Workload_Incorrect_V4 if { +# ControlNumber := "Defender 2.2" +# Requirement := "The custom policy SHOULD be applied in Teams" + +# Output := tests with input as { +# "dlp_compliance_rules": [ +# { +# "ContentContainsSensitiveInformation": [ +# {"name": "U.S. Individual Taxpayer Identification Number (ITIN)"}, +# {"name": "Credit Card Number"}, +# {"name": "U.S. Social Security Number (SSN)"} +# ], +# "Name": "Baseline Rule", +# "Disabled" : false, +# "ParentPolicyName": "Default Office 365 DLP policy", +# "BlockAccess": true, +# "BlockAccessScope": "All", +# "NotifyUser": [ +# "SiteAdmin", +# "LastModifier", +# "Owner" +# ], +# "NotifyUserType": "NotSet" +# } +# ], +# "dlp_compliance_policies": [ +# { +# "TeamsLocation": ["All"], +# "Workload": "", +# "Name": "Default Office 365 DLP policy", +# "Mode": "Enable", +# "Enabled": true +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "No policy found that applies to Teams." +# } + +# +# Policy 3 +#-- +# test_BlockAccess_Correct if { +# ControlNumber := "Defender 2.2" +# Requirement := "The action for the DLP policy SHOULD be set to block sharing sensitive information with everyone when DLP conditions are met" + +# Output := tests with input as { +# "dlp_compliance_rules": [ +# { +# "ContentContainsSensitiveInformation": [ +# {"name": "U.S. Individual Taxpayer Identification Number (ITIN)"} +# ], +# "Name": "Baseline Rule", +# "Disabled" : false, +# "ParentPolicyName": "Default Office 365 DLP policy", +# "BlockAccess": true, +# "BlockAccessScope": "All", +# "NotifyUser": [ +# "SiteAdmin", +# "LastModifier", +# "Owner" +# ], +# "NotifyUserType": "NotSet" +# } +# ], +# "dlp_compliance_policies": [ +# { +# "Name": "Default Office 365 DLP policy", +# "Mode": "Enable", +# "Enabled": true +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_BlockAccess_IncorrectV1 if { +# ControlNumber := "Defender 2.2" +# Requirement := "The action for the DLP policy SHOULD be set to block sharing sensitive information with everyone when DLP conditions are met" + +# Output := tests with input as { +# "dlp_compliance_rules": [ +# { +# "ContentContainsSensitiveInformation": [ +# {"name": "U.S. Individual Taxpayer Identification Number (ITIN)"} +# ], +# "Name": "Baseline Rule", +# "Disabled" : false, +# "ParentPolicyName": "Default Office 365 DLP policy", +# "BlockAccess": false, +# "BlockAccessScope": "All", +# "NotifyUser": [ +# "SiteAdmin", +# "LastModifier", +# "Owner" +# ], +# "NotifyUserType": "NotSet" +# } +# ], +# "dlp_compliance_policies": [ +# { +# "Name": "Default Office 365 DLP policy", +# "Mode": "Enable", +# "Enabled": true +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "1 rule(s) found that do(es) not block access or associated policy not set to enforce block action: Baseline Rule" +# } + +# test_BlockAccess_IncorrectV2 if { +# ControlNumber := "Defender 2.2" +# Requirement := "The action for the DLP policy SHOULD be set to block sharing sensitive information with everyone when DLP conditions are met" + +# Output := tests with input as { +# "dlp_compliance_rules": [ +# { +# "ContentContainsSensitiveInformation": [ +# {"name": "U.S. Individual Taxpayer Identification Number (ITIN)"} +# ], +# "Name": "Baseline Rule", +# "Disabled" : false, +# "ParentPolicyName": "Default Office 365 DLP policy", +# "BlockAccess": true, +# "BlockAccessScope": "All", +# "NotifyUser": [ +# "SiteAdmin", +# "LastModifier", +# "Owner" +# ], +# "NotifyUserType": "NotSet" +# } +# ], +# "dlp_compliance_policies": [ +# { +# "Name": "Default Office 365 DLP policy", +# "Mode": "TestWithNotifications", +# "Enabled": true +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "1 rule(s) found that do(es) not block access or associated policy not set to enforce block action: Baseline Rule" +# } + +# +# Policy 4 +#-- +# test_NotifyUser_Correct_V1 if { +# ControlNumber := "Defender 2.2" +# Requirement := "Notifications to inform users and help educate them on the proper use of sensitive information SHOULD be enabled" + +# Output := tests with input as { +# "dlp_compliance_rules": [ +# { +# "ContentContainsSensitiveInformation": [ +# {"name": "U.S. Individual Taxpayer Identification Number (ITIN)"} +# ], +# "Name": "Baseline Rule", +# "Disabled" : false, +# "ParentPolicyName": "Default Office 365 DLP policy", +# "BlockAccess": true, +# "BlockAccessScope": "All", +# "NotifyUser": [ +# "SiteAdmin" +# ], +# "NotifyUserType": "NotSet" +# } +# ], +# "dlp_compliance_policies": [ +# { +# "Name": "Default Office 365 DLP policy", +# "Mode": "Enable", +# "Enabled": true +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_NotifyUser_Correct_V2 if { +# ControlNumber := "Defender 2.2" +# Requirement := "Notifications to inform users and help educate them on the proper use of sensitive information SHOULD be enabled" + +# Output := tests with input as { +# "dlp_compliance_rules": [ +# { +# "ContentContainsSensitiveInformation": [ +# {"name": "U.S. Individual Taxpayer Identification Number (ITIN)"} +# ], +# "Name": "Baseline Rule", +# "Disabled" : false, +# "ParentPolicyName": "Default Office 365 DLP policy", +# "BlockAccess": true, +# "BlockAccessScope": "All", +# "NotifyUser": [ +# "SiteAdmin", +# "LastModifier", +# "Owner" +# ], +# "NotifyUserType": "NotSet" +# } +# ], +# "dlp_compliance_policies": [ +# { +# "Name": "Default Office 365 DLP policy", +# "Mode": "Enable", +# "Enabled": true +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_NotifyUser_Incorrect if { +# ControlNumber := "Defender 2.2" +# Requirement := "Notifications to inform users and help educate them on the proper use of sensitive information SHOULD be enabled" + +# Output := tests with input as { +# "dlp_compliance_rules": [ +# { +# "ContentContainsSensitiveInformation": [ +# {"name": "U.S. Individual Taxpayer Identification Number (ITIN)"} +# ], +# "Name": "Baseline Rule", +# "Disabled" : false, +# "ParentPolicyName": "Default Office 365 DLP policy", +# "BlockAccess": true, +# "BlockAccessScope": "All", +# "NotifyUser": [ ], +# "NotifyUserType": "NotSet" +# } +# ], +# "dlp_compliance_policies": [ +# { +# "Name": "Default Office 365 DLP policy", +# "Mode": "Enable", +# "Enabled": true +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "1 rule(s) found that do(es) not notify at least one user: Baseline Rule" +# } + +# +# Policy 5 +#-- +# test_NotImplemented_Correct_V1 if { +# ControlNumber := "Defender 2.2" +# PolicyId := "TBD" +# Requirement := "A list of apps that are not allowed to access files protected by DLP policy SHOULD be defined" + +# Output := tests with input as { } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == sprintf("Currently cannot be checked automatically. See Defender Secure Configuration Baseline policy %v for instructions on manual check", [PolicyId]) +# } + +# +# Policy 6 +#-- +# test_NotImplemented_Correct_V2 if { +# ControlNumber := "Defender 2.2" +# PolicyId := "TBD" +# Requirement := "A list of browsers that are not allowed to access files protected by DLP policy SHOULD be defined" + +# Output := tests with input as { } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == sprintf("Currently cannot be checked automatically. See Defender Secure Configuration Baseline policy %v for instructions on manual check", [PolicyId]) +# } \ No newline at end of file diff --git a/Testing/Unit/Rego/Defender/DefenderConfig_03_test.rego b/Testing/Unit/Rego/Defender/DefenderConfig_03_test.rego new file mode 100644 index 0000000000..a42b8713a1 --- /dev/null +++ b/Testing/Unit/Rego/Defender/DefenderConfig_03_test.rego @@ -0,0 +1,199 @@ +package defender +import future.keywords + +# TODO: Policy Id(s) needs to be resolved + +# +# Policy 1 +#-- +# test_EnableFileFilter_Correct if { +# ControlNumber := "Defender 2.3" +# Requirement := "The common attachments filter SHALL be enabled in the default anti-malware policy and in all existing policies" + +# Output := tests with input as { +# "malware_filter_policies": [ +# { +# "EnableFileFilter" : true, +# "Name": "Default" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_EnableFileFilter_Incorrect if { +# ControlNumber := "Defender 2.3" +# Requirement := "The common attachments filter SHALL be enabled in the default anti-malware policy and in all existing policies" + +# Output := tests with input as { +# "malware_filter_policies": [ +# { +# "EnableFileFilter" : false, +# "Name": "Default" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "1 malware policy(ies) found that do(es) not have the common attachments filter enabled: Default" +# } + +# test_EnableFileFilterMultiple_Incorrect if { +# ControlNumber := "Defender 2.3" +# Requirement := "The common attachments filter SHALL be enabled in the default anti-malware policy and in all existing policies" + +# Output := tests with input as { +# "malware_filter_policies": [ +# { +# "EnableFileFilter" : true, +# "Name": "Default" +# }, +# { +# "EnableFileFilter" : false, +# "Name": "Custom 1" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "1 malware policy(ies) found that do(es) not have the common attachments filter enabled: Custom 1" +# } + +# +# Policy 2 +#-- +# test_FileTypes_Correct_V1 if { +# ControlNumber := "Defender 2.3" +# Requirement := "Disallowed file types SHALL be determined and set. At a minimum, click-to-run files SHOULD be blocked: exe files" + +# Output := tests with input as { +# "malware_filter_policies": [ +# { +# "FileTypes" : ["exe"], +# "EnableFileFilter" : true, +# "Name": "Default" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_FileTypes_Incorrect_V1 if { +# ControlNumber := "Defender 2.3" +# Requirement := "Disallowed file types SHALL be determined and set. At a minimum, click-to-run files SHOULD be blocked: exe files" + +# Output := tests with input as { +# "malware_filter_policies": [ +# { +# "FileTypes" : ["cmd", "vbe"], +# "EnableFileFilter" : true, +# "Name": "Default" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "No malware policies found that block .exe files." +# } + +# test_FileTypes_Correct_V2 if { +# ControlNumber := "Defender 2.3" +# Requirement := "Disallowed file types SHALL be determined and set. At a minimum, click-to-run files SHOULD be blocked: cmd files" + +# Output := tests with input as { +# "malware_filter_policies": [ +# { +# "FileTypes" : ["cmd"], +# "EnableFileFilter" : true, +# "Name": "Default" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_FileTypes_Incorrect_V2 if { +# ControlNumber := "Defender 2.3" +# Requirement := "Disallowed file types SHALL be determined and set. At a minimum, click-to-run files SHOULD be blocked: cmd files" + +# Output := tests with input as { +# "malware_filter_policies": [ +# { +# "FileTypes" : ["exe", "vbe"], +# "EnableFileFilter" : true, +# "Name": "Default" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "No malware policies found that block .cmd files." +# } + +# test_FileTypes_Correct_V3 if { +# ControlNumber := "Defender 2.3" +# Requirement := "Disallowed file types SHALL be determined and set. At a minimum, click-to-run files SHOULD be blocked: vbe files" + +# Output := tests with input as { +# "malware_filter_policies": [ +# { +# "FileTypes" : ["vbe"], +# "EnableFileFilter" : true, +# "Name": "Default" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_FileTypes_Incorrect_V3 if { +# ControlNumber := "Defender 2.3" +# Requirement := "Disallowed file types SHALL be determined and set. At a minimum, click-to-run files SHOULD be blocked: vbe files" + +# Output := tests with input as { +# "malware_filter_policies": [ +# { +# "FileTypes" : ["exe", "cmd"], +# "EnableFileFilter" : true, +# "Name": "Default" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "No malware policies found that block .vbe files." +# } \ No newline at end of file diff --git a/Testing/Unit/Rego/Defender/DefenderConfig_04_test.rego b/Testing/Unit/Rego/Defender/DefenderConfig_04_test.rego new file mode 100644 index 0000000000..8174457b4f --- /dev/null +++ b/Testing/Unit/Rego/Defender/DefenderConfig_04_test.rego @@ -0,0 +1,71 @@ +package defender +import future.keywords + +# TODO: Policy Id(s) needs to be resolved + +# +# Policy 1 +#-- +# test_ZapEnabled_Correct if { +# ControlNumber := "Defender 2.4" +# Requirement := "Zero-hour Auto Purge (ZAP) for malware SHOULD be enabled in the default anti-malware policy and in all existing custom policies" + +# Output := tests with input as { +# "malware_filter_policies": [ +# { +# "ZapEnabled" : true, +# "Name": "Default" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_ZapEnabled_Incorrect if { +# ControlNumber := "Defender 2.4" +# Requirement := "Zero-hour Auto Purge (ZAP) for malware SHOULD be enabled in the default anti-malware policy and in all existing custom policies" + +# Output := tests with input as { +# "malware_filter_policies": [ +# { +# "ZapEnabled" : false, +# "Name": "Default" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "1 malware policy(ies) found without ZAP for malware enabled: Default" +# } + +# test_ZapEnabledMultiple_Incorrect if { +# ControlNumber := "Defender 2.4" +# Requirement := "Zero-hour Auto Purge (ZAP) for malware SHOULD be enabled in the default anti-malware policy and in all existing custom policies" + +# Output := tests with input as { +# "malware_filter_policies": [ +# { +# "ZapEnabled" : true, +# "Name": "Default" +# }, +# { +# "ZapEnabled" : false, +# "Name": "Custom 1" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "1 malware policy(ies) found without ZAP for malware enabled: Custom 1" +# } \ No newline at end of file diff --git a/Testing/Unit/Rego/Defender/DefenderConfig_05_test.rego b/Testing/Unit/Rego/Defender/DefenderConfig_05_test.rego new file mode 100644 index 0000000000..b63b54c3b6 --- /dev/null +++ b/Testing/Unit/Rego/Defender/DefenderConfig_05_test.rego @@ -0,0 +1,1378 @@ +package defender +import future.keywords + +# TODO: Policy Id(s) needs to be resolved + +# +# Policy 1 +#-- +# test_TargetedUsers_Correct if { +# ControlNumber := "Defender 2.5" +# Requirement := "User impersonation protection SHOULD be enabled for key agency leaders" + +# Output := tests with input as { +# "anti_phish_policies": [ +# { +# "Name" : "Standard Preset Security Policy1659535429826", +# "Enabled" : true, +# "EnableTargetedUserProtection" : true, +# "TargetedUsersToProtect" : [ +# "john doe;jdoe@someemail.com", +# "jane doe;jadoe@someemail.com" +# ], +# "TargetedUserProtectionAction": "Quarantine" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_Enabled_Incorrect if { +# ControlNumber := "Defender 2.5" +# Requirement := "User impersonation protection SHOULD be enabled for key agency leaders" + +# Output := tests with input as { +# "anti_phish_policies" : [ +# { +# "Name" : "Standard Preset Security Policy1659535429826", +# "Enabled" : false, +# "EnableTargetedUserProtection" : true, +# "TargetedUsersToProtect" : [ +# "john doe;jdoe@someemail.com", +# "jane doe;jadoe@someemail.com" +# ], +# "TargetedUserProtectionAction" : "Quarantine" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "No users are included for targeted user protection." +# } + +# test_EnableTargetedUserProtection_Incorrect if { +# ControlNumber := "Defender 2.5" +# Requirement := "User impersonation protection SHOULD be enabled for key agency leaders" + +# Output := tests with input as { +# "anti_phish_policies" : [ +# { +# "Name" : "Standard Preset Security Policy1659535429826", +# "Enabled" : true, +# "EnableTargetedUserProtection" : false, +# "TargetedUsersToProtect" : [ +# "john doe;jdoe@someemail.com", +# "jane doe;jadoe@someemail.com" +# ], +# "TargetedUserProtectionAction" : "Quarantine" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "No users are included for targeted user protection." +# } + +# test_TargetedUsersToProtect_Incorrect if { +# ControlNumber := "Defender 2.5" +# Requirement := "User impersonation protection SHOULD be enabled for key agency leaders" + +# Output := tests with input as { +# "anti_phish_policies" : [ +# { +# "Name" : "Standard Preset Security Policy1659535429826", +# "Enabled" : true, +# "EnableTargetedUserProtection" : true, +# "TargetedUsersToProtect" : [ ], +# "TargetedUserProtectionAction" : "Quarantine" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "No users are included for targeted user protection." +# } + +# +# Policy 2 +#-- +# test_OrganizationDomain_Correct if { +# ControlNumber := "Defender 2.5" +# Requirement := "Domain impersonation protection SHOULD be enabled for domains owned by the agency" + +# Output := tests with input as { +# "anti_phish_policies" : [ +# { +# "Name" : "Standard Preset Security Policy1659535429826", +# "Enabled" : true, +# "EnableOrganizationDomainsProtection" : true, +# "EnableTargetedDomainsProtection" : true, +# "TargetedDomainProtectionAction" : "Quarantine", +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_Enabled_Incorrect_V2 if { +# ControlNumber := "Defender 2.5" +# Requirement := "Domain impersonation protection SHOULD be enabled for domains owned by the agency" + +# Output := tests with input as { +# "anti_phish_policies" : [ +# { +# "Name" : "Standard Preset Security Policy1659535429826", +# "Enabled" : false, +# "EnableOrganizationDomainsProtection" : true, +# "EnableTargetedDomainsProtection" : true, +# "TargetedDomainProtectionAction" : "Quarantine", +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement not met" +# } + +# test_EnableOrganizationDomainsProtection_Incorrect if { +# ControlNumber := "Defender 2.5" +# Requirement := "Domain impersonation protection SHOULD be enabled for domains owned by the agency" + +# Output := tests with input as { +# "anti_phish_policies" : [ +# { +# "Name" : "Standard Preset Security Policy1659535429826", +# "Enabled" : true, +# "EnableOrganizationDomainsProtection" : false, +# "EnableTargetedDomainsProtection" : true, +# "TargetedDomainProtectionAction" : "Quarantine", +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement not met" +# } + +# test_EnableTargetedDomainsProtection_Incorrect if { +# ControlNumber := "Defender 2.5" +# Requirement := "Domain impersonation protection SHOULD be enabled for domains owned by the agency" + +# Output := tests with input as { +# "anti_phish_policies" : [ +# { +# "Name" : "Standard Preset Security Policy1659535429826", +# "Enabled" : true, +# "EnableOrganizationDomainsProtection" : true, +# "EnableTargetedDomainsProtection" : false, +# "TargetedDomainProtectionAction" : "Quarantine", +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement not met" +# } + +# +# Policy 3 +#-- +# test_CustomDomains_Correct if { +# ControlNumber := "Defender 2.5" +# Requirement := "Domain impersonation protection SHOULD be added for frequent partners" + +# Output := tests with input as { +# "anti_phish_policies" : [ +# { +# "Name" : "Standard Preset Security Policy1659535429826", +# "Enabled" : true, +# "EnableTargetedDomainsProtection" : true, +# "TargetedDomainsToProtect" : [ "test domain" ], +# "TargetedDomainProtectionAction" : "Quarantine" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_Enabled_Incorrect_V3 if { +# ControlNumber := "Defender 2.5" +# Requirement := "Domain impersonation protection SHOULD be added for frequent partners" + +# Output := tests with input as { +# "anti_phish_policies" : [ +# { +# "Name" : "Standard Preset Security Policy1659535429826", +# "Enabled" : false, +# "EnableTargetedDomainsProtection" : true, +# "TargetedDomainsToProtect" : [ "test domain" ], +# "TargetedDomainProtectionAction" : "Quarantine" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "The Custom Domains protection policies: Enabled, EnableTargetedDomainsProtection, and TargetedDomainsToProtect are not set correctly" +# } + +# test_EnableTargetedDomainsProtection_Incorrect if { +# ControlNumber := "Defender 2.5" +# Requirement := "Domain impersonation protection SHOULD be added for frequent partners" + +# Output := tests with input as { +# "anti_phish_policies" : [ +# { +# "Name" : "Standard Preset Security Policy1659535429826", +# "Enabled" : true, +# "EnableTargetedDomainsProtection" : false, +# "TargetedDomainsToProtect" : [ "test domain" ], +# "TargetedDomainProtectionAction" : "Quarantine" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "The Custom Domains protection policies: Enabled, EnableTargetedDomainsProtection, and TargetedDomainsToProtect are not set correctly" +# } + +# test_TargetedDomainsToProtect_Incorrect if { +# ControlNumber := "Defender 2.5" +# Requirement := "Domain impersonation protection SHOULD be added for frequent partners" + +# Output := tests with input as { +# "anti_phish_policies" : [ +# { +# "Name" : "Standard Preset Security Policy1659535429826", +# "Enabled" : true, +# "EnableTargetedDomainsProtection" : true, +# "TargetedDomainsToProtect" : [ ], +# "TargetedDomainProtectionAction" : "Quarantine" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "The Custom Domains protection policies: Enabled, EnableTargetedDomainsProtection, and TargetedDomainsToProtect are not set correctly" +# } + +# +# Policy 4 +#-- +# test_Email_Correct if { +# ControlNumber := "Defender 2.5" +# Requirement := "Intelligence for impersonation protection SHALL be enabled" + +# Output := tests with input as { +# "anti_phish_policies" : [ +# { +# "Name" : "Standard Preset Security Policy1659535429826", +# "Enabled" : true, +# "EnableMailboxIntelligenceProtection" : true, +# "MailboxIntelligenceProtectionAction" : "Quarantine" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_Enabled_Incorrect_V4 if { +# ControlNumber := "Defender 2.5" +# Requirement := "Intelligence for impersonation protection SHALL be enabled" + +# Output := tests with input as { +# "anti_phish_policies" : [ +# { +# "Name" : "Standard Preset Security Policy1659535429826", +# "Enabled" : false, +# "EnableMailboxIntelligenceProtection" : true, +# "MailboxIntelligenceProtectionAction" : "Quarantine" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement not met" +# } + +# test_EnableMailboxIntelligenceProtection_Incorrect if { +# ControlNumber := "Defender 2.5" +# Requirement := "Intelligence for impersonation protection SHALL be enabled" + +# Output := tests with input as { +# "anti_phish_policies" : [ +# { +# "Name" : "Standard Preset Security Policy1659535429826", +# "Enabled" : true, +# "EnableMailboxIntelligenceProtection" : false, +# "MailboxIntelligenceProtectionAction" : "Quarantine" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement not met" +# } + +# +# Policy 5 +#-- +# test_TargetedUserProtectionAction_Correct if { +# ControlNumber := "Defender 2.5" +# Requirement := "Message action SHALL be set to quarantine if the message is detected as impersonated: users default policy" + +# Output := tests with input as { +# "anti_phish_policies" : [ +# { +# "TargetedUserProtectionAction" : "Quarantine", +# "Identity" : "Office365 AntiPhish Default" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_TargetedUserProtectionAction_Incorrect if { +# ControlNumber := "Defender 2.5" +# Requirement := "Message action SHALL be set to quarantine if the message is detected as impersonated: users default policy" + +# Output := tests with input as { +# "anti_phish_policies" : [ +# { +# "TargetedUserProtectionAction" : "Not Quarantine", +# "Identity" : "Office365 AntiPhish Default" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement not met" +# } + +# test_TargetedUserProtectionActionCustom_Correct if { +# ControlNumber := "Defender 2.5" +# Requirement := "Message action SHOULD be set to quarantine if the message is detected as impersonated: users non-default policies" + +# Output := tests with input as { +# "anti_phish_policies" : [ +# { +# "TargetedUserProtectionAction" : "Quarantine", +# "Identity" : "Custom 1" +# }, +# { +# "TargetedUserProtectionAction" : "Not Quarantine", +# "Identity" : "Office365 AntiPhish Default" # The default policy should be ignored here +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_TargetedUserProtectionActionCustom_Incorrect if { +# ControlNumber := "Defender 2.5" +# Requirement := "Message action SHOULD be set to quarantine if the message is detected as impersonated: users non-default policies" + +# Output := tests with input as { +# "anti_phish_policies" : [ +# { +# "TargetedUserProtectionAction" : "Quarantine", +# "Identity" : "Custom 1" +# }, +# { +# "TargetedUserProtectionAction" : "Not Quarantine", +# "Identity" : "Custom 2" +# }, +# { +# "TargetedUserProtectionAction" : "Not Quarantine", +# "Identity" : "Office365 AntiPhish Default" # The default policy should be ignored here +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "1 non-default anti phish policy(ies) found where the action for messages detected as user impersonation is not quarantine: Custom 2" +# } + + +# test_TargetedDomainProtectionAction_Correct if { +# ControlNumber := "Defender 2.5" +# Requirement := "Message action SHALL be set to quarantine if the message is detected as impersonated: domains default policy" + +# Output := tests with input as { +# "anti_phish_policies" : [ +# { +# "TargetedDomainProtectionAction" : "Quarantine", +# "Identity" : "Office365 AntiPhish Default" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_TargetedDomainProtectionAction_Incorrect if { +# ControlNumber := "Defender 2.5" +# Requirement := "Message action SHALL be set to quarantine if the message is detected as impersonated: domains default policy" + +# Output := tests with input as { +# "anti_phish_policies" : [ +# { +# "TargetedDomainProtectionAction" : "Not Quarantine", +# "Identity" : "Office365 AntiPhish Default" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement not met" +# } + +# test_TargetedDomainProtectionActionCustom_Correct if { +# ControlNumber := "Defender 2.5" +# Requirement := "Message action SHOULD be set to quarantine if the message is detected as impersonated: domains non-default policies" +# Output := tests with input as { +# "anti_phish_policies" : [ +# { +# "TargetedDomainProtectionAction" : "Quarantine", +# "Identity" : "Custom 1" +# }, +# { +# "TargetedDomainProtectionAction" : "Not Quarantine", +# "Identity" : "Office365 AntiPhish Default" # The default policy should be ignored here +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_TargetedDomainProtectionActionCustom_Incorrect if { +# ControlNumber := "Defender 2.5" +# Requirement := "Message action SHOULD be set to quarantine if the message is detected as impersonated: domains non-default policies" +# Output := tests with input as { +# "anti_phish_policies" : [ +# { +# "TargetedDomainProtectionAction" : "Quarantine", +# "Identity" : "Custom 1" +# }, +# { +# "TargetedDomainProtectionAction" : "Not Quarantine", +# "Identity" : "Custom 2" +# }, +# { +# "TargetedDomainProtectionAction" : "Not Quarantine", +# "Identity" : "Custom 3" +# }, +# { +# "TargetedDomainProtectionAction" : "Not Quarantine", +# "Identity" : "Office365 AntiPhish Default" # The default policy should be ignored here +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# startswith(RuleOutput[0].ReportDetails, "2 non-default anti phish policy(ies) found where the action for messages detected as domain impersonation is not quarantine:") +# # I don't think we can assume the order rego will Output these, hence the "includes" check instead of a simple == +# contains(RuleOutput[0].ReportDetails, "Custom 2") +# contains(RuleOutput[0].ReportDetails, "Custom 3") +# } + +# test_MailboxIntelligenceProtectionAction_Correct if { +# ControlNumber := "Defender 2.5" +# Requirement := "Message action SHALL be set to quarantine if the message is detected as impersonated: mailbox default policy" + +# Output := tests with input as { +# "anti_phish_policies" : [ +# { +# "MailboxIntelligenceProtectionAction" : "Quarantine", +# "Identity" : "Office365 AntiPhish Default" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_MailboxIntelligenceProtectionAction_Incorrect if { +# ControlNumber := "Defender 2.5" +# Requirement := "Message action SHALL be set to quarantine if the message is detected as impersonated: mailbox default policy" + +# Output := tests with input as { +# "anti_phish_policies" : [ +# { +# "MailboxIntelligenceProtectionAction" : "Not Quarantine", +# "Identity" : "Office365 AntiPhish Default" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement not met" +# } + +# test_MailIntProtectionActionCustom_Correct if { +# ControlNumber := "Defender 2.5" +# Requirement := "Message action SHOULD be set to quarantine if the message is detected as impersonated: mailbox non-default policies" +# Output := tests with input as { +# "anti_phish_policies" : [ +# { +# "MailboxIntelligenceProtectionAction" : "Quarantine", +# "Identity" : "Custom 1" +# }, +# { +# "MailboxIntelligenceProtectionAction" : "Quarantine", +# "Identity" : "Custom 2" +# }, +# { +# "MailboxIntelligenceProtectionAction" : "something else", +# "Identity" : "Standard Preset Security Policy314195" # should be ignored +# }, +# { +# "MailboxIntelligenceProtectionAction" : "Not Quarantine", +# "Identity" : "Office365 AntiPhish Default" # The default policy should be ignored here +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails = "Requirement met" +# } + +# test_MailIntProtectionActionCustom_Incorrect if { +# ControlNumber := "Defender 2.5" +# Requirement := "Message action SHOULD be set to quarantine if the message is detected as impersonated: mailbox non-default policies" +# Output := tests with input as { +# "anti_phish_policies" : [ +# { +# "MailboxIntelligenceProtectionAction" : "Quarantine", +# "Identity" : "Custom 1" +# }, +# { +# "MailboxIntelligenceProtectionAction" : "Not Quarantine", +# "Identity" : "Custom 2" +# }, +# { +# "MailboxIntelligenceProtectionAction" : "something else", +# "Identity" : "Standard Preset Security Policy314195" # should be ignored +# }, +# { +# "MailboxIntelligenceProtectionAction" : "Not Quarantine", +# "Identity" : "Office365 AntiPhish Default" # The default policy should be ignored here +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails = "1 non-default anti phish policy(ies) found where the action for messages flagged by mailbox intelligence is not quarantine: Custom 2" +# } + +# +# Policy 6 +#-- +# test_AuthenticationFailAction_Correct if { +# ControlNumber := "Defender 2.5" +# Requirement := "Mail classified as spoofed SHALL be quarantined: default policy" + +# Output := tests with input as { +# "anti_phish_policies" : [ +# { +# "AuthenticationFailAction" : "Quarantine", +# "Identity" : "Office365 AntiPhish Default" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_AuthenticationFailAction_Incorrect if { +# ControlNumber := "Defender 2.5" +# Requirement := "Mail classified as spoofed SHALL be quarantined: default policy" + +# Output := tests with input as { +# "anti_phish_policies" : [ +# { +# "AuthenticationFailAction" : "Not Quarantine", +# "Identity" : "Office365 AntiPhish Default" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement not met" +# } + +# test_AuthenticationFailActionNonDefault_Correct if { +# ControlNumber := "Defender 2.5" +# Requirement := "Mail classified as spoofed SHOULD be quarantined: non-default policies" + +# Output := tests with input as { +# "anti_phish_policies" : [ +# { +# "AuthenticationFailAction" : "Quarantine", +# "Identity" : "Not Standard Preset SecurityPolicy1659535429826" +# }, +# { +# "AuthenticationFailAction" : "Quarantine", +# "Identity" : "Not Standard Preset SecurityPolicy Either" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_AuthenticationFailActionNonDefault_Incorrect if { +# ControlNumber := "Defender 2.5" +# Requirement := "Mail classified as spoofed SHOULD be quarantined: non-default policies" + +# Output := tests with input as { +# "anti_phish_policies" : [ +# { +# "AuthenticationFailAction" : "Not Quarantine", +# "Identity" : "Not Standard Preset SecurityPolicy1659535429826" +# }, +# { +# "AuthenticationFailAction" : "Quarantine", +# "Identity" : "Not Standard Preset SecurityPolicy Either" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "1 custom anti phish policy(ies) found where the action for spoofed emails is not set to quarantine: Not Standard Preset SecurityPolicy1659535429826" +# #Custom anti phish policy(ies) found where the action for spoofed emails is not set to quarantine. +# } + +# +# Policy 7 +#-- +# test_EnableFirstContactSafetyTipsDefault_Correct if { +# ControlNumber := "Defender 2.5" +# Requirement := "All safety tips SHALL be enabled: first contact default policy" + +# Output := tests with input as { +# "anti_phish_policies" : [ +# { +# "EnableFirstContactSafetyTips" : true, +# "Identity" : "Office365 AntiPhish Default" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_EnableFirstContactSafetyTipsDefault_Incorrect if { +# ControlNumber := "Defender 2.5" +# Requirement := "All safety tips SHALL be enabled: first contact default policy" + +# Output := tests with input as { +# "anti_phish_policies" : [ +# { +# "EnableFirstContactSafetyTips" : false, +# "Identity" : "Office365 AntiPhish Default" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement not met" +# } + +# test_EnableFirstContactSafetyTipsNonDefault_Correct if { +# ControlNumber := "Defender 2.5" +# Requirement := "All safety tips SHOULD be enabled: first contact non-default policies" + +# Output := tests with input as { +# "anti_phish_policies" : [ +# { +# "EnableFirstContactSafetyTips" : true, +# "Identity" : "Custom policy 1" +# }, +# { +# "EnableFirstContactSafetyTips" : true, +# "Identity" : "Custom policy 2" +# }, +# { +# "EnableFirstContactSafetyTips" : true, +# "Identity" : "Custom policy 3" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_EnableFirstContactSafetyTipsNonDefault_Incorrect if { +# ControlNumber := "Defender 2.5" +# Requirement := "All safety tips SHOULD be enabled: first contact non-default policies" + +# Output := tests with input as { +# "anti_phish_policies" : [ +# { +# "EnableFirstContactSafetyTips" : true, +# "Identity" : "Custom policy 1" +# }, +# { +# "EnableFirstContactSafetyTips" : false, +# "Identity" : "Custom policy 2" +# }, +# { +# "EnableFirstContactSafetyTips" : true, +# "Identity" : "Custom policy 3" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "1 custom anti phish policy(ies) found where first contact safety tips are not enabled: Custom policy 2" +# } + +# test_EnableSimilarUsersSafetyTipsDefault_Correct if { +# ControlNumber := "Defender 2.5" +# Requirement := "All safety tips SHALL be enabled: user impersonation default policy" + +# Output := tests with input as { +# "anti_phish_policies" : [ +# { +# "EnableSimilarUsersSafetyTips" : true, +# "Identity" : "Office365 AntiPhish Default" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_EnableSimilarUsersSafetyTipsDefault_Incorrect if { +# ControlNumber := "Defender 2.5" +# Requirement := "All safety tips SHALL be enabled: user impersonation default policy" + +# Output := tests with input as { +# "anti_phish_policies" : [ +# { +# "EnableSimilarUsersSafetyTips" : false, +# "Identity" : "Office365 AntiPhish Default" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement not met" +# } + +# test_EnableSimilarUserSafetyTipsNonDefault_Correct if { +# ControlNumber := "Defender 2.5" +# Requirement := "All safety tips SHOULD be enabled: user impersonation non-default policies" + +# Output := tests with input as { +# "anti_phish_policies" : [ +# { +# "EnableSimilarUsersSafetyTips" : true, +# "Identity" : "Custom policy 1" +# }, +# { +# "EnableSimilarUsersSafetyTips" : true, +# "Identity" : "Custom policy 2" +# }, +# { +# "EnableSimilarUsersSafetyTips" : true, +# "Identity" : "Custom policy 3" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_EnableSimilarUserSafetyTipsNonDefault_Incorrect if { +# ControlNumber := "Defender 2.5" +# Requirement := "All safety tips SHOULD be enabled: user impersonation non-default policies" + +# Output := tests with input as { +# "anti_phish_policies" : [ +# { +# "EnableSimilarUsersSafetyTips" : true, +# "Identity" : "Custom policy 1" +# }, +# { +# "EnableSimilarUsersSafetyTips" : false, +# "Identity" : "Custom policy 2" +# }, +# { +# "EnableSimilarUsersSafetyTips" : true, +# "Identity" : "Custom policy 3" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "1 custom anti phish policy(ies) found where similar user safety tips are not enabled: Custom policy 2" +# } + +# test_EnableSimilarDomainsSafetyTipsDomains_Correct if { +# ControlNumber := "Defender 2.5" +# Requirement := "All safety tips SHALL be enabled: domain impersonation default policy" + +# Output := tests with input as { +# "anti_phish_policies" : [ +# { +# "EnableSimilarDomainsSafetyTips" : true, +# "Identity" : "Office365 AntiPhish Default" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_EnableSimilarDomainsSafetyTipsDefault_Incorrect if { +# ControlNumber := "Defender 2.5" +# Requirement := "All safety tips SHALL be enabled: domain impersonation default policy" + +# Output := tests with input as { +# "anti_phish_policies" : [ +# { +# "EnableSimilarDomainsSafetyTips" : false, +# "Identity" : "Office365 AntiPhish Default" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement not met" +# } + +# test_EnableSimilarDomainsSafetyTipsNonDefault_Correct if { +# ControlNumber := "Defender 2.5" +# Requirement := "All safety tips SHOULD be enabled: domain impersonation non-default policies" + +# Output := tests with input as { +# "anti_phish_policies" : [ +# { +# "EnableSimilarDomainsSafetyTips" : true, +# "Identity" : "Custom policy 1" +# }, +# { +# "EnableSimilarDomainsSafetyTips" : true, +# "Identity" : "Custom policy 2" +# }, +# { +# "EnableSimilarDomainsSafetyTips" : true, +# "Identity" : "Custom policy 3" +# }, +# { +# "EnableSimilarDomainsSafetyTips" : false, # The default policy should be ignored +# "Identity" : "Office365 AntiPhish Default" +# }, +# { +# "EnableSimilarDomainsSafetyTips" : false, # The preset policy should be ignored too +# "Identity" : "Standard Preset Security Policy12345" +# }, +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_EnableSimilarDomainsSafetyTipsNonDefault_Incorrect if { +# ControlNumber := "Defender 2.5" +# Requirement := "All safety tips SHOULD be enabled: domain impersonation non-default policies" + +# Output := tests with input as { +# "anti_phish_policies" : [ +# { +# "EnableSimilarDomainsSafetyTips" : true, +# "Identity" : "Custom policy 1" +# }, +# { +# "EnableSimilarDomainsSafetyTips" : false, +# "Identity" : "Custom policy 2" +# }, +# { +# "EnableSimilarDomainsSafetyTips" : true, +# "Identity" : "Custom policy 3" +# }, +# { +# "EnableSimilarDomainsSafetyTips" : false, # The default policy should be ignored +# "Identity" : "Office365 AntiPhish Default" +# }, +# { +# "EnableSimilarDomainsSafetyTips" : false, # The preset policy should be ignored too +# "Identity" : "Standard Preset Security Policy12345" +# }, +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "1 custom anti phish policy(ies) found where similar domains safety tips are not enabled: Custom policy 2" +# } + +# test_EnableUnusualCharactersSafetyTips_Correct if { +# ControlNumber := "Defender 2.5" +# Requirement := "All safety tips SHALL be enabled: user impersonation unusual characters default policy" + +# Output := tests with input as { +# "anti_phish_policies" : [ +# { +# "EnableUnusualCharactersSafetyTips" : true, +# "Identity" : "Office365 AntiPhish Default" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_EnableUnusualCharactersSafetyTips_Incorrect if { +# ControlNumber := "Defender 2.5" +# Requirement := "All safety tips SHALL be enabled: user impersonation unusual characters default policy" + +# Output := tests with input as { +# "anti_phish_policies" : [ +# { +# "EnableUnusualCharactersSafetyTips" : false, +# "Identity" : "Office365 AntiPhish Default" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement not met" +# } + +# test_EnableUnusualCharSafetyTipsNonDefault_Correct if { +# ControlNumber := "Defender 2.5" +# Requirement := "All safety tips SHOULD be enabled: user impersonation unusual characters non-default policies" + +# Output := tests with input as { +# "anti_phish_policies" : [ +# { +# "EnableUnusualCharactersSafetyTips" : true, +# "Identity" : "Custom policy 1" +# }, +# { +# "EnableUnusualCharactersSafetyTips" : true, +# "Identity" : "Custom policy 2" +# }, +# { +# "EnableUnusualCharactersSafetyTips" : true, +# "Identity" : "Custom policy 3" +# }, +# { +# "EnableUnusualCharactersSafetyTips" : false, # The default policy should be ignored +# "Identity" : "Office365 AntiPhish Default" +# }, +# { +# "EnableUnusualCharactersSafetyTips" : false, # The preset policy should be ignored too +# "Identity" : "Standard Preset Security Policy12345" +# }, +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_EnableUnusualCharSafetyTipsNonDefault_Incorrect if { +# ControlNumber := "Defender 2.5" +# Requirement := "All safety tips SHOULD be enabled: user impersonation unusual characters non-default policies" + +# Output := tests with input as { +# "anti_phish_policies" : [ +# { +# "EnableUnusualCharactersSafetyTips" : true, +# "Identity" : "Custom policy 1" +# }, +# { +# "EnableUnusualCharactersSafetyTips" : false, +# "Identity" : "Custom policy 2" +# }, +# { +# "EnableUnusualCharactersSafetyTips" : true, +# "Identity" : "Custom policy 3" +# }, +# { +# "EnableUnusualCharactersSafetyTips" : false, # The default policy should be ignored +# "Identity" : "Office365 AntiPhish Default" +# }, +# { +# "EnableUnusualCharactersSafetyTips" : false, # The preset policy should be ignored too +# "Identity" : "Standard Preset Security Policy12345" +# }, +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "1 custom anti phish policy(ies) found where unusual character safety tips are not enabled: Custom policy 2" +# } + +# test_EnableViaTagDefault_Correct if { +# ControlNumber := "Defender 2.5" +# Requirement := "All safety tips SHALL be enabled: \"via\" tag default policy" + +# Output := tests with input as { +# "anti_phish_policies" : [ +# { +# "EnableViaTag" : true, +# "Identity" : "Office365 AntiPhish Default" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_EnableViaTagDefault_Incorrect if { +# ControlNumber := "Defender 2.5" +# Requirement := "All safety tips SHALL be enabled: \"via\" tag default policy" + +# Output := tests with input as { +# "anti_phish_policies" : [ +# { +# "EnableViaTag" : false, +# "Identity" : "Office365 AntiPhish Default" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement not met" +# } + +# test_EnableViaTagSafetyTipsNonDefault_Correct if { +# ControlNumber := "Defender 2.5" +# Requirement := "All safety tips SHOULD be enabled: \"via\" tag non-default policies" + +# Output := tests with input as { +# "anti_phish_policies" : [ +# { +# "EnableViaTag" : true, +# "Identity" : "Custom policy 1" +# }, +# { +# "EnableViaTag" : true, +# "Identity" : "Custom policy 2" +# }, +# { +# "EnableViaTag" : true, +# "Identity" : "Custom policy 3" +# }, +# { +# "EnableViaTag" : false, # The default policy should be ignored +# "Identity" : "Office365 AntiPhish Default" +# }, +# { +# "EnableViaTag" : false, # The preset policy should be ignored too +# "Identity" : "Standard Preset Security Policy12345" +# }, +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_EnableViaTagSafetyTipsNonDefault_Incorrect if { +# ControlNumber := "Defender 2.5" +# Requirement := "All safety tips SHOULD be enabled: \"via\" tag non-default policies" + +# Output := tests with input as { +# "anti_phish_policies" : [ +# { +# "EnableViaTag" : true, +# "Identity" : "Custom policy 1" +# }, +# { +# "EnableViaTag" : false, +# "Identity" : "Custom policy 2" +# }, +# { +# "EnableViaTag" : true, +# "Identity" : "Custom policy 3" +# }, +# { +# "EnableViaTag" : false, # The default policy should be ignored +# "Identity" : "Office365 AntiPhish Default" +# }, +# { +# "EnableViaTag" : false, # The preset policy should be ignored too +# "Identity" : "Standard Preset Security Policy12345" +# }, +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "1 custom anti phish policy(ies) found where via tag is not enabled: Custom policy 2" +# } + +# test_EnableUnauthenticatedSenderDefault_Correct if { +# ControlNumber := "Defender 2.5" +# Requirement := "All safety tips SHALL be enabled: \"?\" for unauthenticated senders for spoof default policy" + +# Output := tests with input as { +# "anti_phish_policies" : [ +# { +# "EnableUnauthenticatedSender" : true, +# "Identity" : "Office365 AntiPhish Default" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_EnableUnauthenticatedSenderDefault_Incorrect if { +# ControlNumber := "Defender 2.5" +# Requirement := "All safety tips SHALL be enabled: \"?\" for unauthenticated senders for spoof default policy" + +# Output := tests with input as { +# "anti_phish_policies" : [ +# { +# "EnableUnauthenticatedSender" : false, +# "Identity" : "Office365 AntiPhish Default" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement not met" +# } + +# test_EnableUnauthSenderTipsNonDefault_Correct if { +# ControlNumber := "Defender 2.5" +# Requirement := "All safety tips SHOULD be enabled: \"?\" for unauthenticated senders for spoof non-default policies" + +# Output := tests with input as { +# "anti_phish_policies" : [ +# { +# "EnableUnauthenticatedSender" : true, +# "Identity" : "Custom policy 1" +# }, +# { +# "EnableUnauthenticatedSender" : true, +# "Identity" : "Custom policy 2" +# }, +# { +# "EnableUnauthenticatedSender" : true, +# "Identity" : "Custom policy 3" +# }, +# { +# "EnableUnauthenticatedSender" : false, # The default policy should be ignored +# "Identity" : "Office365 AntiPhish Default" +# }, +# { +# "EnableUnauthenticatedSender" : false, # The preset policy should be ignored too +# "Identity" : "Standard Preset Security Policy12345" +# }, +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_EnableUnauthSenderTipsNonDefault_Incorrect if { +# ControlNumber := "Defender 2.5" +# Requirement := "All safety tips SHOULD be enabled: \"?\" for unauthenticated senders for spoof non-default policies" + +# Output := tests with input as { +# "anti_phish_policies" : [ +# { +# "EnableUnauthenticatedSender" : true, +# "Identity" : "Custom policy 1" +# }, +# { +# "EnableUnauthenticatedSender" : false, +# "Identity" : "Custom policy 2" +# }, +# { +# "EnableUnauthenticatedSender" : true, +# "Identity" : "Custom policy 3" +# }, +# { +# "EnableUnauthenticatedSender" : false, # The default policy should be ignored +# "Identity" : "Office365 AntiPhish Default" +# }, +# { +# "EnableUnauthenticatedSender" : false, # The preset policy should be ignored too +# "Identity" : "Standard Preset Security Policy12345" +# }, +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "1 custom anti phish policy(ies) found where '?' for unauthenticated sender is not enabled: Custom policy 2" +# } \ No newline at end of file diff --git a/Testing/Unit/Rego/Defender/DefenderConfig_06_test.rego b/Testing/Unit/Rego/Defender/DefenderConfig_06_test.rego new file mode 100644 index 0000000000..21add583be --- /dev/null +++ b/Testing/Unit/Rego/Defender/DefenderConfig_06_test.rego @@ -0,0 +1,1279 @@ +package defender +import future.keywords + +# TODO: Policy Id(s) needs to be resolved + +# +# Policy 1 +#-- +# test_BulkThreshold_Correct if { +# ControlNumber := "Defender 2.6" +# Requirement := "The bulk complaint level (BCL) threshold SHOULD be set to six or lower: default policy" + +# Output := tests with input as { +# "hosted_content_filter_policies": [ +# { +# "BulkThreshold": 6, +# "Identity" : "Default" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_BulkThreshold_CorrectV2 if { +# ControlNumber := "Defender 2.6" +# Requirement := "The bulk complaint level (BCL) threshold SHOULD be set to six or lower: default policy" + +# Output := tests with input as { +# "hosted_content_filter_policies": [ +# { +# "BulkThreshold": 5, +# "Identity" : "Default" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_BulkThreshold_Incorrect if { +# ControlNumber := "Defender 2.6" +# Requirement := "The bulk complaint level (BCL) threshold SHOULD be set to six or lower: default policy" + +# Output := tests with input as { +# "hosted_content_filter_policies": [ +# { +# "BulkThreshold": 7, +# "Identity" : "Default" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement not met" +# } + +### + +# test_NonDefBulkThreshold_Correct if { +# ControlNumber := "Defender 2.6" +# Requirement := "The bulk complaint level (BCL) threshold SHOULD be set to six or lower: non-default policies" + +# Output := tests with input as { +# "hosted_content_filter_policies": [ +# { +# "BulkThreshold": 6, +# "Identity":"Not Default" +# }, +# { +# "BulkThreshold": 6, +# "Identity":"Default" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_NonDefBulkThreshold_CorrectV2 if { +# ControlNumber := "Defender 2.6" +# Requirement := "The bulk complaint level (BCL) threshold SHOULD be set to six or lower: non-default policies" + +# Output := tests with input as { +# "hosted_content_filter_policies": [ +# { +# "BulkThreshold": 5, +# "Identity":"Not Default" +# }, +# { +# "BulkThreshold": 5, +# "Identity":"Default" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_NonDefBulkThreshold_Incorrect if { +# ControlNumber := "Defender 2.6" +# Requirement := "The bulk complaint level (BCL) threshold SHOULD be set to six or lower: non-default policies" + +# Output := tests with input as { +# "hosted_content_filter_policies": [ +# { +# "BulkThreshold": 7, +# "Identity":"Not Default" +# }, +# { +# "BulkThreshold": 7, +# "Identity":"Default" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "1 custom anti-spam policy(ies) found where bulk complaint level threshold is set to 7 or more: Not Default" +# } + +# +# Policy 2 +#-- +# test_SpamAction_Correct if { +# ControlNumber := "Defender 2.6" +# Requirement := "Spam SHALL be moved to either the junk email folder or the quarantine folder: default policy" + +# Output := tests with input as { +# "hosted_content_filter_policies": [ +# { +# "SpamAction": "Quarantine", +# "Identity": "Default" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_SpamAction_CorrectV2 if { +# ControlNumber := "Defender 2.6" +# Requirement := "Spam SHALL be moved to either the junk email folder or the quarantine folder: default policy" + +# Output := tests with input as { +# "hosted_content_filter_policies": [ +# { +# "SpamAction": "MoveToJmf", +# "Identity": "Default" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_SpamAction_Incorrect if { +# ControlNumber := "Defender 2.6" +# Requirement := "Spam SHALL be moved to either the junk email folder or the quarantine folder: default policy" + +# Output := tests with input as { +# "hosted_content_filter_policies": [ +# { +# "SpamAction": "Not MoveToJmf", +# "Identity": "Default" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement not met" +# } + +# test_SpamAction_Incorrect_V2 if { +# ControlNumber := "Defender 2.6" +# Requirement := "Spam SHALL be moved to either the junk email folder or the quarantine folder: default policy" + +# Output := tests with input as { +# "hosted_content_filter_policies": [ +# { +# "SpamAction": "Not Quarantine", +# "Identity": "Default" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement not met" +# } + +# test_HighConfSpamAction_Correct if { +# ControlNumber := "Defender 2.6" +# Requirement := "High confidence spam SHALL be moved to either the junk email folder or the quarantine folder: default policy" + +# Output := tests with input as { +# "hosted_content_filter_policies": [ +# { +# "HighConfidenceSpamAction": "Quarantine", +# "Identity": "Default" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_HighConfSpamAction_CorrectV2 if { +# ControlNumber := "Defender 2.6" +# Requirement := "High confidence spam SHALL be moved to either the junk email folder or the quarantine folder: default policy" + +# Output := tests with input as { +# "hosted_content_filter_policies": [ +# { +# "HighConfidenceSpamAction": "MoveToJmf", +# "Identity": "Default" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_HighConfSpamAction_Incorrect if { +# ControlNumber := "Defender 2.6" +# Requirement := "High confidence spam SHALL be moved to either the junk email folder or the quarantine folder: default policy" + +# Output := tests with input as { +# "hosted_content_filter_policies": [ +# { +# "HighConfidenceSpamAction": "Not MoveToJmf", +# "Identity": "Default" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement not met" +# } + +# test_HighConfSpamAction_Incorrect_V2 if { +# ControlNumber := "Defender 2.6" +# Requirement := "High confidence spam SHALL be moved to either the junk email folder or the quarantine folder: default policy" + +# Output := tests with input as { +# "hosted_content_filter_policies": [ +# { +# "HighConfidenceSpamAction": "Not Quarantine", +# "Identity": "Default" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement not met" +# } + +# test_Non_Def_SpamAction_Correct if { +# ControlNumber := "Defender 2.6" +# Requirement := "Spam SHOULD be moved to either the junk email folder or the quarantine folder: non-default policies" + +# Output := tests with input as { +# "hosted_content_filter_policies": [ +# { +# "SpamAction": "Quarantine", +# "Identity": "Not Default" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_Non_Def_SpamAction_CorrectV2 if { +# ControlNumber := "Defender 2.6" +# Requirement := "Spam SHOULD be moved to either the junk email folder or the quarantine folder: non-default policies" + +# Output := tests with input as { +# "hosted_content_filter_policies": [ +# { +# "SpamAction": "MoveToJmf", +# "Identity": "Not Default" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_Non_Def_SpamAction_Incorrect if { +# ControlNumber := "Defender 2.6" +# Requirement := "Spam SHOULD be moved to either the junk email folder or the quarantine folder: non-default policies" + +# Output := tests with input as { +# "hosted_content_filter_policies": [ +# { +# "SpamAction": "Not MoveToJmf", +# "Identity": "Not Default" +# }, +# { +# "SpamAction": "Not MoveToJmf", +# "Identity": "Default" +# } ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "1 custom anti-spam policy(ies) found where spam is not being sent to the Quarantine folder or the Junk Mail Folder: Not Default" +# } + +# test_Non_Def_SpamAction_Incorrect_V2 if { +# ControlNumber := "Defender 2.6" +# Requirement := "Spam SHOULD be moved to either the junk email folder or the quarantine folder: non-default policies" + +# Output := tests with input as { +# "hosted_content_filter_policies": [ +# { +# "SpamAction": "Not Quarantine", +# "Identity": "Not Default" +# }, +# { +# "SpamAction": "Not Quarantine", +# "Identity": "Default" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "1 custom anti-spam policy(ies) found where spam is not being sent to the Quarantine folder or the Junk Mail Folder: Not Default" +# } + +# test_Non_Def_HighConfSpamAction_Correct if { +# ControlNumber := "Defender 2.6" +# Requirement := "High confidence spam SHOULD be moved to either the junk email folder or the quarantine folder: non-default policies" + +# Output := tests with input as { +# "hosted_content_filter_policies": [ +# { +# "HighConfidenceSpamAction": "Quarantine", +# "Identity": "Not Default" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_Non_Def_HighConfSpamAction_CorrectV2 if { +# ControlNumber := "Defender 2.6" +# Requirement := "High confidence spam SHOULD be moved to either the junk email folder or the quarantine folder: non-default policies" + +# Output := tests with input as { +# "hosted_content_filter_policies": [ +# { +# "HighConfidenceSpamAction": "MoveToJmf", +# "Identity": "Not Default" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_Non_Def_HighConfSpamAction_Incorrect if { +# ControlNumber := "Defender 2.6" +# Requirement := "High confidence spam SHOULD be moved to either the junk email folder or the quarantine folder: non-default policies" + +# Output := tests with input as { +# "hosted_content_filter_policies": [ +# { +# "HighConfidenceSpamAction": "Not MoveToJmf", +# "Identity": "Not Default" +# }, +# { +# "HighConfidenceSpamAction": "Not MoveToJmf", +# "Identity": "Default" +# } ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "1 custom anti-spam policy(ies) found where high confidence spam is not being sent to the Quarantine folder or the Junk Mail Folder: Not Default"} + +# test_Non_Def_HighConfSpamAction_Incorrect_V2 if { +# ControlNumber := "Defender 2.6" +# Requirement := "High confidence spam SHOULD be moved to either the junk email folder or the quarantine folder: non-default policies" + +# Output := tests with input as { +# "hosted_content_filter_policies": [ +# { +# "HighConfidenceSpamAction": "Not Quarantine", +# "Identity": "Not Default" +# }, +# { +# "HighConfidenceSpamAction": "Not Quarantine", +# "Identity": "Default" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "1 custom anti-spam policy(ies) found where high confidence spam is not being sent to the Quarantine folder or the Junk Mail Folder: Not Default"} + +# +# Policy 3 +#-- +# test_PhishingSpamAction_Correct if { +# ControlNumber := "Defender 2.6" +# Requirement := "Phishing SHALL be quarantined: default policy" + +# Output := tests with input as { +# "hosted_content_filter_policies": [ +# { +# "PhishSpamAction": "Quarantine", +# "Identity": "Default" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_PhishingSpamAction_Incorrect if { +# ControlNumber := "Defender 2.6" +# Requirement := "Phishing SHALL be quarantined: default policy" + +# Output := tests with input as { +# "hosted_content_filter_policies": [ +# { +# "PhishSpamAction": "Not Quarantine", +# "Identity": "Default" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement not met" +# } + +# test_HighConfidencePhishAction_Correct if { +# ControlNumber := "Defender 2.6" +# Requirement := "High confidence phishing SHALL be quarantined: default policy" + +# Output := tests with input as { +# "hosted_content_filter_policies": [ +# { +# "HighConfidencePhishAction": "Quarantine", +# "Identity": "Default" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_HighConfidencePhishAction_Incorrect if { +# ControlNumber := "Defender 2.6" +# Requirement := "High confidence phishing SHALL be quarantined: default policy" + +# Output := tests with input as { +# "hosted_content_filter_policies": [ +# { +# "HighConfidencePhishAction": "Not Quarantine", +# "Identity": "Default" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement not met" +# } + +# test_Non_Def_PhishingSpamAction_Correct if { +# ControlNumber := "Defender 2.6" +# Requirement := "Phishing SHOULD be quarantined: non-default policies" + +# Output := tests with input as { +# "hosted_content_filter_policies": [ +# { +# "PhishSpamAction": "Quarantine", +# "Identity": "Not Default" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_Non_Def_PhishingSpamAction_Incorrect if { +# ControlNumber := "Defender 2.6" +# Requirement := "Phishing SHOULD be quarantined: non-default policies" + +# Output := tests with input as { +# "hosted_content_filter_policies": [ +# { +# "PhishSpamAction": "Not Quarantine", +# "Identity": "Not Default" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "1 custom anti-spam policy(ies) found where phishing isn't moved to the quarantine folder: Not Default" +# } + +# test_Non_Def_HighConfidencePhishAction_Correct if { +# ControlNumber := "Defender 2.6" +# Requirement := "High confidence phishing SHOULD be quarantined: non-default policies" + +# Output := tests with input as { +# "hosted_content_filter_policies": [ +# { +# "HighConfidencePhishAction": "Quarantine", +# "Identity": "Not Default" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_Non_Def_HighConfidencePhishAction_Incorrect if { +# ControlNumber := "Defender 2.6" +# Requirement := "High confidence phishing SHOULD be quarantined: non-default policies" + +# Output := tests with input as { +# "hosted_content_filter_policies": [ +# { +# "HighConfidencePhishAction": "Not Quarantine", +# "Identity": "Not Default" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "1 custom anti-spam policy(ies) found where high-confidence phishing isn't moved to quarantine folder: Not Default" +# } + +# +# Policy 4 +#-- +# test_BulkSpamAction_Correct if { +# ControlNumber := "Defender 2.6" +# Requirement := "Bulk email SHOULD be moved to either the junk email folder or the quarantine folder: default policy" + +# Output := tests with input as { +# "hosted_content_filter_policies": [ +# { +# "BulkSpamAction": "Quarantine", +# "Identity": "Default" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_BulkSpamAction_CorrectV2 if { +# ControlNumber := "Defender 2.6" +# Requirement := "Bulk email SHOULD be moved to either the junk email folder or the quarantine folder: default policy" + +# Output := tests with input as { +# "hosted_content_filter_policies": [ +# { +# "BulkSpamAction": "MoveToJmf", +# "Identity": "Default" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_BulkSpamAction_Incorrect if { +# ControlNumber := "Defender 2.6" +# Requirement := "Bulk email SHOULD be moved to either the junk email folder or the quarantine folder: default policy" + +# Output := tests with input as { +# "hosted_content_filter_policies": [ +# { +# "BulkSpamAction": "Not Quarantine", +# "Identity": "Default" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement not met" +# } + +# test_BulkSpamAction_Incorrect_V2 if { +# ControlNumber := "Defender 2.6" +# Requirement := "Bulk email SHOULD be moved to either the junk email folder or the quarantine folder: default policy" + +# Output := tests with input as { +# "hosted_content_filter_policies": [ +# { +# "BulkSpamAction": "Not MoveToJmf", +# "Identity": "Default" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement not met" +# } + +# +# Policy 5 +#-- +# test_QuarantineRetentionPeriod_Correct if { +# ControlNumber := "Defender 2.6" +# Requirement := "Spam in quarantine SHOULD be retained for at least 30 days: default policy" + +# Output := tests with input as { +# "hosted_content_filter_policies": [ +# { +# "QuarantineRetentionPeriod": 30, +# "Identity": "Default" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_QuarantineRetentionPeriod_Incorrect if { +# ControlNumber := "Defender 2.6" +# Requirement := "Spam in quarantine SHOULD be retained for at least 30 days: default policy" + +# Output := tests with input as { +# "hosted_content_filter_policies": [ +# { +# "QuarantineRetentionPeriod": 31, +# "Identity": "Default" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement not met" +# } + +# test_QuarantineRetentionPeriod_Incorrect_V2 if { +# ControlNumber := "Defender 2.6" +# Requirement := "Spam in quarantine SHOULD be retained for at least 30 days: default policy" + +# Output := tests with input as { +# "hosted_content_filter_policies": [ +# { +# "QuarantineRetentionPeriod": 29, +# "Identity": "Default" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement not met" +# } + +# test_QuarantineRetentionPeriodCustom_Correct if { +# ControlNumber := "Defender 2.6" +# Requirement := "Spam in quarantine SHOULD be retained for at least 30 days: non-default policies" + +# Output := tests with input as { +# "hosted_content_filter_policies": [ +# { +# "QuarantineRetentionPeriod": 30, +# "Identity": "Custom 1" +# }, +# { +# "QuarantineRetentionPeriod": 3, +# "Identity": "Default" # This policy should be ignored +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_QuarantineRetentionPeriodCustom_Incorrect if { +# ControlNumber := "Defender 2.6" +# Requirement := "Spam in quarantine SHOULD be retained for at least 30 days: non-default policies" + +# Output := tests with input as { +# "hosted_content_filter_policies": [ +# { +# "QuarantineRetentionPeriod": 30, +# "Identity": "Custom 1" +# }, +# { +# "QuarantineRetentionPeriod": 29, +# "Identity": "Custom 2" +# }, +# { +# "QuarantineRetentionPeriod": 3, +# "Identity": "Default" # This policy should be ignored +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "1 custom anti-spam policy(ies) found where spam in quarantine isn't retained for 30 days: Custom 2" +# } + +# +# Policy 6 +#-- +# test_InlineSafetyTipsEnabled_Correct if { +# ControlNumber := "Defender 2.6" +# Requirement := "Spam safety tips SHOULD be turned on: default policy" + +# Output := tests with input as { +# "hosted_content_filter_policies": [ +# { +# "InlineSafetyTipsEnabled": true, +# "Identity": "Default" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_InlineSafetyTipsEnabled_Incorrect if { +# ControlNumber := "Defender 2.6" +# Requirement := "Spam safety tips SHOULD be turned on: default policy" + +# Output := tests with input as { +# "hosted_content_filter_policies": [ +# { +# "InlineSafetyTipsEnabled": false, +# "Identity": "Default" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement not met" +# } + +# test_InlineSafetyTipsEnabledCustom_Correct if { +# ControlNumber := "Defender 2.6" +# Requirement := "Spam safety tips SHOULD be turned on: non-default policies" + +# Output := tests with input as { +# "hosted_content_filter_policies": [ +# { +# "InlineSafetyTipsEnabled": false, +# "Identity": "Default" # should be ignored +# }, +# { +# "InlineSafetyTipsEnabled": true, +# "Identity": "Custom 1" +# }, +# { +# "InlineSafetyTipsEnabled": true, +# "Identity": "Custom 2" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_InlineSafetyTipsEnabledCustom_Incorrect if { +# ControlNumber := "Defender 2.6" +# Requirement := "Spam safety tips SHOULD be turned on: non-default policies" + +# Output := tests with input as { +# "hosted_content_filter_policies": [ +# { +# "InlineSafetyTipsEnabled": false, +# "Identity": "Default" # should be ignored +# }, +# { +# "InlineSafetyTipsEnabled": false, +# "Identity": "Custom 1" +# }, +# { +# "InlineSafetyTipsEnabled": true, +# "Identity": "Custom 2" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "1 custom anti-spam policy(ies) found where spam safety tips is disabled: Custom 1" +# } + +# +# Policy 7 +#-- +# test_ZapEnabled_Correct if { +# ControlNumber := "Defender 2.6" +# Requirement := "Zero-hour auto purge (ZAP) SHALL be enabled: default policy" + +# Output := tests with input as { +# "hosted_content_filter_policies": [ +# { +# "ZapEnabled": true, +# "Identity": "Default" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_ZapEnabled_Incorrect if { +# ControlNumber := "Defender 2.6" +# Requirement := "Zero-hour auto purge (ZAP) SHALL be enabled: default policy" + +# Output := tests with input as { +# "hosted_content_filter_policies": [ +# { +# "ZapEnabled": false, +# "Identity": "Default" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement not met" +# } + +# test_SpamZapEnabled_Correct if { +# ControlNumber := "Defender 2.6" +# Requirement := "Zero-hour auto purge (ZAP) SHALL be enabled for spam messages: default policy" + +# Output := tests with input as { +# "hosted_content_filter_policies": [ +# { +# "SpamZapEnabled": true, +# "Identity": "Default" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_SpamZapEnabled_Incorrect if { +# ControlNumber := "Defender 2.6" +# Requirement := "Zero-hour auto purge (ZAP) SHALL be enabled for spam messages: default policy" + +# Output := tests with input as { +# "hosted_content_filter_policies": [ +# { +# "SpamZapEnabled": false, +# "Identity": "Default" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement not met" +# } + +# test_PhishZapEnabled_Correct if { +# ControlNumber := "Defender 2.6" +# Requirement := "Zero-hour auto purge (ZAP) SHALL be enabled for phishing: default policy" + +# Output := tests with input as { +# "hosted_content_filter_policies": [ +# { +# "PhishZapEnabled": true, +# "Identity": "Default" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_PhishZapEnabled_Incorrect if { +# ControlNumber := "Defender 2.6" +# Requirement := "Zero-hour auto purge (ZAP) SHALL be enabled for phishing: default policy" + +# Output := tests with input as { +# "hosted_content_filter_policies": [ +# { +# "PhishZapEnabled": false, +# "Identity": "Default" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement not met" +# } + +# test_ZapEnabledCustom_Correct if { +# ControlNumber := "Defender 2.6" +# Requirement := "Zero-hour auto purge (ZAP) SHOULD be enabled: non-default" + +# Output := tests with input as { +# "hosted_content_filter_policies": [ +# { +# "ZapEnabled": true, +# "Identity": "Not Default" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_ZapEnabledCustom_Incorrect if { +# ControlNumber := "Defender 2.6" +# Requirement := "Zero-hour auto purge (ZAP) SHOULD be enabled: non-default" + +# Output := tests with input as { +# "hosted_content_filter_policies": [ +# { +# "ZapEnabled": false, +# "Identity": "Not Default" +# }, +# { +# "ZapEnabled": false, +# "Identity": "Default" # SHOULD be ignored +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "1 custom anti-spam policies found where Zero-hour auto purge is disabled: Not Default" +# } + +# test_SpamZapEnabled_Correct if { +# ControlNumber := "Defender 2.6" +# Requirement := "Zero-hour auto purge (ZAP) SHOULD be enabled for Spam: non-default" + +# Output := tests with input as { +# "hosted_content_filter_policies": [ +# { +# "SpamZapEnabled": true, +# "Identity": "Not Default" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_SpamZapEnabledCustom_Incorrect if { +# ControlNumber := "Defender 2.6" +# Requirement := "Zero-hour auto purge (ZAP) SHOULD be enabled for Spam: non-default" + +# Output := tests with input as { +# "hosted_content_filter_policies": [ +# { +# "SpamZapEnabled": false, +# "Identity": "Not Default" +# }, +# { +# "SpamZapEnabled": false, # should be ignored +# "Identity": "Default" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "1 custom anti-spam policies found where Zero-hour auto purge for spam is disabled: Not Default" +# } + +# test_PhishZapEnabledCustom_Correct if { +# ControlNumber := "Defender 2.6" +# Requirement := "Zero-hour auto purge (ZAP) SHOULD be enabled for phishing: non-default" + +# Output := tests with input as { +# "hosted_content_filter_policies": [ +# { +# "PhishZapEnabled": true, +# "Identity": "Not Default" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_PhishZapEnabledCustom_Incorrect if { +# ControlNumber := "Defender 2.6" +# Requirement := "Zero-hour auto purge (ZAP) SHOULD be enabled for phishing: non-default" + +# Output := tests with input as { +# "hosted_content_filter_policies": [ +# { +# "PhishZapEnabled": false, +# "Identity": "Not Default" +# }, +# { +# "PhishZapEnabled": false, # should be ignored +# "Identity": "Default" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "1 custom anti-spam policy(ies) found where Zero-hour auto purge for phishing is disabled: Not Default" +# } + +# +# Policy 8 +#-- +# test_AllowedSenderDomainsNotEmpty_Correct if { +# ControlNumber := "Defender 2.6" +# Requirement := "Allowed senders MAY be added but allowed domains SHALL NOT be added: default policy" + +# Output := tests with input as { +# "hosted_content_filter_policies": [ +# { +# "AllowedSenderDomains": [], +# "Identity": "Default" +# } +# ] +# } + + + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_AllowedSenderDomainsNotEmpty_Incorrect if { +# ControlNumber := "Defender 2.6" +# Requirement := "Allowed senders MAY be added but allowed domains SHALL NOT be added: default policy" + +# Output := tests with input as { +# "hosted_content_filter_policies": [ +# { +# "AllowedSenderDomains": [""], +# "Identity": "Default" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "1 custom anti-spam policy(ies) found where there is at least one allowed sender domain: Default" +# } + +# test_AllowedSenderDomainsNotEmptyCustom_Correct if { +# ControlNumber := "Defender 2.6" +# Requirement := "Allowed senders MAY be added but allowed domains SHOULD NOT be added: non-default" + +# Output := tests with input as { +# "hosted_content_filter_policies": [ +# { +# "AllowedSenderDomains": [], +# "Identity": "Not Default" +# } +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_AllowedSenderDomainsNotEmptyCustom_Incorrect if { +# ControlNumber := "Defender 2.6" +# Requirement := "Allowed senders MAY be added but allowed domains SHOULD NOT be added: non-default" + +# Output := tests with input as { +# "hosted_content_filter_policies": [ +# { +# "AllowedSenderDomains": [""], +# "Identity": "Not Default" +# }, +# { +# "AllowedSenderDomains": [""], +# "Identity": "Default" +# } +# ] +# } + + + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# print(RuleOutput) + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "1 custom policy(ies) found where there is at least one allowed sender domain: Not Default" +# } \ No newline at end of file diff --git a/Testing/Unit/Rego/Defender/DefenderConfig_07_test.rego b/Testing/Unit/Rego/Defender/DefenderConfig_07_test.rego new file mode 100644 index 0000000000..a1c879f6c3 --- /dev/null +++ b/Testing/Unit/Rego/Defender/DefenderConfig_07_test.rego @@ -0,0 +1,1413 @@ +package defender +import future.keywords + +# TODO: Policy Id(s) needs to be resolved + +# +# Policy 1 +#-- +# test_Domains_Correct if { +# ControlNumber := "Defender 2.7" +# Requirement := "The Safe Links Policy SHALL include all agency domains-and by extension-all users" + +# Output := tests with input as { +# "safe_links_rules" : [ +# { +# "RecipientDomainIs": ["Test Domain"], +# "Identity" : "Test Policy Rule", +# "SafeLinksPolicy": "Test Policy", +# "State" : "Enabled" +# } +# ], +# "all_domains" : [ +# { +# "DomainName" : "Test Domain" +# } +# ], +# "defender_license" : true +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_DomainName_Incorrect_V1 if { +# ControlNumber := "Defender 2.7" +# Requirement := "The Safe Links Policy SHALL include all agency domains-and by extension-all users" + +# Output := tests with input as { +# "safe_links_rules" : [ +# { +# "RecipientDomainIs": [""], +# "Identity" : "Test Policy", +# "SafeLinksPolicy": "Test Policy", +# "State" : "Enabled" +# } +# ], +# "all_domains" : [ +# { +# "DomainName" : "Test Domain" +# } +# ], +# "defender_license" : true +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "No policy found that applies to all domains: Test Domain" +# } + +# test_DomainName_Incorrect_V2 if { +# ControlNumber := "Defender 2.7" +# Requirement := "The Safe Links Policy SHALL include all agency domains-and by extension-all users" + +# Output := tests with input as { +# "safe_links_rules" : [ +# { +# "RecipientDomainIs": ["Test Domain2"], +# "Identity" : "Test Policy", +# "SafeLinksPolicy": "Test Policy", +# "State" : "Enabled" +# } +# ], +# "all_domains" : [ +# { +# "DomainName" : "Test Domain" +# } +# ], +# "defender_license" : true +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "No policy found that applies to all domains: Test Domain" +# } + +# test_Domains_Incorrect_v3 if { +# ControlNumber := "Defender 2.7" +# Requirement := "The Safe Links Policy SHALL include all agency domains-and by extension-all users" + +# Output := tests with input as { +# "safe_links_rules" : [ +# { +# "RecipientDomainIs": ["Test Domain"], +# "Identity" : "Test Policy", +# "SafeLinksPolicy": "Test Policy", +# "State" : "Disabled" +# } +# ], +# "all_domains" : [ +# { +# "DomainName" : "Test Domain" +# } +# ], +# "defender_license" : true +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "No policy found that applies to all domains: Test Domain" +# } + +# test_Domains_Incorrect_V4 if { +# # If no defender license is present, the provider will output "safe_links_rules" +# # and "safe_links_policies" as empty lists +# ControlNumber := "Defender 2.7" +# Requirement := "The Safe Links Policy SHALL include all agency domains-and by extension-all users" + +# Output := tests with input as { +# "safe_links_rules": [], +# "safe_links_policies": [], +# "all_domains" : [ +# { +# "DomainName" : "Test Domain" +# } +# ], +# "defender_license" : false +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement not met **NOTE: Either you do not have sufficient permissions or your tenant does not have a license for Microsoft Defender for Office 365 Plan 1, which is required for this feature.**" +# } + +# +# Policy 2 +#-- +# test_EnableSafeLinksForEmail_Correct_V1 if { +# ControlNumber := "Defender 2.7" +# Requirement := "URL rewriting and malicious link click checking SHALL be enabled" + +# Output := tests with input as { +# "safe_links_rules": [ +# { +# "State" : "Enabled", +# "SafeLinksPolicy": "a", +# "Identity" : "a" +# }, +# { +# "State" : "Enabled", +# "SafeLinksPolicy": "b", +# "Identity" : "b rule" +# } +# ], +# "safe_links_policies": [ +# { +# "EnableSafeLinksForEmail" : true, +# "Identity": "a" +# }, +# { +# "EnableSafeLinksForEmail" : false, +# "Identity": "b" +# }, +# ], +# "defender_license" : true +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_EnableSafeLinksForEmail_Correct_V2 if { +# ControlNumber := "Defender 2.7" +# Requirement := "URL rewriting and malicious link click checking SHALL be enabled" + +# Output := tests with input as { +# "safe_links_rules": [ +# { +# "State" : "Enabled", +# "SafeLinksPolicy": "b", +# "Identity" : "a" +# }, +# { +# "State" : "Disabled", +# "SafeLinksPolicy": "b", +# "Identity" : "b rule" +# } +# ], +# "safe_links_policies": [ +# { +# "EnableSafeLinksForEmail" : true, +# "Identity": "a" +# }, +# { +# "EnableSafeLinksForEmail" : true, +# "Identity": "b" +# } +# ], +# "defender_license" : true +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_EnableSafeLinksForEmail_Incorrect_V1 if { +# ControlNumber := "Defender 2.7" +# Requirement := "URL rewriting and malicious link click checking SHALL be enabled" + +# Output := tests with input as { +# "safe_links_rules": [ +# { +# "Identity" : "Default Rule", +# "SafeLinksPolicy": "Default", +# "State" : "Enabled" +# } +# ], +# "safe_links_policies": [ +# { +# "EnableSafeLinksForEmail" : false, +# "Identity": "Default" +# } +# ], +# "defender_license" : true +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement not met" +# } + +# test_EnableSafeLinksForEmail_Incorrect_V2 if { +# ControlNumber := "Defender 2.7" +# Requirement := "URL rewriting and malicious link click checking SHALL be enabled" + +# Output := tests with input as { +# "safe_links_rules": [ +# { +# "Identity" : "Default Rule", +# "SafeLinksPolicy": "Default", +# "State" : "Disabled" +# } +# ], +# "safe_links_policies": [ +# { +# "EnableSafeLinksForEmail" : true, +# "Identity": "Default" +# } +# ], +# "defender_license" : true +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement not met" +# } + +# test_EnableSafeLinksForEmail_Incorrect_V3 if { +# # If no defender license is present, the provider will output "safe_links_rules" +# # and "safe_links_policies" as empty lists +# ControlNumber := "Defender 2.7" +# Requirement := "URL rewriting and malicious link click checking SHALL be enabled" + +# Output := tests with input as { +# "safe_links_rules" : [], +# "safe_links_policies" : [], +# "defender_license" : false +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement not met **NOTE: Either you do not have sufficient permissions or your tenant does not have a license for Microsoft Defender for Office 365 Plan 1, which is required for this feature.**" +# } + +# +# Policy 3 +#-- +# test_EnableSafeLinksForTeams_Correct_V1 if { +# ControlNumber := "Defender 2.7" +# Requirement := "Malicious link click checking SHALL be enabled with Microsoft Teams" + +# Output := tests with input as { +# "safe_links_rules": [ +# { +# "State" : "Enabled", +# "SafeLinksPolicy": "a", +# "Identity" : "a rule" +# }, +# { +# "State" : "Enabled", +# "SafeLinksPolicy": "b", +# "Identity" : "a" +# } +# ], +# "safe_links_policies": [ +# { +# "EnableSafeLinksForTeams" : true, +# "Identity": "a" +# }, +# { +# "EnableSafeLinksForTeams" : false, +# "Identity": "b" +# } +# ], +# "defender_license" : true +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_EnableSafeLinksForTeams_Correct_V2 if { +# ControlNumber := "Defender 2.7" +# Requirement := "Malicious link click checking SHALL be enabled with Microsoft Teams" + +# Output := tests with input as { +# "safe_links_rules": [ +# { +# "State" : "Disabled", +# "Identity" : "a", +# "SafeLinksPolicy": "a" +# }, +# { +# "State" : "Enabled", +# "Identity" : "b rule", +# "SafeLinksPolicy": "b" +# } +# ], +# "safe_links_policies": [ +# { +# "EnableSafeLinksForTeams" : true, +# "Identity": "a" +# }, +# { +# "EnableSafeLinksForTeams" : true, +# "Identity": "b" +# } +# ], +# "defender_license" : true +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_EnableSafeLinksForTeams_Incorrect_V1 if { +# ControlNumber := "Defender 2.7" +# Requirement := "Malicious link click checking SHALL be enabled with Microsoft Teams" + +# Output := tests with input as { +# "safe_links_rules": [ +# { +# "Identity" : "Default", +# "SafeLinksPolicy": "Default", +# "State" : "Enabled" +# } +# ], +# "safe_links_policies": [ +# { +# "EnableSafeLinksForTeams" : false, +# "Identity": "Default" +# } +# ], +# "defender_license" : true +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement not met" +# } + +# test_EnableSafeLinksForTeams_Incorrect_V2 if { +# ControlNumber := "Defender 2.7" +# Requirement := "Malicious link click checking SHALL be enabled with Microsoft Teams" + +# Output := tests with input as { +# "safe_links_rules": [ +# { +# "Identity" : "Default", +# "SafeLinksPolicy": "Default", +# "State" : "Disabled" +# } +# ], +# "safe_links_policies": [ +# { +# "EnableSafeLinksForTeams" : false, +# "Identity": "Default" +# } +# ], +# "defender_license" : true +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement not met" +# } + +# test_EnableSafeLinksForTeams_Incorrect_V3 if { +# # If no defender license is present, the provider will output "safe_links_rules" +# # and "safe_links_policies" as empty lists +# ControlNumber := "Defender 2.7" +# Requirement := "Malicious link click checking SHALL be enabled with Microsoft Teams" + +# Output := tests with input as { +# "safe_links_rules" : [], +# "safe_links_policies" : [], +# "defender_license" : false +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement not met **NOTE: Either you do not have sufficient permissions or your tenant does not have a license for Microsoft Defender for Office 365 Plan 1, which is required for this feature.**" +# } + +# +# Policy 4 +#-- +# test_ScanUrls_Correct_V1 if { +# ControlNumber := "Defender 2.7" +# Requirement := "Real-time suspicious URL and file-link scanning SHALL be enabled" + +# Output := tests with input as { +# "safe_links_rules": [ +# { +# "State" : "Enabled", +# "SafeLinksPolicy": "a", +# "Identity" : "a" +# }, +# { +# "State" : "Enabled", +# "SafeLinksPolicy": "b", +# "Identity" : "b" +# } +# ], +# "safe_links_policies": [ +# { +# "ScanUrls" : false, +# "Identity": "a" +# }, +# { +# "ScanUrls" : true, +# "Identity": "b" +# } +# ], +# "defender_license" : true +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_ScanUrls_Correct_V2 if { +# ControlNumber := "Defender 2.7" +# Requirement := "Real-time suspicious URL and file-link scanning SHALL be enabled" + +# Output := tests with input as { +# "safe_links_rules": [ +# { +# "State" : "Disabled", +# "SafeLinksPolicy": "a", +# "Identity" : "a" +# }, +# { +# "State" : "Enabled", +# "SafeLinksPolicy": "b", +# "Identity" : "b" +# } +# ], +# "safe_links_policies": [ +# { +# "ScanUrls" : true, +# "Identity": "a" +# }, +# { +# "ScanUrls" : true, +# "Identity": "b" +# } +# ], +# "defender_license" : true +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_ScanUrls_Incorrect_V1 if { +# ControlNumber := "Defender 2.7" +# Requirement := "Real-time suspicious URL and file-link scanning SHALL be enabled" + +# Output := tests with input as { +# "safe_links_rules": [ +# { +# "Identity" : "Default", +# "SafeLinksPolicy": "Default", +# "State" : "Enabled" +# } +# ], +# "safe_links_policies": [ +# { +# "ScanUrls" : false, +# "Identity": "Default" +# } +# ], +# "defender_license" : true +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement not met" +# } + +# test_ScanUrls_Incorrect_V2 if { +# ControlNumber := "Defender 2.7" +# Requirement := "Real-time suspicious URL and file-link scanning SHALL be enabled" + +# Output := tests with input as { +# "safe_links_rules": [ +# { +# "Identity" : "Default", +# "SafeLinksPolicy": "Default", +# "State" : "Disabled" +# } +# ], +# "safe_links_policies": [ +# { +# "ScanUrls" : false, +# "Identity": "Default" +# } +# ], +# "defender_license" : true +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement not met" +# } + +# test_ScanUrls_Incorrect_V3 if { +# # If no defender license is present, the provider will output "safe_links_rules" +# # and "safe_links_policies" as empty lists +# ControlNumber := "Defender 2.7" +# Requirement := "Real-time suspicious URL and file-link scanning SHALL be enabled" + +# Output := tests with input as { +# "safe_links_rules" : [], +# "safe_links_policies" : [], +# "defender_license" : false +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement not met **NOTE: Either you do not have sufficient permissions or your tenant does not have a license for Microsoft Defender for Office 365 Plan 1, which is required for this feature.**" +# } + +# +# Policy 5 +#-- +# test_DeliverMessageAfterScan_Correct_V1 if { +# ControlNumber := "Defender 2.7" +# Requirement := "URLs SHALL be scanned completely before message delivery" + +# Output := tests with input as { +# "safe_links_rules": [ +# { +# "State" : "Enabled", +# "SafeLinksPolicy": "a", +# "Identity" : "a rule" +# }, +# { +# "State" : "Enabled", +# "SafeLinksPolicy": "b", +# "Identity" : "b" +# } +# ], +# "safe_links_policies": [ +# { +# "DeliverMessageAfterScan" : true, +# "Identity": "a" +# }, +# { +# "DeliverMessageAfterScan" : false, +# "Identity": "b" +# } +# ], +# "defender_license" : true +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_DeliverMessageAfterScan_Correct_V2 if { +# ControlNumber := "Defender 2.7" +# Requirement := "URLs SHALL be scanned completely before message delivery" + +# Output := tests with input as { +# "safe_links_rules": [ +# { +# "State" : "Enabled", +# "SafeLinksPolicy": "a", +# "Identity" : "a" +# }, +# { +# "State" : "Disabled", +# "SafeLinksPolicy": "b", +# "Identity" : "b rule" +# } +# ], +# "safe_links_policies": [ +# { +# "DeliverMessageAfterScan" : true, +# "Identity": "a" +# }, +# { +# "DeliverMessageAfterScan" : true, +# "Identity": "b" +# } +# ], +# "defender_license" : true +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_DeliverMessageAfterScan_Incorrect_V1 if { +# ControlNumber := "Defender 2.7" +# Requirement := "URLs SHALL be scanned completely before message delivery" + +# Output := tests with input as { +# "safe_links_rules": [ +# { +# "Identity" : "Default", +# "SafeLinksPolicy": "Default", +# "State" : "Enabled" +# } +# ], +# "safe_links_policies": [ +# { +# "DeliverMessageAfterScan" : false, +# "Identity": "Default" +# } +# ], +# "defender_license" : true +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement not met" +# } + +# test_DeliverMessageAfterScan_Incorrect_V2 if { +# ControlNumber := "Defender 2.7" +# Requirement := "URLs SHALL be scanned completely before message delivery" + +# Output := tests with input as { +# "safe_links_rules": [ +# { +# "Identity" : "Default", +# "SafeLinksPolicy": "Default", +# "State" : "Disabled" +# } +# ], +# "safe_links_policies": [ +# { +# "DeliverMessageAfterScan" : false, +# "Identity": "Default" +# } +# ], +# "defender_license" : true +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement not met" +# } + +# test_DeliverMessageAfterScan_Incorrect_V3 if { +# # If no defender license is present, the provider will output "safe_links_rules" +# # and "safe_links_policies" as empty lists +# ControlNumber := "Defender 2.7" +# Requirement := "URLs SHALL be scanned completely before message delivery" + +# Output := tests with input as { +# "safe_links_rules" : [], +# "safe_links_policies" : [], +# "defender_license" : false +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement not met **NOTE: Either you do not have sufficient permissions or your tenant does not have a license for Microsoft Defender for Office 365 Plan 1, which is required for this feature.**" +# } + +# +# Policy 6 +#-- +# test_EnableForInternalSenders_Correct_V1 if { +# ControlNumber := "Defender 2.7" +# Requirement := "Internal agency email messages SHALL have safe links enabled" + +# Output := tests with input as { +# "safe_links_rules": [ +# { +# "State" : "Enabled", +# "SafeLinksPolicy": "a", +# "Identity" : "a" +# }, +# { +# "State" : "Enabled", +# "SafeLinksPolicy": "b", +# "Identity" : "b" +# } +# ], +# "safe_links_policies": [ +# { +# "Identity" : "a", +# "EnableForInternalSenders" : false +# }, +# { +# "Identity" : "b", +# "EnableForInternalSenders" : true +# } +# ], +# "defender_license" : true +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_EnableForInternalSenders_Correct_V2 if { +# ControlNumber := "Defender 2.7" +# Requirement := "Internal agency email messages SHALL have safe links enabled" + +# Output := tests with input as { +# "safe_links_rules": [ +# { +# "State" : "Disabled", +# "SafeLinksPolicy": "a", +# "Identity" : "a" +# }, +# { +# "State" : "Enabled", +# "SafeLinksPolicy": "b", +# "Identity" : "b rule" +# } +# ], +# "safe_links_policies": [ +# { +# "Identity" : "a", +# "EnableForInternalSenders" : true +# }, +# { +# "Identity" : "b", +# "EnableForInternalSenders" : true +# } +# ], +# "defender_license" : true +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_EnableForInternalSenders_Incorrect_V1 if { +# ControlNumber := "Defender 2.7" +# Requirement := "Internal agency email messages SHALL have safe links enabled" + +# Output := tests with input as { +# "safe_links_rules": [ +# { +# "Identity" : "Default", +# "SafeLinksPolicy": "Default", +# "State" : "Enabled" +# } +# ], +# "safe_links_policies": [ +# { +# "Identity" : "Not Built-in Protection Policy", +# "EnableForInternalSenders" : false +# } +# ], +# "defender_license" : true +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement not met" +# } + +# test_EnableForInternalSenders_Incorrect_V2 if { +# ControlNumber := "Defender 2.7" +# Requirement := "Internal agency email messages SHALL have safe links enabled" + +# Output := tests with input as { +# "safe_links_rules": [ +# { +# "Identity" : "Default", +# "SafeLinksPolicy": "Default", +# "State" : "Disabled" +# } +# ], +# "safe_links_policies": [ +# { +# "Identity" : "Not Built-in Protection Policy", +# "EnableForInternalSenders" : false +# } +# ], +# "defender_license" : true +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement not met" +# } + +# test_EnableForInternalSenders_Incorrect_V3 if { +# # If no defender license is present, the provider will output "safe_links_rules" +# # and "safe_links_policies" as empty lists +# ControlNumber := "Defender 2.7" +# Requirement := "Internal agency email messages SHALL have safe links enabled" + +# Output := tests with input as { +# "safe_links_rules" : [], +# "safe_links_policies" : [], +# "defender_license" : false +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement not met **NOTE: Either you do not have sufficient permissions or your tenant does not have a license for Microsoft Defender for Office 365 Plan 1, which is required for this feature.**" +# } + +# +# Policy 7 +#-- +# test_TrackClicks_Correct_V1 if { +# ControlNumber := "Defender 2.7" +# Requirement := "User click tracking SHALL be enabled" + +# Output := tests with input as { +# "safe_links_rules": [ +# { +# "State" : "Enabled", +# "SafeLinksPolicy": "a", +# "Identity" : "a" +# }, +# { +# "State" : "Enabled", +# "SafeLinksPolicy": "b", +# "Identity" : "b" +# } +# ], +# "safe_links_policies": [ +# { +# "TrackClicks" : false, +# "Identity": "a" +# }, +# { +# "TrackClicks" : true, +# "Identity": "b" +# } +# ], +# "defender_license" : true +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_TrackClicks_Correct_V2 if { +# ControlNumber := "Defender 2.7" +# Requirement := "User click tracking SHALL be enabled" + +# Output := tests with input as { +# "safe_links_rules": [ +# { +# "State" : "Enabled", +# "SafeLinksPolicy": "a", +# "Identity" : "a" +# }, +# { +# "State" : "Disabled", +# "SafeLinksPolicy": "b", +# "Identity" : "b" +# } +# ], +# "safe_links_policies": [ +# { +# "TrackClicks" : true, +# "Identity": "a" +# }, +# { +# "TrackClicks" : true, +# "Identity": "b" +# } +# ], +# "defender_license" : true +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_TrackClicks_Incorrect_V1 if { +# ControlNumber := "Defender 2.7" +# Requirement := "User click tracking SHALL be enabled" + +# Output := tests with input as { +# "safe_links_rules": [ +# { +# "Identity" : "Default", +# "State" : "Enabled", +# "SafeLinksPolicy": "Default" +# } +# ], +# "safe_links_policies": [ +# { +# "TrackClicks" : false, +# "Identity": "Default" +# } +# ], +# "defender_license" : true +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement not met" +# } + +# test_TrackClicks_Incorrect_V2 if { +# ControlNumber := "Defender 2.7" +# Requirement := "User click tracking SHALL be enabled" + +# Output := tests with input as { +# "safe_links_rules": [ +# { +# "Identity" : "Default", +# "State" : "Disabled", +# "SafeLinksPolicy": "Default" +# } +# ], +# "safe_links_policies": [ +# { +# "TrackClicks" : false, +# "Identity": "Default" +# } +# ], +# "defender_license" : true +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement not met" +# } + +# test_TrackClicks_Incorrect_V3 if { +# # If no defender license is present, the provider will output "safe_links_rules" +# # and "safe_links_policies" as empty lists +# ControlNumber := "Defender 2.7" +# Requirement := "User click tracking SHALL be enabled" + +# Output := tests with input as { +# "safe_links_rules" : [], +# "safe_links_policies" : [], +# "defender_license" : false +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement not met **NOTE: Either you do not have sufficient permissions or your tenant does not have a license for Microsoft Defender for Office 365 Plan 1, which is required for this feature.**" +# } + +# +# Policy 8 +#-- +# test_EnableSafeLinksForOffice_Correct_V1 if { +# ControlNumber := "Defender 2.7" +# Requirement := "Safe Links in Office 365 apps SHALL be turned on" + +# Output := tests with input as { +# "safe_links_rules": [ +# { +# "Identity" : "a rule", +# "SafeLinksPolicy": "a", +# "State" : "Enabled" +# }, +# { +# "Identity" : "b", +# "SafeLinksPolicy": "b", +# "State" : "Enabled" +# } +# ], +# "safe_links_policies": [ +# { +# "EnableSafeLinksForOffice" : true, +# "Identity" : "a" +# }, +# { +# # Only one policy needs to be true. +# "EnableSafeLinksForOffice" : false, +# "Identity" : "b" +# } +# ], +# "defender_license" : true +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_EnableSafeLinksForOffice_Correct_V2 if { +# ControlNumber := "Defender 2.7" +# Requirement := "Safe Links in Office 365 apps SHALL be turned on" + +# Output := tests with input as { +# "safe_links_rules": [ +# { +# "Identity" : "a rule", +# "SafeLinksPolicy": "a", +# "State" : "Enabled" +# }, +# { +# # Only one policy needs to be true. +# "Identity" : "b", +# "SafeLinksPolicy": "b", +# "State" : "Disabled" +# } +# ], +# "safe_links_policies": [ +# { +# "EnableSafeLinksForOffice" : true, +# "Identity" : "a" +# }, +# { +# "EnableSafeLinksForOffice" : true, +# "Identity" : "b" +# } +# ], +# "defender_license" : true +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_EnableSafeLinksForOffice_Incorrect_V1 if { +# ControlNumber := "Defender 2.7" +# Requirement := "Safe Links in Office 365 apps SHALL be turned on" + +# Output := tests with input as { +# "safe_links_rules": [ +# { +# "State" : "Disabled", +# "SafeLinksPolicy": "a", +# "Identity" : "a" +# } +# ], +# "safe_links_policies": [ +# { +# "EnableSafeLinksForOffice" : false, +# "Identity" : "a" +# } +# ], +# "defender_license" : true +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement not met" +# } + +# test_EnableSafeLinksForOffice_Incorrect_V2 if { +# ControlNumber := "Defender 2.7" +# Requirement := "Safe Links in Office 365 apps SHALL be turned on" + +# Output := tests with input as { +# "safe_links_rules": [ +# { +# "State" : "Disabled", +# "SafeLinksPolicy": "a", +# "Identity" : "a" +# } +# ], +# "safe_links_policies": [ +# { +# "EnableSafeLinksForOffice" : true, +# "Identity" : "a" +# } +# ], +# "defender_license" : true +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement not met" +# } + +# test_EnableSafeLinksForOffice_Incorrect_V3 if { +# ControlNumber := "Defender 2.7" +# Requirement := "Safe Links in Office 365 apps SHALL be turned on" + +# Output := tests with input as { +# "safe_links_rules": [ +# { +# "State" : "Enabled", +# "SafeLinksPolicy": "a", +# "Identity" : "a" +# } +# ], +# "safe_links_policies": [ +# { +# "EnableSafeLinksForOffice" : false, +# "Identity" : "a" +# } +# ], +# "defender_license" : true +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement not met" +# } + +# test_EnableSafeLinksForOffice_Incorrect_V4 if { +# # If no defender license is present, the provider will output "safe_links_rules" +# # and "safe_links_policies" as empty lists +# ControlNumber := "Defender 2.7" +# Requirement := "Safe Links in Office 365 apps SHALL be turned on" + +# Output := tests with input as { +# "safe_links_rules" : [], +# "safe_links_policies" : [], +# "defender_license" : false +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement not met **NOTE: Either you do not have sufficient permissions or your tenant does not have a license for Microsoft Defender for Office 365 Plan 1, which is required for this feature.**" +# } + +# +# Policy 9 +#-- +# test_AllowClickThrough_Correct_V1 if { +# ControlNumber := "Defender 2.7" +# Requirement := "Users SHALL NOT be enabled to click through to the original URL" + +# Output := tests with input as { +# "safe_links_rules": [ +# { +# "State" : "Enabled", +# "SafeLinksPolicy": "a", +# "Identity" : "a rule" +# }, +# { +# "State" : "Enabled", +# "SafeLinksPolicy": "b", +# "Identity" : "b" +# } +# ], +# "safe_links_policies": [ +# { +# "AllowClickThrough" : false, +# "Identity" : "a" +# }, +# { +# "AllowClickThrough" : true, +# "Identity" : "b" +# } +# ], +# "defender_license" : true +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_AllowClickThrough_Correct_V2 if { +# ControlNumber := "Defender 2.7" +# Requirement := "Users SHALL NOT be enabled to click through to the original URL" + +# Output := tests with input as { +# "safe_links_rules": [ +# { +# "State" : "Enabled", +# "SafeLinksPolicy": "a", +# "Identity" : "a rule" +# }, +# { +# "State" : "Disabled", +# "SafeLinksPolicy": "b", +# "Identity" : "b" +# } +# ], +# "safe_links_policies": [ +# { +# "AllowClickThrough" : false, +# "Identity" : "a" +# }, +# { +# "AllowClickThrough" : false, +# "Identity" : "b" +# } +# ], +# "defender_license" : true +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_AllowClickThrough_Incorrect_V1 if { +# ControlNumber := "Defender 2.7" +# Requirement := "Users SHALL NOT be enabled to click through to the original URL" + +# Output := tests with input as { +# "safe_links_rules": [ +# { +# "State" : "Disabled", +# "SafeLinksPolicy": "a", +# "Identity" : "a" +# } +# ], +# "safe_links_policies": [ +# { +# "AllowClickThrough" : true, +# "Identity" : "a" +# } +# ], +# "defender_license" : true +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement not met" +# } + +# test_AllowClickThrough_Incorrect_V2 if { +# ControlNumber := "Defender 2.7" +# Requirement := "Users SHALL NOT be enabled to click through to the original URL" + +# Output := tests with input as { +# "safe_links_rules": [ +# { +# "State" : "Disabled", +# "SafeLinksPolicy": "a", +# "Identity" : "a" +# } +# ], +# "safe_links_policies": [ +# { +# "AllowClickThrough" : false, +# "Identity" : "a" +# } +# ], +# "defender_license" : true +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement not met" +# } + +# test_AllowClickThrough_Incorrect_V3 if { +# ControlNumber := "Defender 2.7" +# Requirement := "Users SHALL NOT be enabled to click through to the original URL" + +# Output := tests with input as { +# "safe_links_rules": [ +# { +# "State" : "Enabled", +# "SafeLinksPolicy": "a", +# "Identity" : "a" +# } +# ], +# "safe_links_policies": [ +# { +# "AllowClickThrough" : true, +# "Identity" : "a" +# } +# ], +# "defender_license" : true +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement not met" +# } + +# test_AllowClickThrough_Incorrect_V4 if { +# # If no defender license is present, the provider will output "safe_links_rules" +# # and "safe_links_policies" as empty lists +# ControlNumber := "Defender 2.7" +# Requirement := "Users SHALL NOT be enabled to click through to the original URL" + +# Output := tests with input as { +# "safe_links_rules" : [], +# "safe_links_policies" : [], +# "defender_license" : false +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement not met **NOTE: Either you do not have sufficient permissions or your tenant does not have a license for Microsoft Defender for Office 365 Plan 1, which is required for this feature.**" +# } diff --git a/Testing/Unit/Rego/Defender/DefenderConfig_08_test.rego b/Testing/Unit/Rego/Defender/DefenderConfig_08_test.rego new file mode 100644 index 0000000000..90f2938865 --- /dev/null +++ b/Testing/Unit/Rego/Defender/DefenderConfig_08_test.rego @@ -0,0 +1,467 @@ +package defender +import future.keywords + +# TODO: Policy Id(s) needs to be resolved + +# +# Policy 1 +#-- +# test_Domains_Correct if { +# ControlNumber := "Defender 2.8" +# Requirement := "At least one Safe Attachments Policy SHALL include all agency domains-and by extension-all users" + +# Output := tests with input as { +# "safe_attachment_rules" : [ +# { +# "RecipientDomainIs": ["Test Domain"], +# "SafeAttachmentPolicy": "Test Policy", +# "Identity" : "Test Policy Rule" +# } +# ], +# "all_domains" : [ +# { +# "DomainName" : "Test Domain" +# } +# ], +# "defender_license" : true +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_DomainName_Incorrect_V1 if { +# ControlNumber := "Defender 2.8" +# Requirement := "At least one Safe Attachments Policy SHALL include all agency domains-and by extension-all users" + +# Output := tests with input as { +# "safe_attachment_rules" : [ +# { +# "RecipientDomainIs": [""], +# "SafeAttachmentPolicy": "Test Policy", +# "Identity" : "Test Policy Rule" +# } +# ], +# "all_domains" : [ +# { +# "DomainName" : "Test Domain" +# } +# ], +# "defender_license" : true +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "No policy found that applies to all domains: Test Domain" +# } + +# test_DomainName_Incorrect_V2 if { +# ControlNumber := "Defender 2.8" +# Requirement := "At least one Safe Attachments Policy SHALL include all agency domains-and by extension-all users" + +# Output := tests with input as { +# "safe_attachment_rules" : [ +# { +# "RecipientDomainIs": ["Test Domain2"], +# "SafeAttachmentPolicy": "Test Policy", +# "Identity" : "Test Policy Rule" +# } +# ], +# "all_domains" : [ +# { +# "DomainName" : "Test Domain" +# } +# ], +# "defender_license" : true +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "No policy found that applies to all domains: Test Domain" +# } + +# test_DomainName_Incorrect_V3 if { +# # If no defender license is present, the provider will output "safe_attachment_rules" +# # and "safe_attachment_policies" as empty lists +# ControlNumber := "Defender 2.8" +# Requirement := "At least one Safe Attachments Policy SHALL include all agency domains-and by extension-all users" + +# Output := tests with input as { +# "safe_attachment_rules" : [], +# "all_domains" : [ +# { +# "DomainName" : "Test Domain" +# } +# ], +# "safe_attachment_policies" : [], +# "defender_license" : false +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement not met **NOTE: Either you do not have sufficient permissions or your tenant does not have a license for Microsoft Defender for Office 365 Plan 1, which is required for this feature.**" +# } + +# +# Policy 2 +#-- +# test_Action_Correct if { +# ControlNumber := "Defender 2.8" +# Requirement := "The action for malware in email attachments SHALL be set to block" + +# Output := tests with input as { +# "safe_attachment_rules": [ +# { +# "RecipientDomainIs": ["Test Domain"], +# "SafeAttachmentPolicy": "Test Policy", +# "Identity" : "Test Policy Rule" +# } +# ], +# "all_domains" : [ +# { +# "DomainName" : "Test Domain" +# } +# ], +# "safe_attachment_policies" : [ +# { +# "Action" : "Block", +# "Enable" : true, +# "RedirectAddress" : "127.0.0.1", +# "Identity" : "Test Policy" +# } +# ], +# "defender_license" : true +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_RecipientDomainIs_Incorrect_V1 if { +# ControlNumber := "Defender 2.8" +# Requirement := "The action for malware in email attachments SHALL be set to block" + +# Output := tests with input as { +# "safe_attachment_rules": [ +# { +# "RecipientDomainIs": [""], +# "SafeAttachmentPolicy": "Test Policy", +# "Identity" : "Test Policy" +# } +# ], +# "all_domains" : [ +# { +# "DomainName" : "Test Domain" +# } +# ], +# "safe_attachment_policies" : [ +# { +# "Action" : "Block", +# "Enable" : true, +# "RedirectAddress" : "127.0.0.1", +# "Identity" : "Test Policy" +# } +# ], +# "defender_license" : true +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "No enabled policy found with action set to block that apply to all domains" +# } + +# test_RecipientDomainIs_Incorrect_V2 if { +# ControlNumber := "Defender 2.8" +# Requirement := "The action for malware in email attachments SHALL be set to block" + +# Output := tests with input as { +# "safe_attachment_rules": [ +# { +# "RecipientDomainIs": ["Test Domain2"], +# "SafeAttachmentPolicy": "Test Policy", +# "Identity" : "Test Policy" +# } +# ], +# "all_domains" : [ +# { +# "DomainName" : "Test Domain" +# } +# ], +# "safe_attachment_policies" : [ +# { +# "Action" : "Block", +# "Enable" : true, +# "RedirectAddress" : "127.0.0.1", +# "Identity" : "Test Policy" +# } +# ], +# "defender_license" : true +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "No enabled policy found with action set to block that apply to all domains" +# } + +# test_Action_Incorrect_V1 if { +# ControlNumber := "Defender 2.8" +# Requirement := "The action for malware in email attachments SHALL be set to block" + +# Output := tests with input as { +# "safe_attachment_rules": [ +# { +# "RecipientDomainIs": ["Test Domain"], +# "SafeAttachmentPolicy": "Test Policy", +# "Identity" : "Test Policy" +# } +# ], +# "all_domains" : [ +# { +# "DomainName" : "Test Domain" +# } +# ], +# "safe_attachment_policies" : [ +# { +# "Action" : "Not Block", +# "Enable" : true, +# "RedirectAddress" : "127.0.0.1", +# "Identity" : "Test Policy" +# } +# ], +# "defender_license" : true +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "No enabled policy found with action set to block that apply to all domains" +# } + +# test_Action_Incorrect_V2 if { +# # If no defender license is present, the provider will output "safe_attachment_rules" +# # and "safe_attachment_policies" as empty lists +# ControlNumber := "Defender 2.8" +# Requirement := "The action for malware in email attachments SHALL be set to block" + +# Output := tests with input as { +# "safe_attachment_rules" : [], +# "all_domains" : [ +# { +# "DomainName" : "Test Domain" +# } +# ], +# "safe_attachment_policies" : [], +# "defender_license" : false +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement not met **NOTE: Either you do not have sufficient permissions or your tenant does not have a license for Microsoft Defender for Office 365 Plan 1, which is required for this feature.**" +# } + +# test_Enable_Incorrect if { +# ControlNumber := "Defender 2.8" +# Requirement := "The action for malware in email attachments SHALL be set to block" + +# Output := tests with input as { +# "safe_attachment_rules": [ +# { +# "RecipientDomainIs": ["Test Domain"], +# "SafeAttachmentPolicy": "Test Policy", +# "Identity" : "Test Policy " +# } +# ], +# "all_domains" : [ +# { +# "DomainName" : "Test Domain" +# } +# ], +# "safe_attachment_policies" : [ +# { +# "Action" : "Block", +# "Enable" : false, +# "RedirectAddress" : "127.0.0.1", +# "Identity" : "Test Policy" +# } +# ], +# "defender_license" : true +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "No enabled policy found with action set to block that apply to all domains" +# } + +# test_Identity_Incorrect if { +# ControlNumber := "Defender 2.8" +# Requirement := "The action for malware in email attachments SHALL be set to block" + +# Output := tests with input as { +# "safe_attachment_rules": [ +# { +# "RecipientDomainIs": ["Test Domain"], +# "SafeAttachmentPolicy": "Test Policy", +# "Identity" : "Test Policy" +# } +# ], +# "all_domains" : [ +# { +# "DomainName" : "Test Domain" +# } +# ], +# "safe_attachment_policies" : [ +# { +# "Action" : "Block", +# "Enable" : true, +# "RedirectAddress" : "127.0.0.1", +# "Identity" : "" +# } +# ], +# "defender_license" : true +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "No enabled policy found with action set to block that apply to all domains" +# } + +# +# Policy 3 +#-- +# test_RedirectPolicies_Correct if { +# ControlNumber := "Defender 2.8" +# Requirement := "Redirect emails with detected attachments to an agency-specified email SHOULD be enabled" + +# Output := tests with input as { +# "safe_attachment_rules": [ +# { +# "RecipientDomainIs": ["Test Domain"], +# "SafeAttachmentPolicy": "Test Policy", +# "Identity" : "Test Policy Rule" +# } +# ], +# "all_domains" : [ +# { +# "DomainName" : "Test Domain" +# } +# ], +# "safe_attachment_policies" : [ +# { +# "Action" : "Block", +# "Enable" : true, +# "RedirectAddress" : "127.0.0.1", +# "Identity" : "Test Policy" +# } +# ], +# "defender_license" : true +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_RedirectAddress_Incorrect if { +# ControlNumber := "Defender 2.8" +# Requirement := "Redirect emails with detected attachments to an agency-specified email SHOULD be enabled" + +# Output := tests with input as { +# "safe_attachment_rules": [ +# { +# "RecipientDomainIs": ["Test Domain"], +# "SafeAttachmentPolicy": "Test Policy", +# "Identity" : "Test Policy Rule" +# } +# ], +# "all_domains" : [ +# { +# "DomainName" : "Test Domain" +# } +# ], +# "safe_attachment_policies" : [ +# { +# "Action" : "Block", +# "Enable" : true, +# "RedirectAddress" : "", +# "Identity" : "Test Policy" +# } +# ], +# "defender_license" : true +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "No enabled policy found with action set to block and at least one contact specified" +# } + +# +# Policy 4 +#-- +# test_Spot_Correct if { +# ControlNumber := "Defender 2.8" +# Requirement := "Safe attachments SHOULD be enabled for SharePoint, OneDrive, and Microsoft Teams" + +# Output := tests with input as { +# "atp_policy_for_o365" : [ +# { +# "EnableATPForSPOTeamsODB" : true, +# "Identity" : "Default" +# } +# ], +# "defender_license" : true +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_Spot_Incorrect if { +# ControlNumber := "Defender 2.8" +# Requirement := "Safe attachments SHOULD be enabled for SharePoint, OneDrive, and Microsoft Teams" + +# Output := tests with input as { +# "atp_policy_for_o365" : [ +# { +# "EnableATPForSPOTeamsODB" : false, +# "Identity" : "Default" +# } +# ], +# "defender_license" : true +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement not met" +# } diff --git a/Testing/Unit/Rego/Defender/DefenderConfig_09_test.rego b/Testing/Unit/Rego/Defender/DefenderConfig_09_test.rego new file mode 100644 index 0000000000..78d7e22d6f --- /dev/null +++ b/Testing/Unit/Rego/Defender/DefenderConfig_09_test.rego @@ -0,0 +1,234 @@ +package defender +import future.keywords + +# TODO: Policy Id(s) needs to be resolved +# +# Policy 1 +#-- +# test_Disabled_Correct if { +# ControlNumber := "Defender 2.9" +# Requirement := "At a minimum, the alerts required by the Exchange Online Minimum Viable Secure Configuration Baseline SHALL be enabled" + +# Output := tests with input as { +# "protection_alerts": [ +# { +# "Name": "Suspicious email sending patterns detected", +# "Disabled": false +# }, +# { +# "Name": "Unusual increase in email reported as phish", +# "Disabled": false +# }, +# { +# "Name": "Suspicious Email Forwarding Activity", +# "Disabled": false +# }, +# { +# "Name": "Messages have been delayed", +# "Disabled": false +# }, +# { +# "Name": "Tenant restricted from sending unprovisioned email", +# "Disabled": false +# }, +# { +# "Name": "User restricted from sending email", +# "Disabled": false +# }, +# { +# "Name": "Malware campaign detected after delivery", +# "Disabled": false +# }, +# { +# "Name": "A potentially malicious URL click was detected", +# "Disabled": false +# }, +# { +# "Name": "Suspicious connector activity", +# "Disabled": false +# }, +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_Disabled_Correct_V2 if { +# # Test having extra alerts enabled that aren't required by the baseline +# # SHOULDn't matter +# ControlNumber := "Defender 2.9" +# Requirement := "At a minimum, the alerts required by the Exchange Online Minimum Viable Secure Configuration Baseline SHALL be enabled" + +# Output := tests with input as { +# "protection_alerts": [ +# { +# "Name": "Suspicious email sending patterns detected", +# "Disabled": false +# }, +# { +# "Name": "Unusual increase in email reported as phish", +# "Disabled": false +# }, +# { +# "Name": "Suspicious Email Forwarding Activity", +# "Disabled": false +# }, +# { +# "Name": "Messages have been delayed", +# "Disabled": false +# }, +# { +# "Name": "Tenant restricted from sending unprovisioned email", +# "Disabled": false +# }, +# { +# "Name": "User restricted from sending email", +# "Disabled": false +# }, +# { +# "Name": "Malware campaign detected after delivery", +# "Disabled": false +# }, +# { +# "Name": "A potentially malicious URL click was detected", +# "Disabled": false +# }, +# { +# "Name": "Suspicious connector activity", +# "Disabled": false +# }, +# { +# "Name": "Successful exact data match upload", # Not required +# "Disabled": false +# }, +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_Disabled_Incorrect if { +# ControlNumber := "Defender 2.9" +# Requirement := "At a minimum, the alerts required by the Exchange Online Minimum Viable Secure Configuration Baseline SHALL be enabled" + +# Output := tests with input as { +# "protection_alerts": [ +# { +# "Name": "Suspicious email sending patterns detected", +# "Disabled": true # SHOULD be false +# }, +# { +# "Name": "Unusual increase in email reported as phish", +# "Disabled": false +# }, +# { +# "Name": "Suspicious Email Forwarding Activity", +# "Disabled": false +# }, +# { +# "Name": "Messages have been delayed", +# "Disabled": false +# }, +# { +# "Name": "Tenant restricted from sending unprovisioned email", +# "Disabled": false +# }, +# { +# "Name": "User restricted from sending email", +# "Disabled": false +# }, +# { +# "Name": "Malware campaign detected after delivery", +# "Disabled": false +# }, +# { +# "Name": "A potentially malicious URL click was detected", +# "Disabled": false +# }, +# { +# "Name": "Suspicious connector activity", +# "Disabled": false +# }, +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "1 disabled required alert(s) found: Suspicious email sending patterns detected" +# } + +# test_Disabled_Incorrect_V2 if { +# # What happens if the alert is entirely missing instead of just disabled? +# ControlNumber := "Defender 2.9" +# Requirement := "At a minimum, the alerts required by the Exchange Online Minimum Viable Secure Configuration Baseline SHALL be enabled" + +# Output := tests with input as { +# "protection_alerts": [ +# { +# "Name": "Unusual increase in email reported as phish", +# "Disabled": false +# }, +# { +# "Name": "Suspicious Email Forwarding Activity", +# "Disabled": false +# }, +# { +# "Name": "Messages have been delayed", +# "Disabled": false +# }, +# { +# "Name": "Tenant restricted from sending unprovisioned email", +# "Disabled": false +# }, +# { +# "Name": "User restricted from sending email", +# "Disabled": false +# }, +# { +# "Name": "Malware campaign detected after delivery", +# "Disabled": false +# }, +# { +# "Name": "A potentially malicious URL click was detected", +# "Disabled": false +# }, +# { +# "Name": "Suspicious connector activity", +# "Disabled": false +# }, +# ] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "1 disabled required alert(s) found: Suspicious email sending patterns detected" +# } + +# +# Policy 2 +#-- +# test_NotImplemented_Correct if { +# ControlNumber := "Defender 2.9" +# PolicyId := "MS.DEFENDER.TBD" +# Requirement := "The alerts SHOULD be sent to a monitored address or incorporated into a SIEM" + +# Output := tests with input as { } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == NotCheckedDetails(PolicyId) +# } \ No newline at end of file diff --git a/Testing/Unit/Rego/Defender/DefenderConfig_10_test.rego b/Testing/Unit/Rego/Defender/DefenderConfig_10_test.rego new file mode 100644 index 0000000000..886cb91a65 --- /dev/null +++ b/Testing/Unit/Rego/Defender/DefenderConfig_10_test.rego @@ -0,0 +1,70 @@ +package defender +import future.keywords +import data.report.utils.NotCheckedDetails + +# +# Policy 1 +#-- +test_AdminAuditLogEnabled_Correct if { + PolicyId := "MS.DEFENDER.10.1v1" + + Output := tests with input as { + "admin_audit_log_config": [{ + "Identity": "Admin Audit Log Settings", + "UnifiedAuditLogIngestionEnabled" : true + }] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "Requirement met" +} + +test_AdminAuditLogEnabled_Incorrect if { + PolicyId := "MS.DEFENDER.10.1v1" + + Output := tests with input as { + "admin_audit_log_config": [{ + "Identity": "Admin Audit Log Settings", + "UnifiedAuditLogIngestionEnabled" : false + }] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "Requirement not met" +} + +# +# Policy 2 +#-- +test_NotImplemented_Correct_V1 if { + PolicyId := "MS.DEFENDER.10.2v1" + + Output := tests with input as { } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == NotCheckedDetails(PolicyId) +} + +# +# Policy 3 +#-- +test_NotImplemented_Correct_V2 if { + PolicyId := "MS.DEFENDER.10.3v1" + + Output := tests with input as { } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == NotCheckedDetails(PolicyId) +} diff --git a/Testing/Unit/Rego/EXO/EXOConfig2_09_test.rego b/Testing/Unit/Rego/EXO/EXOConfig2_09_test.rego deleted file mode 100644 index 43b6257e9a..0000000000 --- a/Testing/Unit/Rego/EXO/EXOConfig2_09_test.rego +++ /dev/null @@ -1,51 +0,0 @@ -package exo -import future.keywords - - -# -# Policy 1 -#-- -test_3rdParty_Correct_V1 if { - ControlNumber := "EXO 2.9" - Requirement := "Emails SHALL be filtered by the file types of included attachments. The selected filtering solution SHOULD offer services comparable to Microsoft Defender's Common Attachment Filter" - - Output := tests with input as { } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check" -} - -# -# Policy 2 -#-- -test_3rdParty_Correct_V2 if { - ControlNumber := "EXO 2.9" - Requirement := "The attachment filter SHOULD attempt to determine the true file type and assess the file extension" - - Output := tests with input as { } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check" -} - -# -# Policy 3 -#-- -test_3rdParty_Correct_V3 if { - ControlNumber := "EXO 2.9" - Requirement := "Disallowed file types SHALL be determined and set. At a minimum, click-to-run files SHOULD be blocked (e.g., .exe, .cmd, and .vbe)" - - Output := tests with input as { } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check" -} \ No newline at end of file diff --git a/Testing/Unit/Rego/EXO/EXOConfig2_11_test.rego b/Testing/Unit/Rego/EXO/EXOConfig2_11_test.rego deleted file mode 100644 index 3d1fca13ed..0000000000 --- a/Testing/Unit/Rego/EXO/EXOConfig2_11_test.rego +++ /dev/null @@ -1,51 +0,0 @@ -package exo -import future.keywords - - -# -# Policy 1 -#-- -test_3rdParty_Correct_V1 if { - ControlNumber := "EXO 2.11" - Requirement := "Impersonation protection checks SHOULD be used" - - Output := tests with input as { } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check" -} - -# -# Policy 2 -#-- -test_3rdParty_Correct_V2 if { - ControlNumber := "EXO 2.11" - Requirement := "User warnings, comparable to the user safety tips included with EOP, SHOULD be displayed" - - Output := tests with input as { } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check" -} - -# -# Policy 3 -#-- -test_3rdParty_Correct_V3 if { - ControlNumber := "EXO 2.11" - Requirement := "The phishing protection solution SHOULD include an AI-based phishing detection tool comparable to EOP Mailbox Intelligence" - - Output := tests with input as { } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check" -} \ No newline at end of file diff --git a/Testing/Unit/Rego/EXO/EXOConfig2_14_test.rego b/Testing/Unit/Rego/EXO/EXOConfig2_14_test.rego deleted file mode 100644 index 8cba3792bf..0000000000 --- a/Testing/Unit/Rego/EXO/EXOConfig2_14_test.rego +++ /dev/null @@ -1,51 +0,0 @@ -package exo -import future.keywords - - -# -# Policy 1 -#-- -test_3rdParty_Correct_V1 if { - ControlNumber := "EXO 2.14" - Requirement := "A spam filter SHALL be enabled. The filtering solution selected SHOULD offer services comparable to the native spam filtering offered by Microsoft" - - Output := tests with input as { } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check" -} - -# -# Policy 2 -#-- -test_3rdParty_Correct_V2 if { - ControlNumber := "EXO 2.14" - Requirement := "Spam and high confidence spam SHALL be moved to either the junk email folder or the quarantine folder" - - Output := tests with input as { } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check" -} - -# -# Policy 3 -#-- -test_3rdParty_Correct_V3 if { - ControlNumber := "EXO 2.14" - Requirement := "Allowed senders MAY be added, but allowed domains SHALL NOT be added" - - Output := tests with input as { } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check" -} \ No newline at end of file diff --git a/Testing/Unit/Rego/EXO/EXOConfig2_01_test.rego b/Testing/Unit/Rego/EXO/EXOConfig_01_test.rego similarity index 65% rename from Testing/Unit/Rego/EXO/EXOConfig2_01_test.rego rename to Testing/Unit/Rego/EXO/EXOConfig_01_test.rego index cb699a6ea4..84bd705f88 100644 --- a/Testing/Unit/Rego/EXO/EXOConfig2_01_test.rego +++ b/Testing/Unit/Rego/EXO/EXOConfig_01_test.rego @@ -6,8 +6,7 @@ import future.keywords # Policy 1 #-- test_AutoForwardEnabled_Correct if { - ControlNumber := "EXO 2.1" - Requirement := "Automatic forwarding to external domains SHALL be disabled" + PolicyId := "MS.EXO.1.1v1" Output := tests with input as { "remote_domains": [ @@ -18,7 +17,7 @@ test_AutoForwardEnabled_Correct if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -26,8 +25,7 @@ test_AutoForwardEnabled_Correct if { } test_AutoForwardEnabled_Incorrect_V1 if { - ControlNumber := "EXO 2.1" - Requirement := "Automatic forwarding to external domains SHALL be disabled" + PolicyId := "MS.EXO.1.1v1" Output := tests with input as { "remote_domains": [ @@ -38,7 +36,7 @@ test_AutoForwardEnabled_Incorrect_V1 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -46,8 +44,7 @@ test_AutoForwardEnabled_Incorrect_V1 if { } test_AutoForwardEnabled_Incorrect_V2 if { - ControlNumber := "EXO 2.1" - Requirement := "Automatic forwarding to external domains SHALL be disabled" + PolicyId := "MS.EXO.1.1v1" Output := tests with input as { "remote_domains": [ @@ -62,7 +59,7 @@ test_AutoForwardEnabled_Incorrect_V2 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -70,8 +67,7 @@ test_AutoForwardEnabled_Incorrect_V2 if { } test_AutoForwardEnabled_Incorrect_V3 if { - ControlNumber := "EXO 2.1" - Requirement := "Automatic forwarding to external domains SHALL be disabled" + PolicyId := "MS.EXO.1.1v1" Output := tests with input as { "remote_domains": [ @@ -90,13 +86,9 @@ test_AutoForwardEnabled_Incorrect_V3 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet RuleOutput[0].ReportDetails == "2 remote domain(s) that allows automatic forwarding: Test name, Test name 2" } - -# TODO: what about the case where "remote_domains" is empty? -# Is this possible? Or will the default domain "*" always be there? -# Requires exploration online and manual testing. \ No newline at end of file diff --git a/Testing/Unit/Rego/EXO/EXOConfig2_02_test.rego b/Testing/Unit/Rego/EXO/EXOConfig_02_test.rego similarity index 60% rename from Testing/Unit/Rego/EXO/EXOConfig2_02_test.rego rename to Testing/Unit/Rego/EXO/EXOConfig_02_test.rego index a6a414d735..81757ae25d 100644 --- a/Testing/Unit/Rego/EXO/EXOConfig2_02_test.rego +++ b/Testing/Unit/Rego/EXO/EXOConfig_02_test.rego @@ -1,29 +1,27 @@ package exo import future.keywords - +import data.report.utils.NotCheckedDetails # # Policy 1 #-- test_NotImplemented_Correct if { - ControlNumber := "EXO 2.2" - Requirement := "A list of approved IP addresses for sending mail SHALL be maintained" + PolicyId := "MS.EXO.2.1v1" Output := tests with input as { } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Currently cannot be checked automatically. See Exchange Online Secure Configuration Baseline policy 2.# for instructions on manual check" + RuleOutput[0].ReportDetails == NotCheckedDetails(PolicyId) } # # Policy 2 #-- test_Rdata_Correct if { - ControlNumber := "EXO 2.2" - Requirement := "An SPF policy(s) that designates only these addresses as approved senders SHALL be published" + PolicyId := "MS.EXO.2.2v1" Output := tests with input as { "spf_records": [ @@ -35,7 +33,7 @@ test_Rdata_Correct if { } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -43,8 +41,7 @@ test_Rdata_Correct if { } test_Rdata_Correct_V2 if { - ControlNumber := "EXO 2.2" - Requirement := "An SPF policy(s) that designates only these addresses as approved senders SHALL be published" + PolicyId := "MS.EXO.2.2v1" Output := tests with input as { "spf_records": [ @@ -55,7 +52,7 @@ test_Rdata_Correct_V2 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -63,8 +60,7 @@ test_Rdata_Correct_V2 if { } test_Rdata_Incorrect if { - ControlNumber := "EXO 2.2" - Requirement := "An SPF policy(s) that designates only these addresses as approved senders SHALL be published" + PolicyId := "MS.EXO.2.2v1" Output := tests with input as { "spf_records": [ @@ -75,7 +71,7 @@ test_Rdata_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -83,8 +79,7 @@ test_Rdata_Incorrect if { } test_Rdata_Incorrect_V2 if { - ControlNumber := "EXO 2.2" - Requirement := "An SPF policy(s) that designates only these addresses as approved senders SHALL be published" + PolicyId := "MS.EXO.2.2v1" Output := tests with input as { "spf_records": [ @@ -95,7 +90,7 @@ test_Rdata_Incorrect_V2 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -103,8 +98,7 @@ test_Rdata_Incorrect_V2 if { } test_Rdata_Incorrect_V3 if { - ControlNumber := "EXO 2.2" - Requirement := "An SPF policy(s) that designates only these addresses as approved senders SHALL be published" + PolicyId := "MS.EXO.2.2v1" Output := tests with input as { "spf_records": [ @@ -123,7 +117,7 @@ test_Rdata_Incorrect_V3 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -137,8 +131,7 @@ test_Rdata_Incorrect_V3 if { } test_Rdata_Multiple_Correct_V1 if { - ControlNumber := "EXO 2.2" - Requirement := "An SPF policy(s) that designates only these addresses as approved senders SHALL be published" + PolicyId := "MS.EXO.2.2v1" Output := tests with input as { "spf_records": [ @@ -149,7 +142,7 @@ test_Rdata_Multiple_Correct_V1 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -157,8 +150,7 @@ test_Rdata_Multiple_Correct_V1 if { } test_Rdata_Multiple_Correct_V2 if { - ControlNumber := "EXO 2.2" - Requirement := "An SPF policy(s) that designates only these addresses as approved senders SHALL be published" + PolicyId := "MS.EXO.2.2v1" Output := tests with input as { "spf_records": [ @@ -169,7 +161,7 @@ test_Rdata_Multiple_Correct_V2 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -177,8 +169,7 @@ test_Rdata_Multiple_Correct_V2 if { } test_Rdata_Multiple_Incorrect if { - ControlNumber := "EXO 2.2" - Requirement := "An SPF policy(s) that designates only these addresses as approved senders SHALL be published" + PolicyId := "MS.EXO.2.2v1" Output := tests with input as { "spf_records": [ @@ -189,7 +180,7 @@ test_Rdata_Multiple_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet diff --git a/Testing/Unit/Rego/EXO/EXOConfig2_03_test.rego b/Testing/Unit/Rego/EXO/EXOConfig_03_test.rego similarity index 79% rename from Testing/Unit/Rego/EXO/EXOConfig2_03_test.rego rename to Testing/Unit/Rego/EXO/EXOConfig_03_test.rego index 90ea3606e2..ddde94c127 100644 --- a/Testing/Unit/Rego/EXO/EXOConfig2_03_test.rego +++ b/Testing/Unit/Rego/EXO/EXOConfig_03_test.rego @@ -6,8 +6,7 @@ import future.keywords # Policy 1 #-- test_Enabled_Correct_V1 if { - ControlNumber := "EXO 2.3" - Requirement := "DKIM SHOULD be enabled for any custom domain" + PolicyId := "MS.EXO.3.1v1" Output := tests with input as { "dkim_config": [ @@ -30,7 +29,7 @@ test_Enabled_Correct_V1 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -39,8 +38,7 @@ test_Enabled_Correct_V1 if { test_Enabled_Correct_V2 if { # Test with incorrect default domain - ControlNumber := "EXO 2.3" - Requirement := "DKIM SHOULD be enabled for any custom domain" + PolicyId := "MS.EXO.3.1v1" Output := tests with input as { "dkim_config": [ @@ -77,7 +75,7 @@ test_Enabled_Correct_V2 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -86,8 +84,7 @@ test_Enabled_Correct_V2 if { test_Enabled_Correct_V3 if { # Test for multiple custom domains - ControlNumber := "EXO 2.3" - Requirement := "DKIM SHOULD be enabled for any custom domain" + PolicyId := "MS.EXO.3.1v1" Output := tests with input as { "dkim_config": [ @@ -122,7 +119,7 @@ test_Enabled_Correct_V3 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -131,8 +128,7 @@ test_Enabled_Correct_V3 if { test_Enabled_Correct_V4 if { # Test for no custom domains, just the default domain - ControlNumber := "EXO 2.3" - Requirement := "DKIM SHOULD be enabled for any custom domain" + PolicyId := "MS.EXO.3.1v1" Output := tests with input as { "dkim_config": [ @@ -155,7 +151,7 @@ test_Enabled_Correct_V4 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -163,8 +159,7 @@ test_Enabled_Correct_V4 if { } test_Enabled_Incorrect if { - ControlNumber := "EXO 2.3" - Requirement := "DKIM SHOULD be enabled for any custom domain" + PolicyId := "MS.EXO.3.1v1" Output := tests with input as { "dkim_config": [ @@ -187,7 +182,7 @@ test_Enabled_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -195,8 +190,7 @@ test_Enabled_Incorrect if { } test_Rdata_Incorrect if { - ControlNumber := "EXO 2.3" - Requirement := "DKIM SHOULD be enabled for any custom domain" + PolicyId := "MS.EXO.3.1v1" Output := tests with input as { "dkim_config": [ @@ -219,7 +213,7 @@ test_Rdata_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -227,8 +221,7 @@ test_Rdata_Incorrect if { } test_Rdata_Incorrect_V2 if { - ControlNumber := "EXO 2.3" - Requirement := "DKIM SHOULD be enabled for any custom domain" + PolicyId := "MS.EXO.3.1v1" Output := tests with input as { "dkim_config": [ @@ -251,7 +244,7 @@ test_Rdata_Incorrect_V2 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -259,8 +252,7 @@ test_Rdata_Incorrect_V2 if { } test_Enabled_Correct_V2 if { - ControlNumber := "EXO 2.3" - Requirement := "DKIM SHOULD be enabled for any custom domain" + PolicyId := "MS.EXO.3.1v1" Output := tests with input as { "dkim_config": [ @@ -295,7 +287,7 @@ test_Enabled_Correct_V2 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -303,8 +295,7 @@ test_Enabled_Correct_V2 if { } test_Enabled_Inorrect_V3 if { - ControlNumber := "EXO 2.3" - Requirement := "DKIM SHOULD be enabled for any custom domain" + PolicyId := "MS.EXO.3.1v1" Output := tests with input as { "dkim_config": [ @@ -339,7 +330,7 @@ test_Enabled_Inorrect_V3 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet diff --git a/Testing/Unit/Rego/EXO/EXOConfig2_04_test.rego b/Testing/Unit/Rego/EXO/EXOConfig_04_test.rego similarity index 71% rename from Testing/Unit/Rego/EXO/EXOConfig2_04_test.rego rename to Testing/Unit/Rego/EXO/EXOConfig_04_test.rego index 8f4e047946..97c19f3141 100644 --- a/Testing/Unit/Rego/EXO/EXOConfig2_04_test.rego +++ b/Testing/Unit/Rego/EXO/EXOConfig_04_test.rego @@ -6,8 +6,7 @@ import future.keywords # Policy 1 #-- test_Rdata_Correct if { - ControlNumber := "EXO 2.4" - Requirement := "A DMARC policy SHALL be published for every second-level domain" + PolicyId := "MS.EXO.4.1v1" Output := tests with input as { "dmarc_records":[ @@ -24,7 +23,7 @@ test_Rdata_Correct if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -32,8 +31,7 @@ test_Rdata_Correct if { } test_Rdata_Incorrect if { - ControlNumber := "EXO 2.4" - Requirement := "A DMARC policy SHALL be published for every second-level domain" + PolicyId := "MS.EXO.4.1v1" Output := tests with input as { "dmarc_records":[ @@ -50,7 +48,7 @@ test_Rdata_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -58,8 +56,7 @@ test_Rdata_Incorrect if { } test_Rdata_Incorrect_V2 if { - ControlNumber := "EXO 2.4" - Requirement := "A DMARC policy SHALL be published for every second-level domain" + PolicyId := "MS.EXO.4.1v1" Output := tests with input as { "dmarc_records":[ @@ -76,7 +73,7 @@ test_Rdata_Incorrect_V2 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -84,8 +81,7 @@ test_Rdata_Incorrect_V2 if { } test_Rdata_Incorrect_V3 if { - ControlNumber := "EXO 2.4" - Requirement := "A DMARC policy SHALL be published for every second-level domain" + PolicyId := "MS.EXO.4.1v1" Output := tests with input as { "dmarc_records": [ @@ -110,7 +106,7 @@ test_Rdata_Incorrect_V3 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -121,8 +117,7 @@ test_Rdata_Incorrect_V3 if { # Policy 2 #-- test_Rdata_Correct_V2 if { - ControlNumber := "EXO 2.4" - Requirement := "The DMARC message rejection option SHALL be \"p=reject\"" + PolicyId := "MS.EXO.4.2v1" Output := tests with input as { "dmarc_records": [ @@ -139,7 +134,7 @@ test_Rdata_Correct_V2 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -147,8 +142,7 @@ test_Rdata_Correct_V2 if { } test_Rdata_Incorrect_V4 if { - ControlNumber := "EXO 2.4" - Requirement := "The DMARC message rejection option SHALL be \"p=reject\"" + PolicyId := "MS.EXO.4.2v1" Output := tests with input as { "dmarc_records": [ @@ -165,7 +159,7 @@ test_Rdata_Incorrect_V4 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -173,8 +167,7 @@ test_Rdata_Incorrect_V4 if { } test_Rdata_Incorrect_V5 if { - ControlNumber := "EXO 2.4" - Requirement := "The DMARC message rejection option SHALL be \"p=reject\"" + PolicyId := "MS.EXO.4.2v1" Output := tests with input as { "dmarc_records": [ @@ -191,7 +184,7 @@ test_Rdata_Incorrect_V5 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -202,8 +195,7 @@ test_Rdata_Incorrect_V5 if { # Policy 3 #-- test_Rdata_Correct_V3 if { - ControlNumber := "EXO 2.4" - Requirement := "The DMARC point of contact for aggregate reports SHALL include reports@dmarc.cyber.dhs.gov" + PolicyId := "MS.EXO.4.3v1" Output := tests with input as { "dmarc_records": [ @@ -220,7 +212,7 @@ test_Rdata_Correct_V3 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -228,8 +220,7 @@ test_Rdata_Correct_V3 if { } test_Rdata_Incorrect_V6 if { - ControlNumber := "EXO 2.4" - Requirement := "The DMARC point of contact for aggregate reports SHALL include reports@dmarc.cyber.dhs.gov" + PolicyId := "MS.EXO.4.3v1" Output := tests with input as { "dmarc_records": [ @@ -246,7 +237,7 @@ test_Rdata_Incorrect_V6 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -254,8 +245,7 @@ test_Rdata_Incorrect_V6 if { } test_Rdata_Incorrect_V7 if { - ControlNumber := "EXO 2.4" - Requirement := "The DMARC point of contact for aggregate reports SHALL include reports@dmarc.cyber.dhs.gov" + PolicyId := "MS.EXO.4.3v1" Output := tests with input as { "dmarc_records": [ @@ -272,7 +262,7 @@ test_Rdata_Incorrect_V7 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -283,8 +273,7 @@ test_Rdata_Incorrect_V7 if { # Policy 4 #-- test_Rdata_Incorrect_V4 if { - ControlNumber := "EXO 2.4" - Requirement := "An agency point of contact SHOULD be included for aggregate and/or failure reports" + PolicyId := "MS.EXO.4.4v1" Output := tests with input as { "dmarc_records": [ @@ -301,7 +290,7 @@ test_Rdata_Incorrect_V4 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -309,8 +298,7 @@ test_Rdata_Incorrect_V4 if { } test_Rdata_Incorrect_V8 if { - ControlNumber := "EXO 2.4" - Requirement := "An agency point of contact SHOULD be included for aggregate and/or failure reports" + PolicyId := "MS.EXO.4.4v1" Output := tests with input as { "dmarc_records": [ @@ -327,7 +315,7 @@ test_Rdata_Incorrect_V8 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet diff --git a/Testing/Unit/Rego/EXO/EXOConfig2_05_test.rego b/Testing/Unit/Rego/EXO/EXOConfig_05_test.rego similarity index 65% rename from Testing/Unit/Rego/EXO/EXOConfig2_05_test.rego rename to Testing/Unit/Rego/EXO/EXOConfig_05_test.rego index d8e5983b5f..085b92b038 100644 --- a/Testing/Unit/Rego/EXO/EXOConfig2_05_test.rego +++ b/Testing/Unit/Rego/EXO/EXOConfig_05_test.rego @@ -6,8 +6,7 @@ import future.keywords # Policy 1 #-- test_SmtpClientAuthenticationDisabled_Correct if { - ControlNumber := "EXO 2.5" - Requirement := "SMTP AUTH SHALL be disabled in Exchange Online" + PolicyId := "MS.EXO.5.1v1" Output := tests with input as { "transport_config": @@ -19,7 +18,7 @@ test_SmtpClientAuthenticationDisabled_Correct if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -27,8 +26,7 @@ test_SmtpClientAuthenticationDisabled_Correct if { } test_SmtpClientAuthenticationDisabled_Incorrect if { - ControlNumber := "EXO 2.5" - Requirement := "SMTP AUTH SHALL be disabled in Exchange Online" + PolicyId := "MS.EXO.5.1v1" Output := tests with input as { "transport_config": [ @@ -39,7 +37,7 @@ test_SmtpClientAuthenticationDisabled_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet diff --git a/Testing/Unit/Rego/EXO/EXOConfig2_06_test.rego b/Testing/Unit/Rego/EXO/EXOConfig_06_test.rego similarity index 65% rename from Testing/Unit/Rego/EXO/EXOConfig2_06_test.rego rename to Testing/Unit/Rego/EXO/EXOConfig_06_test.rego index 2c71008367..3f18a2800c 100644 --- a/Testing/Unit/Rego/EXO/EXOConfig2_06_test.rego +++ b/Testing/Unit/Rego/EXO/EXOConfig_06_test.rego @@ -6,9 +6,8 @@ import future.keywords # Policy 1 #-- test_Domains_Contacts_Correct if { - ControlNumber := "EXO 2.6" - Requirement := "Contact folders SHALL NOT be shared with all domains, although they MAY be shared with specific domains" - + PolicyId := "MS.EXO.6.1v1" + Output := tests with input as { "sharing_policy": [ { @@ -21,7 +20,7 @@ test_Domains_Contacts_Correct if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -29,8 +28,7 @@ test_Domains_Contacts_Correct if { } test_Domains_Contacts_Incorrect if { - ControlNumber := "EXO 2.6" - Requirement := "Contact folders SHALL NOT be shared with all domains, although they MAY be shared with specific domains" + PolicyId := "MS.EXO.6.1v1" Output := tests with input as { "sharing_policy": [ @@ -44,7 +42,7 @@ test_Domains_Contacts_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -60,8 +58,7 @@ test_Domains_Contacts_Incorrect if { # Policy 2 #-- test_Domains_Calender_Correct if { - ControlNumber := "EXO 2.6" - Requirement := "Calendar details SHALL NOT be shared with all domains, although they MAY be shared with specific domains" + PolicyId := "MS.EXO.6.2v1" Output := tests with input as { "sharing_policy": [ @@ -75,7 +72,7 @@ test_Domains_Calender_Correct if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -83,8 +80,7 @@ test_Domains_Calender_Correct if { } test_Domains_Calender_Incorrect if { - ControlNumber := "EXO 2.6" - Requirement := "Calendar details SHALL NOT be shared with all domains, although they MAY be shared with specific domains" + PolicyId := "MS.EXO.6.2v1" Output := tests with input as { "sharing_policy": [ @@ -98,7 +94,7 @@ test_Domains_Calender_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet diff --git a/Testing/Unit/Rego/EXO/EXOConfig2_07_test.rego b/Testing/Unit/Rego/EXO/EXOConfig_07_test.rego similarity index 74% rename from Testing/Unit/Rego/EXO/EXOConfig2_07_test.rego rename to Testing/Unit/Rego/EXO/EXOConfig_07_test.rego index e416f64e74..07128b0416 100644 --- a/Testing/Unit/Rego/EXO/EXOConfig2_07_test.rego +++ b/Testing/Unit/Rego/EXO/EXOConfig_07_test.rego @@ -6,8 +6,7 @@ import future.keywords # Policy 1 #-- test_FromScope_Correct if { - ControlNumber := "EXO 2.7" - Requirement := "External sender warnings SHALL be implemented" + PolicyId := "MS.EXO.7.1v1" Output := tests with input as { "transport_rule": [ @@ -19,7 +18,7 @@ test_FromScope_Correct if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -27,8 +26,7 @@ test_FromScope_Correct if { } test_FromScope_IncorrectV1 if { - ControlNumber := "EXO 2.7" - Requirement := "External sender warnings SHALL be implemented" + PolicyId := "MS.EXO.7.1v1" Output := tests with input as { "transport_rule": [ @@ -40,7 +38,7 @@ test_FromScope_IncorrectV1 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -48,8 +46,7 @@ test_FromScope_IncorrectV1 if { } test_FromScope_IncorrectV2 if { - ControlNumber := "EXO 2.7" - Requirement := "External sender warnings SHALL be implemented" + PolicyId := "MS.EXO.7.1v1" Output := tests with input as { "transport_rule": [ @@ -61,7 +58,7 @@ test_FromScope_IncorrectV2 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -69,8 +66,7 @@ test_FromScope_IncorrectV2 if { } test_FromScope_IncorrectV3 if { - ControlNumber := "EXO 2.7" - Requirement := "External sender warnings SHALL be implemented" + PolicyId := "MS.EXO.7.1v1" Output := tests with input as { "transport_rule": [ @@ -82,7 +78,7 @@ test_FromScope_IncorrectV3 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -90,8 +86,7 @@ test_FromScope_IncorrectV3 if { } test_FromScope_IncorrectV4 if { - ControlNumber := "EXO 2.7" - Requirement := "External sender warnings SHALL be implemented" + PolicyId := "MS.EXO.7.1v1" Output := tests with input as { "transport_rule": [ @@ -103,7 +98,7 @@ test_FromScope_IncorrectV4 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -111,8 +106,7 @@ test_FromScope_IncorrectV4 if { } test_FromScope_Multiple_Correct if { - ControlNumber := "EXO 2.7" - Requirement := "External sender warnings SHALL be implemented" + PolicyId := "MS.EXO.7.1v1" Output := tests with input as { "transport_rule": [ @@ -139,7 +133,7 @@ test_FromScope_Multiple_Correct if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -147,8 +141,7 @@ test_FromScope_Multiple_Correct if { } test_FromScope_Multiple_Incorrect if { - ControlNumber := "EXO 2.7" - Requirement := "External sender warnings SHALL be implemented" + PolicyId := "MS.EXO.7.1v1" Output := tests with input as { "transport_rule": [ @@ -185,7 +178,7 @@ test_FromScope_Multiple_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet diff --git a/Testing/Unit/Rego/EXO/EXOConfig2_08_test.rego b/Testing/Unit/Rego/EXO/EXOConfig_08_test.rego similarity index 51% rename from Testing/Unit/Rego/EXO/EXOConfig2_08_test.rego rename to Testing/Unit/Rego/EXO/EXOConfig_08_test.rego index 81423b9d84..f8ca5a458e 100644 --- a/Testing/Unit/Rego/EXO/EXOConfig2_08_test.rego +++ b/Testing/Unit/Rego/EXO/EXOConfig_08_test.rego @@ -6,12 +6,11 @@ import future.keywords # Policy 1 #-- test_3rdParty_Correct_V1 if { - ControlNumber := "EXO 2.8" - Requirement := "A DLP solution SHALL be used. The selected DLP solution SHOULD offer services comparable to the native DLP solution offered by Microsoft" + PolicyId := "MS.EXO.8.1v1" Output := tests with input as { } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -22,12 +21,10 @@ test_3rdParty_Correct_V1 if { # Policy 2 #-- test_3rdParty_Correct_V2 if { - ControlNumber := "EXO 2.8" - Requirement := "The DLP solution SHALL protect PII and sensitive information, as defined by the agency. At a minimum, the sharing of credit card numbers, Taxpayer Identification Numbers (TIN), and Social Security Numbers (SSN) via email SHALL be restricted" - + PolicyId := "MS.EXO.8.2v1" Output := tests with input as { } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet diff --git a/Testing/Unit/Rego/EXO/EXOConfig_09_test.rego b/Testing/Unit/Rego/EXO/EXOConfig_09_test.rego new file mode 100644 index 0000000000..0fa06f70a2 --- /dev/null +++ b/Testing/Unit/Rego/EXO/EXOConfig_09_test.rego @@ -0,0 +1,47 @@ +package exo +import future.keywords + + +# +# Policy 1 +#-- +test_3rdParty_Correct_V1 if { + PolicyId := "MS.EXO.9.1v1" + + Output := tests with input as { } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check" +} + +# +# Policy 2 +#-- +test_3rdParty_Correct_V2 if { + PolicyId := "MS.EXO.9.2v1" + + Output := tests with input as { } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check" +} + +# +# Policy 3 +#-- +test_3rdParty_Correct_V3 if { + PolicyId := "MS.EXO.9.3v1" + Output := tests with input as { } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check" +} \ No newline at end of file diff --git a/Testing/Unit/Rego/EXO/EXOConfig2_15_test.rego b/Testing/Unit/Rego/EXO/EXOConfig_10_test.rego similarity index 63% rename from Testing/Unit/Rego/EXO/EXOConfig2_15_test.rego rename to Testing/Unit/Rego/EXO/EXOConfig_10_test.rego index 24ef2cbab6..8ac99d51d1 100644 --- a/Testing/Unit/Rego/EXO/EXOConfig2_15_test.rego +++ b/Testing/Unit/Rego/EXO/EXOConfig_10_test.rego @@ -6,12 +6,11 @@ import future.keywords # Policy 1 #-- test_3rdParty_Correct_V1 if { - ControlNumber := "EXO 2.15" - Requirement := "URL comparison with a block-list SHOULD be enabled" + PolicyId := "MS.EXO.10.1v1" Output := tests with input as { } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -22,12 +21,11 @@ test_3rdParty_Correct_V1 if { # Policy 2 #-- test_3rdParty_Correct_V2 if { - ControlNumber := "EXO 2.15" - Requirement := "Direct download links SHOULD be scanned for malware" + PolicyId := "MS.EXO.10.2v1" Output := tests with input as { } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -38,12 +36,11 @@ test_3rdParty_Correct_V2 if { # Policy 3 #-- test_3rdParty_Correct_V3 if { - ControlNumber := "EXO 2.15" - Requirement := "User click tracking SHOULD be enabled" + PolicyId := "MS.EXO.10.3v1" Output := tests with input as { } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet diff --git a/Testing/Unit/Rego/EXO/EXOConfig_11_test.rego b/Testing/Unit/Rego/EXO/EXOConfig_11_test.rego new file mode 100644 index 0000000000..2c759becaa --- /dev/null +++ b/Testing/Unit/Rego/EXO/EXOConfig_11_test.rego @@ -0,0 +1,48 @@ +package exo +import future.keywords + + +# +# Policy 1 +#-- +test_3rdParty_Correct_V1 if { + PolicyId := "MS.EXO.11.1v1" + + Output := tests with input as { } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check" +} + +# +# Policy 2 +#-- +test_3rdParty_Correct_V2 if { + PolicyId := "MS.EXO.11.2v1" + + Output := tests with input as { } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check" +} + +# +# Policy 3 +#-- +test_3rdParty_Correct_V3 if { + PolicyId := "MS.EXO.11.3v1" + + Output := tests with input as { } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check" +} diff --git a/Testing/Unit/Rego/EXO/EXOConfig2_12_test.rego b/Testing/Unit/Rego/EXO/EXOConfig_12_test.rego similarity index 66% rename from Testing/Unit/Rego/EXO/EXOConfig2_12_test.rego rename to Testing/Unit/Rego/EXO/EXOConfig_12_test.rego index 6d9f06ff16..dce10ae79f 100644 --- a/Testing/Unit/Rego/EXO/EXOConfig2_12_test.rego +++ b/Testing/Unit/Rego/EXO/EXOConfig_12_test.rego @@ -6,8 +6,7 @@ import future.keywords # Policy 1 #-- test_IPAllowList_Correct_V1 if { - ControlNumber := "EXO 2.12" - Requirement := "IP allow lists SHOULD NOT be created" + PolicyId := "MS.EXO.12.1v1" Output := tests with input as { "conn_filter": [ @@ -19,7 +18,7 @@ test_IPAllowList_Correct_V1 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -27,8 +26,7 @@ test_IPAllowList_Correct_V1 if { } test_IPAllowList_Correct_V2 if { - ControlNumber := "EXO 2.12" - Requirement := "IP allow lists SHOULD NOT be created" + PolicyId := "MS.EXO.12.1v1" Output := tests with input as { "conn_filter": @@ -41,7 +39,7 @@ test_IPAllowList_Correct_V2 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -49,8 +47,7 @@ test_IPAllowList_Correct_V2 if { } test_IPAllowList_Incorrect if { - ControlNumber := "EXO 2.12" - Requirement := "IP allow lists SHOULD NOT be created" + PolicyId := "MS.EXO.12.1v1" Output := tests with input as { "conn_filter": [ @@ -62,7 +59,7 @@ test_IPAllowList_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -73,8 +70,7 @@ test_IPAllowList_Incorrect if { # Policy 2 #-- test_EnableSafeList_Correct_V1 if { - ControlNumber := "EXO 2.12" - Requirement := "Safe lists SHOULD NOT be enabled" + PolicyId := "MS.EXO.12.2v1" Output := tests with input as { "conn_filter": [ @@ -86,7 +82,7 @@ test_EnableSafeList_Correct_V1 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -94,8 +90,7 @@ test_EnableSafeList_Correct_V1 if { } test_EnableSafeList_Incorrect_V1 if { - ControlNumber := "EXO 2.12" - Requirement := "Safe lists SHOULD NOT be enabled" + PolicyId := "MS.EXO.12.2v1" Output := tests with input as { "conn_filter": [ @@ -107,7 +102,7 @@ test_EnableSafeList_Incorrect_V1 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -115,8 +110,7 @@ test_EnableSafeList_Incorrect_V1 if { } test_EnableSafeList_Correct_V2 if { - ControlNumber := "EXO 2.12" - Requirement := "Safe lists SHOULD NOT be enabled" + PolicyId := "MS.EXO.12.2v1" Output := tests with input as { "conn_filter": [ @@ -128,7 +122,7 @@ test_EnableSafeList_Correct_V2 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet diff --git a/Testing/Unit/Rego/EXO/EXOConfig2_13_test.rego b/Testing/Unit/Rego/EXO/EXOConfig_13_test.rego similarity index 66% rename from Testing/Unit/Rego/EXO/EXOConfig2_13_test.rego rename to Testing/Unit/Rego/EXO/EXOConfig_13_test.rego index b83f060a4d..612d02f553 100644 --- a/Testing/Unit/Rego/EXO/EXOConfig2_13_test.rego +++ b/Testing/Unit/Rego/EXO/EXOConfig_13_test.rego @@ -6,8 +6,7 @@ import future.keywords # Policy 1 #-- test_AuditDisabled_Correct if { - ControlNumber := "EXO 2.13" - Requirement := "Mailbox auditing SHALL be enabled" + PolicyId := "MS.EXO.13.1v1" Output := tests with input as { "org_config": @@ -20,7 +19,7 @@ test_AuditDisabled_Correct if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -28,8 +27,7 @@ test_AuditDisabled_Correct if { } test_AuditDisabled_Incorrect if { - ControlNumber := "EXO 2.13" - Requirement := "Mailbox auditing SHALL be enabled" + PolicyId := "MS.EXO.13.1v1" Output := tests with input as { "org_config": [ @@ -41,7 +39,7 @@ test_AuditDisabled_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet diff --git a/Testing/Unit/Rego/EXO/EXOConfig_14_test.rego b/Testing/Unit/Rego/EXO/EXOConfig_14_test.rego new file mode 100644 index 0000000000..d5bac3a414 --- /dev/null +++ b/Testing/Unit/Rego/EXO/EXOConfig_14_test.rego @@ -0,0 +1,48 @@ +package exo +import future.keywords + + +# +# Policy 1 +#-- +test_3rdParty_Correct_V1 if { + PolicyId := "MS.EXO.14.1v1" + + Output := tests with input as { } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check" +} + +# +# Policy 2 +#-- +test_3rdParty_Correct_V2 if { + PolicyId := "MS.EXO.14.2v1" + + Output := tests with input as { } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check" +} + +# +# Policy 3 +#-- +test_3rdParty_Correct_V3 if { + PolicyId := "MS.EXO.14.3v1" + + Output := tests with input as { } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check" +} \ No newline at end of file diff --git a/Testing/Unit/Rego/EXO/EXOConfig2_17_test.rego b/Testing/Unit/Rego/EXO/EXOConfig_15_test.rego similarity index 63% rename from Testing/Unit/Rego/EXO/EXOConfig2_17_test.rego rename to Testing/Unit/Rego/EXO/EXOConfig_15_test.rego index 3a3c88b227..1fef5365c2 100644 --- a/Testing/Unit/Rego/EXO/EXOConfig2_17_test.rego +++ b/Testing/Unit/Rego/EXO/EXOConfig_15_test.rego @@ -6,12 +6,11 @@ import future.keywords # Policy 1 #-- test_3rdParty_Correct_V1 if { - ControlNumber := "EXO 2.17" - Requirement := "Unified audit logging SHALL be enabled" + PolicyId := "MS.EXO.15.1v1" Output := tests with input as { } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -22,12 +21,11 @@ test_3rdParty_Correct_V1 if { # Policy 2 #-- test_3rdParty_Correct_V2 if { - ControlNumber := "EXO 2.17" - Requirement := "Advanced audit SHALL be enabled" + PolicyId := "MS.EXO.15.2v1" Output := tests with input as { } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -38,12 +36,11 @@ test_3rdParty_Correct_V2 if { # Policy 3 #-- test_3rdParty_Correct_V3 if { - ControlNumber := "EXO 2.17" - Requirement := "Audit logs SHALL be maintained for at least the minimum duration dictated by OMB M-21-31" + PolicyId := "MS.EXO.15.3v1" Output := tests with input as { } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet diff --git a/Testing/Unit/Rego/EXO/EXOConfig2_16_test.rego b/Testing/Unit/Rego/EXO/EXOConfig_16_test.rego similarity index 59% rename from Testing/Unit/Rego/EXO/EXOConfig2_16_test.rego rename to Testing/Unit/Rego/EXO/EXOConfig_16_test.rego index 182df67c11..c2fff0dc4a 100644 --- a/Testing/Unit/Rego/EXO/EXOConfig2_16_test.rego +++ b/Testing/Unit/Rego/EXO/EXOConfig_16_test.rego @@ -6,12 +6,11 @@ import future.keywords # Policy 1 #-- test_3rdParty_Correct_V1 if { - ControlNumber := "EXO 2.16" - Requirement := "At a minimum, the following alerts SHALL be enabled...[see Exchange Online secure baseline for list]" + PolicyId := "MS.EXO.16.1v1" Output := tests with input as { } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -22,12 +21,11 @@ test_3rdParty_Correct_V1 if { # Policy 2 #-- test_3rdParty_Correct_V2 if { - ControlNumber := "EXO 2.16" - Requirement := "The alerts SHOULD be sent to a monitored address or incorporated into a SIEM" + PolicyId := "MS.EXO.16.1v1" Output := tests with input as { } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet diff --git a/Testing/Unit/Rego/EXO/EXOConfig2_10_test.rego b/Testing/Unit/Rego/EXO/EXOConfig_17_test.rego similarity index 62% rename from Testing/Unit/Rego/EXO/EXOConfig2_10_test.rego rename to Testing/Unit/Rego/EXO/EXOConfig_17_test.rego index 6e42ce7d24..7a9e445942 100644 --- a/Testing/Unit/Rego/EXO/EXOConfig2_10_test.rego +++ b/Testing/Unit/Rego/EXO/EXOConfig_17_test.rego @@ -6,12 +6,11 @@ import future.keywords # Policy 1 #-- test_3rdParty_Correct_V1 if { - ControlNumber := "EXO 2.10" - Requirement := "Emails SHALL be scanned for malware" + PolicyId := "MS.EXO.17.1v1" Output := tests with input as { } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -22,12 +21,11 @@ test_3rdParty_Correct_V1 if { # Policy 2 #-- test_3rdParty_Correct_V2 if { - ControlNumber := "EXO 2.10" - Requirement := "Emails identified as containing malware SHALL be quarantined or dropped" + PolicyId := "MS.EXO.17.2v1" Output := tests with input as { } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -38,12 +36,11 @@ test_3rdParty_Correct_V2 if { # Policy 3 #-- test_3rdParty_Correct_V3 if { - ControlNumber := "EXO 2.10" - Requirement := "Email scanning SHOULD be capable of reviewing emails after delivery" + PolicyId := "MS.EXO.17.3v1" Output := tests with input as { } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet diff --git a/Testing/Unit/Rego/OneDrive/OneDriveConfig2_05_test.rego b/Testing/Unit/Rego/OneDrive/OneDriveConfig2_05_test.rego deleted file mode 100644 index 99c90ff230..0000000000 --- a/Testing/Unit/Rego/OneDrive/OneDriveConfig2_05_test.rego +++ /dev/null @@ -1,44 +0,0 @@ -package onedrive -import future.keywords - - -# -# Policy 1 -#-- -test_BlockMacSync_Correct if { - ControlNumber := "OneDrive 2.5" - Requirement := "OneDrive Client Sync SHALL only be allowed only within the local domain" - - Output := tests with input as { - "Tenant_sync_info": [ - { - "BlockMacSync" : false - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_BlockMacSync_Incorrect if { - ControlNumber := "OneDrive 2.5" - Requirement := "OneDrive Client Sync SHALL only be allowed only within the local domain" - - Output := tests with input as { - "Tenant_sync_info": [ - { - "BlockMacSync" : true - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement not met" -} diff --git a/Testing/Unit/Rego/OneDrive/OneDriveConfig2_06_test.rego b/Testing/Unit/Rego/OneDrive/OneDriveConfig2_06_test.rego deleted file mode 100644 index aa0a29a35a..0000000000 --- a/Testing/Unit/Rego/OneDrive/OneDriveConfig2_06_test.rego +++ /dev/null @@ -1,19 +0,0 @@ -package onedrive -import future.keywords - - -# -# Policy 1 -#-- -test_NotImplemented_Correct if { - ControlNumber := "OneDrive 2.6" - Requirement := "OneDrive Client Sync SHALL be restricted to the local domain" - - Output := tests with input as { } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Currently cannot be checked automatically. See Onedrive Secure Configuration Baseline policy 2.6 for instructions on manual check" -} \ No newline at end of file diff --git a/Testing/Unit/Rego/OneDrive/OneDriveConfig2_07_test.rego b/Testing/Unit/Rego/OneDrive/OneDriveConfig2_07_test.rego deleted file mode 100644 index bd9370cd2a..0000000000 --- a/Testing/Unit/Rego/OneDrive/OneDriveConfig2_07_test.rego +++ /dev/null @@ -1,19 +0,0 @@ -package onedrive -import future.keywords - - -# -# Policy 1 -#-- -test_NotImplemented_Correct if { - ControlNumber := "OneDrive 2.7" - Requirement := "Legacy Authentication SHALL be blocked" - - Output := tests with input as { } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Currently cannot be checked automatically. See Onedrive Secure Configuration Baseline policy 2.7 for instructions on manual check" -} \ No newline at end of file diff --git a/Testing/Unit/Rego/OneDrive/OneDriveConfig2_01_test.rego b/Testing/Unit/Rego/OneDrive/OneDriveConfig_01_test.rego similarity index 56% rename from Testing/Unit/Rego/OneDrive/OneDriveConfig2_01_test.rego rename to Testing/Unit/Rego/OneDrive/OneDriveConfig_01_test.rego index d86ba0647b..8ba2d6deb3 100644 --- a/Testing/Unit/Rego/OneDrive/OneDriveConfig2_01_test.rego +++ b/Testing/Unit/Rego/OneDrive/OneDriveConfig_01_test.rego @@ -1,13 +1,12 @@ package onedrive import future.keywords - +import data.report.utils.NotCheckedDetails # # Policy 1 #-- test_OneDriveLoopSharingCapability_Correct if { - ControlNumber := "OneDrive 2.1" - Requirement := "Anyone links SHOULD be disabled" + PolicyId := "MS.ONEDRIVE.1.1v1" Output := tests with input as { "SPO_tenant_info": [ @@ -18,7 +17,7 @@ test_OneDriveLoopSharingCapability_Correct if { "OneDrive_PnP_Flag": false } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -26,8 +25,7 @@ test_OneDriveLoopSharingCapability_Correct if { } test_OneDriveLoopSharingCapability_Incorrect if { - ControlNumber := "OneDrive 2.1" - Requirement := "Anyone links SHOULD be disabled" + PolicyId := "MS.ONEDRIVE.1.1v1" Output := tests with input as { "SPO_tenant_info": [ @@ -38,7 +36,7 @@ test_OneDriveLoopSharingCapability_Incorrect if { "OneDrive_PnP_Flag": false } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -46,8 +44,7 @@ test_OneDriveLoopSharingCapability_Incorrect if { } test_UsingServicePrincipal if { - ControlNumber := "OneDrive 2.1" - Requirement := "Anyone links SHOULD be disabled" + PolicyId := "MS.ONEDRIVE.1.1v1" Output := tests with input as { "SPO_tenant_info": [ @@ -55,10 +52,10 @@ test_UsingServicePrincipal if { "OneDrive_PnP_Flag": true } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet RuleOutput[0].Criticality == "Should/Not-Implemented" - RuleOutput[0].ReportDetails == "Currently cannot be checked automatically while using Service Principals. See Onedrive Secure Configuration Baseline policy 2.1 for instructions on manual check" + RuleOutput[0].ReportDetails == NotCheckedDetails(PolicyId) } \ No newline at end of file diff --git a/Testing/Unit/Rego/OneDrive/OneDriveConfig2_02_test.rego b/Testing/Unit/Rego/OneDrive/OneDriveConfig_02_test.rego similarity index 58% rename from Testing/Unit/Rego/OneDrive/OneDriveConfig2_02_test.rego rename to Testing/Unit/Rego/OneDrive/OneDriveConfig_02_test.rego index 3e9c5cd3e3..94a71a320a 100644 --- a/Testing/Unit/Rego/OneDrive/OneDriveConfig2_02_test.rego +++ b/Testing/Unit/Rego/OneDrive/OneDriveConfig_02_test.rego @@ -1,12 +1,12 @@ package onedrive import future.keywords +import data.report.utils.NotCheckedDetails # # Policy 1 #-- test_ExternalUserExpirationRequired_Correct_V1 if { - ControlNumber := "OneDrive 2.2" - Requirement := "An expiration date SHOULD be set for Anyone links" + PolicyId := "MS.ONEDRIVE.2.1v1" Output := tests with input as { "SPO_tenant_info": [ @@ -17,7 +17,7 @@ test_ExternalUserExpirationRequired_Correct_V1 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -25,8 +25,7 @@ test_ExternalUserExpirationRequired_Correct_V1 if { } test_ExternalUserExpirationRequired_Correct_V2 if { - ControlNumber := "OneDrive 2.2" - Requirement := "An expiration date SHOULD be set for Anyone links" + PolicyId := "MS.ONEDRIVE.2.1v1" Output := tests with input as { "SPO_tenant_info": [ @@ -37,7 +36,7 @@ test_ExternalUserExpirationRequired_Correct_V2 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -45,8 +44,7 @@ test_ExternalUserExpirationRequired_Correct_V2 if { } test_ExternalUserExpirationRequired_Incorrect if { - ControlNumber := "OneDrive 2.2" - Requirement := "An expiration date SHOULD be set for Anyone links" + PolicyId := "MS.ONEDRIVE.2.1v1" Output := tests with input as { "SPO_tenant_info": [ @@ -57,7 +55,7 @@ test_ExternalUserExpirationRequired_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -65,8 +63,7 @@ test_ExternalUserExpirationRequired_Incorrect if { } test_UsingServicePrincipal if { - ControlNumber := "OneDrive 2.2" - Requirement := "An expiration date SHOULD be set for Anyone links" + PolicyId := "MS.ONEDRIVE.2.1v1" Output := tests with input as { "SPO_tenant_info": [ @@ -74,10 +71,27 @@ test_UsingServicePrincipal if { "OneDrive_PnP_Flag": true } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet RuleOutput[0].Criticality == "Should/Not-Implemented" - RuleOutput[0].ReportDetails == "Currently cannot be checked automatically while using Service Principals. See Onedrive Secure Configuration Baseline policy 2.2 for instructions on manual check" + RuleOutput[0].ReportDetails == NotCheckedDetails(PolicyId) +} + +test_UsingServicePrincipal if { + PolicyId := "MS.ONEDRIVE.2.2v1" + + Output := tests with input as { + "SPO_tenant_info": [ + ], + "OneDrive_PnP_Flag": true + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].Criticality == "Should/Not-Implemented" + RuleOutput[0].ReportDetails == NotCheckedDetails(PolicyId) } \ No newline at end of file diff --git a/Testing/Unit/Rego/OneDrive/OneDriveConfig2_03_test.rego b/Testing/Unit/Rego/OneDrive/OneDriveConfig_03_test.rego similarity index 60% rename from Testing/Unit/Rego/OneDrive/OneDriveConfig2_03_test.rego rename to Testing/Unit/Rego/OneDrive/OneDriveConfig_03_test.rego index 60dfef1df8..7942dad47f 100644 --- a/Testing/Unit/Rego/OneDrive/OneDriveConfig2_03_test.rego +++ b/Testing/Unit/Rego/OneDrive/OneDriveConfig_03_test.rego @@ -1,13 +1,13 @@ package onedrive import future.keywords - +import data.report.utils.NotCheckedDetails +import data.report.utils.ReportDetailsBoolean # # Policy 1 #-- test_DefaultLinkPermission_Correct_V1 if { - ControlNumber := "OneDrive 2.3" - Requirement := "Anyone link permissions SHOULD be limited to View" + PolicyId := "MS.ONEDRIVE.3.1v1" Output := tests with input as { "SPO_tenant_info": [ @@ -19,7 +19,7 @@ test_DefaultLinkPermission_Correct_V1 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -27,8 +27,7 @@ test_DefaultLinkPermission_Correct_V1 if { } test_DefaultLinkPermission_Correct_V2 if { - ControlNumber := "OneDrive 2.3" - Requirement := "Anyone link permissions SHOULD be limited to View" + PolicyId := "MS.ONEDRIVE.3.1v1" Output := tests with input as { "SPO_tenant_info": [ @@ -40,16 +39,15 @@ test_DefaultLinkPermission_Correct_V2 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" + RuleOutput[0].ReportDetails == ReportDetailsBoolean(true) } test_DefaultLinkPermission_Correct_V2 if { - ControlNumber := "OneDrive 2.3" - Requirement := "Anyone link permissions SHOULD be limited to View" + PolicyId := "MS.ONEDRIVE.3.1v1" Output := tests with input as { "SPO_tenant_info": [ @@ -61,16 +59,15 @@ test_DefaultLinkPermission_Correct_V2 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" + RuleOutput[0].ReportDetails == ReportDetailsBoolean(true) } test_DefaultLinkPermission_Incorrect if { - ControlNumber := "OneDrive 2.3" - Requirement := "Anyone link permissions SHOULD be limited to View" + PolicyId := "MS.ONEDRIVE.3.1v1" Output := tests with input as { "SPO_tenant_info": [ @@ -82,7 +79,7 @@ test_DefaultLinkPermission_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -90,8 +87,7 @@ test_DefaultLinkPermission_Incorrect if { } test_DefaultLinkPermission_Incorrect_V2 if { - ControlNumber := "OneDrive 2.3" - Requirement := "Anyone link permissions SHOULD be limited to View" + PolicyId := "MS.ONEDRIVE.3.1v1" Output := tests with input as { "SPO_tenant_info": [ @@ -103,7 +99,7 @@ test_DefaultLinkPermission_Incorrect_V2 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -111,8 +107,7 @@ test_DefaultLinkPermission_Incorrect_V2 if { } test_DefaultLinkPermission_Incorrect_V3 if { - ControlNumber := "OneDrive 2.3" - Requirement := "Anyone link permissions SHOULD be limited to View" + PolicyId := "MS.ONEDRIVE.3.1v1" Output := tests with input as { "SPO_tenant_info": [ @@ -124,7 +119,7 @@ test_DefaultLinkPermission_Incorrect_V3 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -132,8 +127,7 @@ test_DefaultLinkPermission_Incorrect_V3 if { } test_UsingServicePrincipal if { - ControlNumber := "OneDrive 2.3" - Requirement := "Anyone link permissions SHOULD be limited to View" + PolicyId := "MS.ONEDRIVE.3.1v1" Output := tests with input as { "SPO_tenant_info": [ @@ -141,10 +135,10 @@ test_UsingServicePrincipal if { "OneDrive_PnP_Flag": true } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet RuleOutput[0].Criticality == "Should/Not-Implemented" - RuleOutput[0].ReportDetails == "Currently cannot be checked automatically while using Service Principals. See Onedrive Secure Configuration Baseline policy 2.3 for instructions on manual check" + RuleOutput[0].ReportDetails == NotCheckedDetails(PolicyId) } \ No newline at end of file diff --git a/Testing/Unit/Rego/OneDrive/OneDriveConfig2_04_test.rego b/Testing/Unit/Rego/OneDrive/OneDriveConfig_04_test.rego similarity index 54% rename from Testing/Unit/Rego/OneDrive/OneDriveConfig2_04_test.rego rename to Testing/Unit/Rego/OneDrive/OneDriveConfig_04_test.rego index 0a91d91bc1..cfbc3e3111 100644 --- a/Testing/Unit/Rego/OneDrive/OneDriveConfig2_04_test.rego +++ b/Testing/Unit/Rego/OneDrive/OneDriveConfig_04_test.rego @@ -1,13 +1,12 @@ package onedrive import future.keywords - +import data.report.utils.ReportDetailsBoolean # -# Policy 1 +# MS.ONEDRIVE.4.1v1 #-- test_AllowedDomainList_Correct_V1 if { - ControlNumber := "OneDrive 2.4" - Requirement := "OneDrive Client for Windows SHALL be restricted to agency-Defined Domain(s)" + PolicyId := "MS.ONEDRIVE.4.1v1" Output := tests with input as { "Tenant_sync_info": [ @@ -19,16 +18,15 @@ test_AllowedDomainList_Correct_V1 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" + RuleOutput[0].ReportDetails == ReportDetailsBoolean(true) } test_AllowedDomainList_Correct_V2 if { - ControlNumber := "OneDrive 2.4" - Requirement := "OneDrive Client for Windows SHALL be restricted to agency-Defined Domain(s)" + PolicyId := "MS.ONEDRIVE.4.1v1" Output := tests with input as { "Tenant_sync_info": [ @@ -42,16 +40,15 @@ test_AllowedDomainList_Correct_V2 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" + RuleOutput[0].ReportDetails == ReportDetailsBoolean(true) } test_AllowedDomainList_Incorrect if { - ControlNumber := "OneDrive 2.4" - Requirement := "OneDrive Client for Windows SHALL be restricted to agency-Defined Domain(s)" + PolicyId := "MS.ONEDRIVE.4.1v1" Output := tests with input as { "Tenant_sync_info": [ @@ -61,9 +58,9 @@ test_AllowedDomainList_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement not met" + RuleOutput[0].ReportDetails == ReportDetailsBoolean(false) } diff --git a/Testing/Unit/Rego/OneDrive/OneDriveConfig_05_test.rego b/Testing/Unit/Rego/OneDrive/OneDriveConfig_05_test.rego new file mode 100644 index 0000000000..23a802de00 --- /dev/null +++ b/Testing/Unit/Rego/OneDrive/OneDriveConfig_05_test.rego @@ -0,0 +1,42 @@ +package onedrive +import future.keywords +import data.report.utils.ReportDetailsBoolean + +# +# Policy 1 +#-- +test_BlockMacSync_Correct if { + PolicyId := "MS.ONEDRIVE.5.1v1" + + Output := tests with input as { + "Tenant_sync_info": [ + { + "BlockMacSync" : false + } + ] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == ReportDetailsBoolean(true) +} + +test_BlockMacSync_Incorrect if { + PolicyId := "MS.ONEDRIVE.5.1v1" + + Output := tests with input as { + "Tenant_sync_info": [ + { + "BlockMacSync" : true + } + ] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == ReportDetailsBoolean(false) +} diff --git a/Testing/Unit/Rego/OneDrive/OneDriveConfig_06_test.rego b/Testing/Unit/Rego/OneDrive/OneDriveConfig_06_test.rego new file mode 100644 index 0000000000..d168cec45f --- /dev/null +++ b/Testing/Unit/Rego/OneDrive/OneDriveConfig_06_test.rego @@ -0,0 +1,18 @@ +package onedrive +import future.keywords +import data.report.utils.NotCheckedDetails + +# +# Policy 1 +#-- +test_NotImplemented_Correct if { + PolicyId := "MS.ONEDRIVE.6.1v1" + + Output := tests with input as { } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == NotCheckedDetails(PolicyId) +} \ No newline at end of file diff --git a/Testing/Unit/Rego/OneDrive/OneDriveConfig_07_test.rego b/Testing/Unit/Rego/OneDrive/OneDriveConfig_07_test.rego new file mode 100644 index 0000000000..e2568119f9 --- /dev/null +++ b/Testing/Unit/Rego/OneDrive/OneDriveConfig_07_test.rego @@ -0,0 +1,18 @@ +package onedrive +import future.keywords +import data.report.utils.NotCheckedDetails + +# +# Policy 1 +#-- +test_NotImplemented_Correct if { + PolicyId := "MS.ONEDRIVE.7.1v1" + + Output := tests with input as { } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == NotCheckedDetails(PolicyId) +} \ No newline at end of file diff --git a/Testing/Unit/Rego/PowerPlatform/PowerPlatformConfig2_01_test.rego b/Testing/Unit/Rego/PowerPlatform/PowerPlatformConfig2_01_test.rego deleted file mode 100644 index 1c832cb40e..0000000000 --- a/Testing/Unit/Rego/PowerPlatform/PowerPlatformConfig2_01_test.rego +++ /dev/null @@ -1,77 +0,0 @@ -package powerplatform -import future.keywords - - -# -# Policy 1 -#-- -test_disableProductionEnvironmentCreationByNonAdminUsers_Correct if { - ControlNumber := "Power Platform 2.1" - Requirement := "The ability to create production and sandbox environments SHALL be restricted to admins" - - Output := tests with input as { - "environment_creation": [{ - "disableEnvironmentCreationByNonAdminUsers" : true - }] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_disableProductionEnvironmentCreationByNonAdminUsers_Incorrect if { - ControlNumber := "Power Platform 2.1" - Requirement := "The ability to create production and sandbox environments SHALL be restricted to admins" - - Output := tests with input as { - "environment_creation": [{ - "disableEnvironmentCreationByNonAdminUsers" : false - }] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement not met" -} - -# -# Policy 2 -#-- -test_disableTrialEnvironmentCreationByNonAdminUsers_Correct if { - ControlNumber := "Power Platform 2.1" - Requirement := "The ability to create trial environments SHALL be restricted to admins" - - Output := tests with input as { - "environment_creation": [{ - "disableTrialEnvironmentCreationByNonAdminUsers" : true - }] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_disableTrialEnvironmentCreationByNonAdminUsers_Incorrect if { - ControlNumber := "Power Platform 2.1" - Requirement := "The ability to create trial environments SHALL be restricted to admins" - - Output := tests with input as { - "environment_creation": [{ - "disableTrialEnvironmentCreationByNonAdminUsers" : false - }] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement not met" -} \ No newline at end of file diff --git a/Testing/Unit/Rego/PowerPlatform/PowerPlatformConfig2_03_test.rego b/Testing/Unit/Rego/PowerPlatform/PowerPlatformConfig2_03_test.rego deleted file mode 100644 index 9dad2e59db..0000000000 --- a/Testing/Unit/Rego/PowerPlatform/PowerPlatformConfig2_03_test.rego +++ /dev/null @@ -1,60 +0,0 @@ -package powerplatform -import future.keywords - - -# -# Policy 1 -#-- -test_isDisabled_Correct if { - ControlNumber := "Power Platform 2.3" - Requirement := "Power Platform tenant isolation SHALL be enabled" - - Output := tests with input as { - "tenant_isolation": [{ - "properties" : { - "isDisabled" : false - } - }] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_isDisabled_Incorrect if { - ControlNumber := "Power Platform 2.3" - Requirement := "Power Platform tenant isolation SHALL be enabled" - - Output := tests with input as { - "tenant_isolation": [{ - "properties" : { - "isDisabled" : true - } - }] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement not met" -} - -# -# Policy 2 -#-- -test_NotImplemented_Correct if { - ControlNumber := "Power Platform 2.3" - Requirement := "An inbound/outbound connection allowlist SHOULD be configured" - - Output := tests with input as { } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Currently cannot be checked automatically. See Power Platform Secure Configuration Baseline policy 2.3 for instructions on manual check" -} \ No newline at end of file diff --git a/Testing/Unit/Rego/PowerPlatform/PowerPlatformConfig2_04_test.rego b/Testing/Unit/Rego/PowerPlatform/PowerPlatformConfig2_04_test.rego deleted file mode 100644 index fd1076375c..0000000000 --- a/Testing/Unit/Rego/PowerPlatform/PowerPlatformConfig2_04_test.rego +++ /dev/null @@ -1,19 +0,0 @@ -package powerplatform -import future.keywords - - -# -# Policy 1 -#-- -test_NotImplemented_Correct if { - ControlNumber := "Power Platform 2.4" - Requirement := "Content security policies for model-driven Power Apps SHALL be enabled" - - Output := tests with input as { } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Currently cannot be checked automatically. See Power Platform Secure Configuration Baseline policy 2.4 for instructions on manual check" -} \ No newline at end of file diff --git a/Testing/Unit/Rego/PowerPlatform/PowerPlatformConfig_01_test.rego b/Testing/Unit/Rego/PowerPlatform/PowerPlatformConfig_01_test.rego new file mode 100644 index 0000000000..bd4762a806 --- /dev/null +++ b/Testing/Unit/Rego/PowerPlatform/PowerPlatformConfig_01_test.rego @@ -0,0 +1,75 @@ +package powerplatform +import future.keywords + + +# +# Policy 1 +#-- +test_disableProductionEnvironmentCreationByNonAdminUsers_Correct if { + PolicyId := "MS.POWERPLATFORM.1.1v1" + + Output := tests with input as { + "environment_creation": [{ + "disableEnvironmentCreationByNonAdminUsers" : true + }] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "Requirement met" +} + +test_disableProductionEnvironmentCreationByNonAdminUsers_Incorrect if { + PolicyId := "MS.POWERPLATFORM.1.1v1" + + Output := tests with input as { + "environment_creation": [{ + "disableEnvironmentCreationByNonAdminUsers" : false + }] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "Requirement not met" +} + +# TODO: Need to resolve Policy ID +# +#-- +# test_disableTrialEnvironmentCreationByNonAdminUsers_Correct if { +# ControlNumber := "Power Platform 2.1" +# Requirement := "The ability to create trial environments SHALL be restricted to admins" + +# Output := tests with input as { +# "environment_creation": [{ +# "disableTrialEnvironmentCreationByNonAdminUsers" : true +# }] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement met" +# } + +# test_disableTrialEnvironmentCreationByNonAdminUsers_Incorrect if { +# ControlNumber := "Power Platform 2.1" +# Requirement := "The ability to create trial environments SHALL be restricted to admins" + +# Output := tests with input as { +# "environment_creation": [{ +# "disableTrialEnvironmentCreationByNonAdminUsers" : false +# }] +# } + +# RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + +# count(RuleOutput) == 1 +# not RuleOutput[0].RequirementMet +# RuleOutput[0].ReportDetails == "Requirement not met" +# } \ No newline at end of file diff --git a/Testing/Unit/Rego/PowerPlatform/PowerPlatformConfig2_02_test.rego b/Testing/Unit/Rego/PowerPlatform/PowerPlatformConfig_02_test.rego similarity index 67% rename from Testing/Unit/Rego/PowerPlatform/PowerPlatformConfig2_02_test.rego rename to Testing/Unit/Rego/PowerPlatform/PowerPlatformConfig_02_test.rego index 7bf8b97396..46597eec09 100644 --- a/Testing/Unit/Rego/PowerPlatform/PowerPlatformConfig2_02_test.rego +++ b/Testing/Unit/Rego/PowerPlatform/PowerPlatformConfig_02_test.rego @@ -6,8 +6,7 @@ import future.keywords # Policy 1 #-- test_name_Correct if { - ControlNumber := "Power Platform 2.2" - Requirement := "A DLP policy SHALL be created to restrict connector access in the default Power Platform environment" + PolicyId := "MS.POWERPLATFORM.2.1v1" Output := tests with input as { "tenant_id": "Test Id", @@ -21,7 +20,7 @@ test_name_Correct if { }] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -29,8 +28,7 @@ test_name_Correct if { } test_name_Incorrect if { - ControlNumber := "Power Platform 2.2" - Requirement := "A DLP policy SHALL be created to restrict connector access in the default Power Platform environment" + PolicyId := "MS.POWERPLATFORM.2.1v1" Output := tests with input as { "tenant_id": "Test Id", @@ -44,7 +42,7 @@ test_name_Incorrect if { }] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -55,8 +53,7 @@ test_name_Incorrect if { # Policy 2 #-- test_environment_list_Correct if { - ControlNumber := "Power Platform 2.2" - Requirement := "Non-default environments SHOULD have at least one DLP policy that affects them" + PolicyId := "MS.POWERPLATFORM.2.2v1" Output := tests with input as { "dlp_policies": [{ @@ -72,7 +69,7 @@ test_environment_list_Correct if { }] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -80,8 +77,7 @@ test_environment_list_Correct if { } test_environment_list_Incorrect if { - ControlNumber := "Power Platform 2.2" - Requirement := "Non-default environments SHOULD have at least one DLP policy that affects them" + PolicyId := "MS.POWERPLATFORM.2.2v1" Output := tests with input as { "dlp_policies": [{ @@ -102,7 +98,7 @@ test_environment_list_Incorrect if { }] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -113,8 +109,7 @@ test_environment_list_Incorrect if { # Policy 3 #-- test_classification_Correct_V1 if { - ControlNumber := "Power Platform 2.2" - Requirement := "All connectors except those listed...[see Power Platform secure configuration baseline for list]...SHOULD be added to the Blocked category in the default environment policy" + PolicyId := "MS.POWERPLATFORM.2.3v1" Output := tests with input as { "tenant_id": "Test Id", @@ -133,7 +128,7 @@ test_classification_Correct_V1 if { }] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -141,8 +136,7 @@ test_classification_Correct_V1 if { } test_classification_Correct_V2 if { - ControlNumber := "Power Platform 2.2" - Requirement := "All connectors except those listed...[see Power Platform secure configuration baseline for list]...SHOULD be added to the Blocked category in the default environment policy" + PolicyId := "MS.POWERPLATFORM.2.3v1" Output := tests with input as { "tenant_id": "Test Id", @@ -161,7 +155,7 @@ test_classification_Correct_V2 if { }] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -169,8 +163,7 @@ test_classification_Correct_V2 if { } test_connectorGroups_Correct if { - ControlNumber := "Power Platform 2.2" - Requirement := "All connectors except those listed...[see Power Platform secure configuration baseline for list]...SHOULD be added to the Blocked category in the default environment policy" + PolicyId := "MS.POWERPLATFORM.2.3v1" Output := tests with input as { "tenant_id": "Test Id", @@ -195,7 +188,7 @@ test_connectorGroups_Correct if { }] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -203,8 +196,7 @@ test_connectorGroups_Correct if { } test_classification_Incorrect_V1 if { - ControlNumber := "Power Platform 2.2" - Requirement := "All connectors except those listed...[see Power Platform secure configuration baseline for list]...SHOULD be added to the Blocked category in the default environment policy" + PolicyId := "MS.POWERPLATFORM.2.3v1" Output := tests with input as { "tenant_id": "Test Id", @@ -223,7 +215,7 @@ test_classification_Incorrect_V1 if { }] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -231,8 +223,7 @@ test_classification_Incorrect_V1 if { } test_classification_Incorrect_V2 if { - ControlNumber := "Power Platform 2.2" - Requirement := "All connectors except those listed...[see Power Platform secure configuration baseline for list]...SHOULD be added to the Blocked category in the default environment policy" + PolicyId := "MS.POWERPLATFORM.2.3v1" Output := tests with input as { "tenant_id": "Test Id", @@ -251,7 +242,7 @@ test_classification_Incorrect_V2 if { }] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -259,8 +250,7 @@ test_classification_Incorrect_V2 if { } test_connectorGroups_Incorrect if { - ControlNumber := "Power Platform 2.2" - Requirement := "All connectors except those listed...[see Power Platform secure configuration baseline for list]...SHOULD be added to the Blocked category in the default environment policy" + PolicyId := "MS.POWERPLATFORM.2.3v1" Output := tests with input as { "tenant_id": "Test Id", @@ -285,7 +275,7 @@ test_connectorGroups_Incorrect if { }] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet diff --git a/Testing/Unit/Rego/PowerPlatform/PowerPlatformConfig_03_test.rego b/Testing/Unit/Rego/PowerPlatform/PowerPlatformConfig_03_test.rego new file mode 100644 index 0000000000..f19fe9ec58 --- /dev/null +++ b/Testing/Unit/Rego/PowerPlatform/PowerPlatformConfig_03_test.rego @@ -0,0 +1,57 @@ +package powerplatform +import future.keywords +import data.report.utils.NotCheckedDetails + +# +# Policy 1 +#-- +test_isDisabled_Correct if { + PolicyId := "MS.POWERPLATFORM.3.1v1" + + Output := tests with input as { + "tenant_isolation": [{ + "properties" : { + "isDisabled" : false + } + }] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "Requirement met" +} + +test_isDisabled_Incorrect if { + PolicyId := "MS.POWERPLATFORM.3.1v1" + + Output := tests with input as { + "tenant_isolation": [{ + "properties" : { + "isDisabled" : true + } + }] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "Requirement not met" +} + +# +# Policy 2 +#-- +test_NotImplemented_Correct if { + PolicyId := "MS.POWERPLATFORM.3.2v1" + + Output := tests with input as { } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == NotCheckedDetails(PolicyId) +} \ No newline at end of file diff --git a/Testing/Unit/Rego/PowerPlatform/PowerPlatformConfig_04_test.rego b/Testing/Unit/Rego/PowerPlatform/PowerPlatformConfig_04_test.rego new file mode 100644 index 0000000000..50ce7d5820 --- /dev/null +++ b/Testing/Unit/Rego/PowerPlatform/PowerPlatformConfig_04_test.rego @@ -0,0 +1,18 @@ +package powerplatform +import future.keywords +import data.report.utils.NotCheckedDetails + +# +# Policy 1 +#-- +test_NotImplemented_Correct if { + PolicyId := "MS.POWERPLATFORM.4.1v1" + + Output := tests with input as { } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == NotCheckedDetails(PolicyId) +} \ No newline at end of file diff --git a/Testing/Unit/Rego/Sharepoint/SharepointConfig2_03_test.rego b/Testing/Unit/Rego/Sharepoint/SharepointConfig2_03_test.rego deleted file mode 100644 index a4a4fb52a6..0000000000 --- a/Testing/Unit/Rego/Sharepoint/SharepointConfig2_03_test.rego +++ /dev/null @@ -1,19 +0,0 @@ -package sharepoint -import future.keywords - - -# -# Policy 1 -#-- -test_NotImplemented_Correct if { - ControlNumber := "Sharepoint 2.3" - Requirement := "Sharing settings for specific SharePoint sites SHOULD align to their sensitivity level" - - Output := tests with input as { } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Currently cannot be checked automatically. See Sharepoint Secure Configuration Baseline policy 2.3 for instructions on manual check" -} \ No newline at end of file diff --git a/Testing/Unit/Rego/Sharepoint/SharepointConfig2_01_test.rego b/Testing/Unit/Rego/Sharepoint/SharepointConfig_01_test.rego similarity index 53% rename from Testing/Unit/Rego/Sharepoint/SharepointConfig2_01_test.rego rename to Testing/Unit/Rego/Sharepoint/SharepointConfig_01_test.rego index 6dbf62e6b1..ba1b014859 100644 --- a/Testing/Unit/Rego/Sharepoint/SharepointConfig2_01_test.rego +++ b/Testing/Unit/Rego/Sharepoint/SharepointConfig_01_test.rego @@ -6,8 +6,7 @@ import future.keywords # Policy 1 #-- test_DefaultSharingLinkType_Correct if { - ControlNumber := "Sharepoint 2.1" - Requirement := "File and folder links default sharing setting SHALL be set to \"Specific People (Only the People the User Specifies)\"" + PolicyId := "MS.SHAREPOINT.1.1v1" Output := tests with input as { "SPO_tenant": [ @@ -17,7 +16,7 @@ test_DefaultSharingLinkType_Correct if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -25,8 +24,7 @@ test_DefaultSharingLinkType_Correct if { } test_DefaultSharingLinkType_Incorrect if { - ControlNumber := "Sharepoint 2.1" - Requirement := "File and folder links default sharing setting SHALL be set to \"Specific People (Only the People the User Specifies)\"" + PolicyId := "MS.SHAREPOINT.1.1v1" Output := tests with input as { "SPO_tenant": [ @@ -36,7 +34,7 @@ test_DefaultSharingLinkType_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet diff --git a/Testing/Unit/Rego/Sharepoint/SharepointConfig2_02_test.rego b/Testing/Unit/Rego/Sharepoint/SharepointConfig_02_test.rego similarity index 53% rename from Testing/Unit/Rego/Sharepoint/SharepointConfig2_02_test.rego rename to Testing/Unit/Rego/Sharepoint/SharepointConfig_02_test.rego index 46f421d633..1953086f7d 100644 --- a/Testing/Unit/Rego/Sharepoint/SharepointConfig2_02_test.rego +++ b/Testing/Unit/Rego/Sharepoint/SharepointConfig_02_test.rego @@ -6,9 +6,8 @@ import future.keywords # Policy 1 #-- test_SharingCapability_Correct_V1 if { - ControlNumber := "Sharepoint 2.2" - Requirement := "External sharing SHOULD be limited to approved domains and security groups per interagency collaboration needs" - + PolicyId := "MS.SHAREPOINT.1.3v1" + Output := tests with input as { "SPO_tenant": [ { @@ -17,7 +16,7 @@ test_SharingCapability_Correct_V1 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -25,8 +24,7 @@ test_SharingCapability_Correct_V1 if { } test_SharingCapability_Correct_V2 if { - ControlNumber := "Sharepoint 2.2" - Requirement := "External sharing SHOULD be limited to approved domains and security groups per interagency collaboration needs" + PolicyId := "MS.SHAREPOINT.1.3v1" Output := tests with input as { "SPO_tenant": [ @@ -36,7 +34,7 @@ test_SharingCapability_Correct_V2 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -44,8 +42,7 @@ test_SharingCapability_Correct_V2 if { } test_SharingCapability_Incorrect if { - ControlNumber := "Sharepoint 2.2" - Requirement := "External sharing SHOULD be limited to approved domains and security groups per interagency collaboration needs" + PolicyId := "MS.SHAREPOINT.1.3v1" Output := tests with input as { "SPO_tenant": [ @@ -55,7 +52,7 @@ test_SharingCapability_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet diff --git a/Testing/Unit/Rego/Sharepoint/SharepointConfig_03_test.rego b/Testing/Unit/Rego/Sharepoint/SharepointConfig_03_test.rego new file mode 100644 index 0000000000..c63204f413 --- /dev/null +++ b/Testing/Unit/Rego/Sharepoint/SharepointConfig_03_test.rego @@ -0,0 +1,18 @@ +package sharepoint +import future.keywords +import data.report.utils.NotCheckedDetails + +# +# Policy 1 +#-- +test_NotImplemented_Correct if { + PolicyId := "MS.SHAREPOINT.2.1v1" + + Output := tests with input as { } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == NotCheckedDetails(PolicyId) +} \ No newline at end of file diff --git a/Testing/Unit/Rego/Sharepoint/SharepointConfig2_04_test.rego b/Testing/Unit/Rego/Sharepoint/SharepointConfig_04_test.rego similarity index 81% rename from Testing/Unit/Rego/Sharepoint/SharepointConfig2_04_test.rego rename to Testing/Unit/Rego/Sharepoint/SharepointConfig_04_test.rego index 0d1e1dd80c..89406e7263 100644 --- a/Testing/Unit/Rego/Sharepoint/SharepointConfig2_04_test.rego +++ b/Testing/Unit/Rego/Sharepoint/SharepointConfig_04_test.rego @@ -6,8 +6,7 @@ import future.keywords # Policy 1 #-- test_SharingCapability_Correct_V1 if { - ControlNumber := "Sharepoint 2.4" - Requirement := "Expiration timer for 'Guest access to a site or OneDrive' should be set to 30 days" + PolicyId := "MS.SHAREPOINT.3.1v1" Output := tests with input as { "SPO_tenant": [ @@ -19,7 +18,7 @@ test_SharingCapability_Correct_V1 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -27,8 +26,7 @@ test_SharingCapability_Correct_V1 if { } test_SharingCapability_Correct_V2 if { - ControlNumber := "Sharepoint 2.4" - Requirement := "Expiration timer for 'Guest access to a site or OneDrive' should be set to 30 days" + PolicyId := "MS.SHAREPOINT.3.1v1" Output := tests with input as { "SPO_tenant": [ @@ -40,7 +38,7 @@ test_SharingCapability_Correct_V2 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -48,8 +46,7 @@ test_SharingCapability_Correct_V2 if { } test_SharingCapability_Correct_V3 if { - ControlNumber := "Sharepoint 2.4" - Requirement := "Expiration timer for 'Guest access to a site or OneDrive' should be set to 30 days" + PolicyId := "MS.SHAREPOINT.3.1v1" Output := tests with input as { "SPO_tenant": [ @@ -61,7 +58,7 @@ test_SharingCapability_Correct_V3 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -69,8 +66,7 @@ test_SharingCapability_Correct_V3 if { } test_SharingCapability_Correct_V4 if { - ControlNumber := "Sharepoint 2.4" - Requirement := "Expiration timer for 'Guest access to a site or OneDrive' should be set to 30 days" + PolicyId := "MS.SHAREPOINT.3.1v1" Output := tests with input as { "SPO_tenant": [ @@ -82,7 +78,7 @@ test_SharingCapability_Correct_V4 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -90,8 +86,7 @@ test_SharingCapability_Correct_V4 if { } test_SharingCapability_Correct_V5 if { - ControlNumber := "Sharepoint 2.4" - Requirement := "Expiration timer for 'Guest access to a site or OneDrive' should be set to 30 days" + PolicyId := "MS.SHAREPOINT.3.1v1" Output := tests with input as { "SPO_tenant": [ @@ -103,7 +98,7 @@ test_SharingCapability_Correct_V5 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -111,8 +106,7 @@ test_SharingCapability_Correct_V5 if { } test_SharingCapability_Correct_V6 if { - ControlNumber := "Sharepoint 2.4" - Requirement := "Expiration timer for 'Guest access to a site or OneDrive' should be set to 30 days" + PolicyId := "MS.SHAREPOINT.3.1v1" Output := tests with input as { "SPO_tenant": [ @@ -124,7 +118,7 @@ test_SharingCapability_Correct_V6 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -132,8 +126,7 @@ test_SharingCapability_Correct_V6 if { } test_Multi_Correct if { - ControlNumber := "Sharepoint 2.4" - Requirement := "Expiration timer for 'Guest access to a site or OneDrive' should be set to 30 days" + PolicyId := "MS.SHAREPOINT.3.1v1" Output := tests with input as { "SPO_tenant": [ @@ -145,7 +138,7 @@ test_Multi_Correct if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -153,8 +146,7 @@ test_Multi_Correct if { } test_ExternalUserExpirationRequired_Incorrect if { - ControlNumber := "Sharepoint 2.4" - Requirement := "Expiration timer for 'Guest access to a site or OneDrive' should be set to 30 days" + PolicyId := "MS.SHAREPOINT.3.1v1" Output := tests with input as { "SPO_tenant": [ @@ -166,7 +158,7 @@ test_ExternalUserExpirationRequired_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -174,8 +166,7 @@ test_ExternalUserExpirationRequired_Incorrect if { } test_ExternalUserExpireInDays_Incorrect_V1 if { - ControlNumber := "Sharepoint 2.4" - Requirement := "Expiration timer for 'Guest access to a site or OneDrive' should be set to 30 days" + PolicyId := "MS.SHAREPOINT.3.1v1" Output := tests with input as { "SPO_tenant": [ @@ -187,7 +178,7 @@ test_ExternalUserExpireInDays_Incorrect_V1 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -195,8 +186,7 @@ test_ExternalUserExpireInDays_Incorrect_V1 if { } test_ExternalUserExpireInDays_Incorrect_V2 if { - ControlNumber := "Sharepoint 2.4" - Requirement := "Expiration timer for 'Guest access to a site or OneDrive' should be set to 30 days" + PolicyId := "MS.SHAREPOINT.3.1v1" Output := tests with input as { "SPO_tenant": [ @@ -208,7 +198,7 @@ test_ExternalUserExpireInDays_Incorrect_V2 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -216,8 +206,7 @@ test_ExternalUserExpireInDays_Incorrect_V2 if { } test_Multi_Incorrect_V1 if { - ControlNumber := "Sharepoint 2.4" - Requirement := "Expiration timer for 'Guest access to a site or OneDrive' should be set to 30 days" + PolicyId := "MS.SHAREPOINT.3.1v1" Output := tests with input as { "SPO_tenant": [ @@ -229,7 +218,7 @@ test_Multi_Incorrect_V1 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -237,8 +226,7 @@ test_Multi_Incorrect_V1 if { } test_Multi_Incorrect_V2 if { - ControlNumber := "Sharepoint 2.4" - Requirement := "Expiration timer for 'Guest access to a site or OneDrive' should be set to 30 days" + PolicyId := "MS.SHAREPOINT.3.1v1" Output := tests with input as { "SPO_tenant": [ @@ -250,7 +238,7 @@ test_Multi_Incorrect_V2 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet diff --git a/Testing/Unit/Rego/Sharepoint/SharepointConfig2_05_test.rego b/Testing/Unit/Rego/Sharepoint/SharepointConfig_05_test.rego similarity index 90% rename from Testing/Unit/Rego/Sharepoint/SharepointConfig2_05_test.rego rename to Testing/Unit/Rego/Sharepoint/SharepointConfig_05_test.rego index 54166eaeac..450c50cdf9 100644 --- a/Testing/Unit/Rego/Sharepoint/SharepointConfig2_05_test.rego +++ b/Testing/Unit/Rego/Sharepoint/SharepointConfig_05_test.rego @@ -1,11 +1,13 @@ package sharepoint import future.keywords +import data.report.utils.NotCheckedDetails # # Policy 1 #-- test_NotImplemented_Correct if { ControlNumber := "Sharepoint 2.5" + PolicyId := "MS.SHAREPOINT.TBD" Requirement := "Users SHALL be prevented from running custom scripts on personal sites (OneDrive)" Output := tests with input as { } @@ -14,7 +16,7 @@ test_NotImplemented_Correct if { count(RuleOutput) == 1 not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Currently cannot be checked automatically. See Sharepoint Secure Configuration Baseline policy 2.5 for instructions on manual check" + RuleOutput[0].ReportDetails == NotCheckedDetails(PolicyId) } # diff --git a/Testing/Unit/Rego/Teams/TeamsConfig2_11_test.rego b/Testing/Unit/Rego/Teams/TeamsConfig2_11_test.rego deleted file mode 100644 index 16ba4a1f9f..0000000000 --- a/Testing/Unit/Rego/Teams/TeamsConfig2_11_test.rego +++ /dev/null @@ -1,51 +0,0 @@ -package teams -import future.keywords - - -# -# Policy 1 -#-- -test_3rdParty_Correct_V1 if { - ControlNumber := "Teams 2.11" - Requirement := "A DLP solution SHALL be enabled" - - Output := tests with input as { } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check" -} - -# -# Policy 2 -#-- -test_3rdParty_Correct_V2 if { - ControlNumber := "Teams 2.11" - Requirement := "Agencies SHOULD use either the native DLP solution offered by Microsoft or a DLP solution that offers comparable services" - - Output := tests with input as { } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check" -} - -# -# Policy 3 -#-- -test_3rdParty_Correct_V3 if { - ControlNumber := "Teams 2.11" - Requirement := "The DLP solution SHALL protect Personally Identifiable Information (PII) and sensitive information, as defined by the agency. At a minimum, the sharing of credit card numbers, taxpayer Identification Numbers (TIN), and Social Security Numbers (SSN) via email SHALL be restricted" - - Output := tests with input as { } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check" -} \ No newline at end of file diff --git a/Testing/Unit/Rego/Teams/TeamsConfig2_01_test.rego b/Testing/Unit/Rego/Teams/TeamsConfig_01_test.rego similarity index 56% rename from Testing/Unit/Rego/Teams/TeamsConfig2_01_test.rego rename to Testing/Unit/Rego/Teams/TeamsConfig_01_test.rego index 605e7ec827..84f3c8db12 100644 --- a/Testing/Unit/Rego/Teams/TeamsConfig2_01_test.rego +++ b/Testing/Unit/Rego/Teams/TeamsConfig_01_test.rego @@ -6,8 +6,7 @@ import future.keywords # Policy 1 #-- test_ExternalParticipantControl_Correct_V1 if { - ControlNumber := "Teams 2.1" - Requirement := "External participants SHOULD NOT be enabled to request control of shared desktops or windows in the Global (Org-wide default) meeting policy or in custom meeting policies if any exist" + PolicyId := "MS.TEAMS.1.1v1" Output := tests with input as { "meeting_policies": [ { @@ -17,7 +16,7 @@ test_ExternalParticipantControl_Correct_V1 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -25,18 +24,17 @@ test_ExternalParticipantControl_Correct_V1 if { } test_ExternalParticipantControl_Correct_V2 if { - ControlNumber := "Teams 2.1" - Requirement := "External participants SHOULD NOT be enabled to request control of shared desktops or windows in the Global (Org-wide default) meeting policy or in custom meeting policies if any exist" + PolicyId := "MS.TEAMS.1.1v1" Output := tests with input as { - "meeting_policies": [ - { - "Identity": "Tag:FirstCustomPolicy", - "AllowExternalParticipantGiveRequestControl" : false - } - ] + "meeting_policies": [ + { + "Identity": "Tag:FirstCustomPolicy", + "AllowExternalParticipantGiveRequestControl" : false + } + ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -44,8 +42,7 @@ test_ExternalParticipantControl_Correct_V2 if { } test_ExternalParticipantControl_Incorrect_V1 if { - ControlNumber := "Teams 2.1" - Requirement := "External participants SHOULD NOT be enabled to request control of shared desktops or windows in the Global (Org-wide default) meeting policy or in custom meeting policies if any exist" + PolicyId := "MS.TEAMS.1.1v1" Output := tests with input as { "meeting_policies": [ { @@ -55,7 +52,7 @@ test_ExternalParticipantControl_Incorrect_V1 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -63,8 +60,7 @@ test_ExternalParticipantControl_Incorrect_V1 if { } test_ExternalParticipantControl_Incorrect_V2 if { - ControlNumber := "Teams 2.1" - Requirement := "External participants SHOULD NOT be enabled to request control of shared desktops or windows in the Global (Org-wide default) meeting policy or in custom meeting policies if any exist" + PolicyId := "MS.TEAMS.1.1v1" Output := tests with input as { "meeting_policies": [ { @@ -74,7 +70,7 @@ test_ExternalParticipantControl_Incorrect_V2 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -82,8 +78,7 @@ test_ExternalParticipantControl_Incorrect_V2 if { } test_ExternalParticipantControl_MultiplePolicies if { - ControlNumber := "Teams 2.1" - Requirement := "External participants SHOULD NOT be enabled to request control of shared desktops or windows in the Global (Org-wide default) meeting policy or in custom meeting policies if any exist" + PolicyId := "MS.TEAMS.1.1v1" Output := tests with input as { "meeting_policies": [ { @@ -101,7 +96,7 @@ test_ExternalParticipantControl_MultiplePolicies if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet diff --git a/Testing/Unit/Rego/Teams/TeamsConfig2_02_test.rego b/Testing/Unit/Rego/Teams/TeamsConfig_02_test.rego similarity index 63% rename from Testing/Unit/Rego/Teams/TeamsConfig2_02_test.rego rename to Testing/Unit/Rego/Teams/TeamsConfig_02_test.rego index 39676b227f..6e7f2dfee0 100644 --- a/Testing/Unit/Rego/Teams/TeamsConfig2_02_test.rego +++ b/Testing/Unit/Rego/Teams/TeamsConfig_02_test.rego @@ -6,9 +6,8 @@ import future.keywords # Policy 1 #-- test_AnonymousMeetingStart_Correct_V1 if { - ControlNumber := "Teams 2.2" - Requirement := "Anonymous users SHALL NOT be enabled to start meetings in the Global (Org-wide default) meeting policy or in custom meeting policies if any exist" - + PolicyId := "MS.TEAMS.2.1v1" + Output := tests with input as { "meeting_policies": [ { @@ -18,7 +17,7 @@ test_AnonymousMeetingStart_Correct_V1 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -26,8 +25,7 @@ test_AnonymousMeetingStart_Correct_V1 if { } test_AnonymousMeetingStart_Correct_V2 if { - ControlNumber := "Teams 2.2" - Requirement := "Anonymous users SHALL NOT be enabled to start meetings in the Global (Org-wide default) meeting policy or in custom meeting policies if any exist" + PolicyId := "MS.TEAMS.2.1v1" Output := tests with input as { "meeting_policies": [ @@ -38,7 +36,7 @@ test_AnonymousMeetingStart_Correct_V2 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -46,8 +44,7 @@ test_AnonymousMeetingStart_Correct_V2 if { } test_AnonymousMeetingStart_Incorrect_V1 if { - ControlNumber := "Teams 2.2" - Requirement := "Anonymous users SHALL NOT be enabled to start meetings in the Global (Org-wide default) meeting policy or in custom meeting policies if any exist" + PolicyId := "MS.TEAMS.2.1v1" Output := tests with input as { "meeting_policies": [ @@ -58,7 +55,7 @@ test_AnonymousMeetingStart_Incorrect_V1 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -66,8 +63,7 @@ test_AnonymousMeetingStart_Incorrect_V1 if { } test_AnonymousMeetingStart_Incorrect_V2 if { - ControlNumber := "Teams 2.2" - Requirement := "Anonymous users SHALL NOT be enabled to start meetings in the Global (Org-wide default) meeting policy or in custom meeting policies if any exist" + PolicyId := "MS.TEAMS.2.1v1" Output := tests with input as { "meeting_policies": [ @@ -78,7 +74,7 @@ test_AnonymousMeetingStart_Incorrect_V2 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -86,8 +82,7 @@ test_AnonymousMeetingStart_Incorrect_V2 if { } test_AnonymousMeetingStart_MultiplePolicies if { - ControlNumber := "Teams 2.2" - Requirement := "Anonymous users SHALL NOT be enabled to start meetings in the Global (Org-wide default) meeting policy or in custom meeting policies if any exist" + PolicyId := "MS.TEAMS.2.1v1" Output := tests with input as { "meeting_policies": [ @@ -106,7 +101,7 @@ test_AnonymousMeetingStart_MultiplePolicies if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet diff --git a/Testing/Unit/Rego/Teams/TeamsConfig2_03_test.rego b/Testing/Unit/Rego/Teams/TeamsConfig_03_test.rego similarity index 65% rename from Testing/Unit/Rego/Teams/TeamsConfig2_03_test.rego rename to Testing/Unit/Rego/Teams/TeamsConfig_03_test.rego index d4c416043f..6bf4e26ce7 100644 --- a/Testing/Unit/Rego/Teams/TeamsConfig2_03_test.rego +++ b/Testing/Unit/Rego/Teams/TeamsConfig_03_test.rego @@ -6,8 +6,7 @@ import future.keywords # Policy 1 #-- test_meeting_policies_Correct if { - ControlNumber := "Teams 2.3" - Requirement := "Anonymous users, including dial-in users, SHOULD NOT be admitted automatically" + PolicyId := "MS.TEAMS.3.1v1" Output := tests with input as { "meeting_policies": [ @@ -19,7 +18,7 @@ test_meeting_policies_Correct if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -27,8 +26,7 @@ test_meeting_policies_Correct if { } test_AllowPSTNUsersToBypassLobby_Incorrect if { - ControlNumber := "Teams 2.3" - Requirement := "Anonymous users, including dial-in users, SHOULD NOT be admitted automatically" + PolicyId := "MS.TEAMS.3.1v1" Output := tests with input as { "meeting_policies": [ @@ -40,7 +38,7 @@ test_AllowPSTNUsersToBypassLobby_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -48,8 +46,7 @@ test_AllowPSTNUsersToBypassLobby_Incorrect if { } test_AutoAdmittedUsers_Incorrect if { - ControlNumber := "Teams 2.3" - Requirement := "Anonymous users, including dial-in users, SHOULD NOT be admitted automatically" + PolicyId := "MS.TEAMS.3.1v1" Output := tests with input as { "meeting_policies": [ @@ -61,7 +58,7 @@ test_AutoAdmittedUsers_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -70,8 +67,7 @@ test_AutoAdmittedUsers_Incorrect if { # It shouldn't matter that the custom policy is incorrect as this policy only applies to the Global policy test_Multiple_Correct if { - ControlNumber := "Teams 2.3" - Requirement := "Anonymous users, including dial-in users, SHOULD NOT be admitted automatically" + PolicyId := "MS.TEAMS.3.1v1" Output := tests with input as { "meeting_policies": [ @@ -88,7 +84,7 @@ test_Multiple_Correct if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -99,8 +95,7 @@ test_Multiple_Correct if { # Policy 2 #-- test_AutoAdmittedUsers_Correct_V1 if { - ControlNumber := "Teams 2.3" - Requirement := "Internal users SHOULD be admitted automatically" + PolicyId := "MS.TEAMS.3.2v1" Output := tests with input as { "meeting_policies": [ @@ -111,7 +106,7 @@ test_AutoAdmittedUsers_Correct_V1 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -119,8 +114,7 @@ test_AutoAdmittedUsers_Correct_V1 if { } test_AutoAdmittedUsers_Correct_V2 if { - ControlNumber := "Teams 2.3" - Requirement := "Internal users SHOULD be admitted automatically" + PolicyId := "MS.TEAMS.3.2v1" Output := tests with input as { "meeting_policies": [ @@ -131,7 +125,7 @@ test_AutoAdmittedUsers_Correct_V2 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -139,8 +133,7 @@ test_AutoAdmittedUsers_Correct_V2 if { } test_AutoAdmittedUsers_Incorrect_V2 if { - ControlNumber := "Teams 2.3" - Requirement := "Internal users SHOULD be admitted automatically" + PolicyId := "MS.TEAMS.3.2v1" Output := tests with input as { "meeting_policies": [ @@ -151,7 +144,7 @@ test_AutoAdmittedUsers_Incorrect_V2 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -159,8 +152,7 @@ test_AutoAdmittedUsers_Incorrect_V2 if { } test_AutoAdmittedUsers_Incorrect_V3 if { - ControlNumber := "Teams 2.3" - Requirement := "Internal users SHOULD be admitted automatically" + PolicyId := "MS.TEAMS.3.2v1" Output := tests with input as { "meeting_policies": [ @@ -171,7 +163,7 @@ test_AutoAdmittedUsers_Incorrect_V3 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet diff --git a/Testing/Unit/Rego/Teams/TeamsConfig2_04_test.rego b/Testing/Unit/Rego/Teams/TeamsConfig_04_test.rego similarity index 82% rename from Testing/Unit/Rego/Teams/TeamsConfig2_04_test.rego rename to Testing/Unit/Rego/Teams/TeamsConfig_04_test.rego index 5c3b20dfe1..05f4a81a4a 100644 --- a/Testing/Unit/Rego/Teams/TeamsConfig2_04_test.rego +++ b/Testing/Unit/Rego/Teams/TeamsConfig_04_test.rego @@ -6,8 +6,7 @@ import future.keywords # Policy 1 #-- test_AllowFederatedUsers_Correct_V1 if { - ControlNumber := "Teams 2.4" - Requirement := "External access SHALL only be enabled on a per-domain basis" + PolicyId := "MS.TEAMS.4.1v1" Output := tests with input as { "federation_configuration": [ @@ -19,7 +18,7 @@ test_AllowFederatedUsers_Correct_V1 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -27,8 +26,7 @@ test_AllowFederatedUsers_Correct_V1 if { } test_AllowFederatedUsers_Correct_V2 if { - ControlNumber := "Teams 2.4" - Requirement := "External access SHALL only be enabled on a per-domain basis" + PolicyId := "MS.TEAMS.4.1v1" Output := tests with input as { "federation_configuration": [ @@ -44,7 +42,7 @@ test_AllowFederatedUsers_Correct_V2 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -52,8 +50,7 @@ test_AllowFederatedUsers_Correct_V2 if { } test_AllowedDomains_Correct if { - ControlNumber := "Teams 2.4" - Requirement := "External access SHALL only be enabled on a per-domain basis" + PolicyId := "MS.TEAMS.4.1v1" Output := tests with input as { "federation_configuration":[ @@ -69,7 +66,7 @@ test_AllowedDomains_Correct if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -77,8 +74,7 @@ test_AllowedDomains_Correct if { } test_AllowedDomains_Incorrect if { - ControlNumber := "Teams 2.4" - Requirement := "External access SHALL only be enabled on a per-domain basis" + PolicyId := "MS.TEAMS.4.1v1" Output := tests with input as { "federation_configuration": [ @@ -90,7 +86,7 @@ test_AllowedDomains_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -98,8 +94,7 @@ test_AllowedDomains_Incorrect if { } test_AllowFederatedUsers_Correct_V1_multi if { - ControlNumber := "Teams 2.4" - Requirement := "External access SHALL only be enabled on a per-domain basis" + PolicyId := "MS.TEAMS.4.1v1" Output := tests with input as { "federation_configuration": [ @@ -116,7 +111,7 @@ test_AllowFederatedUsers_Correct_V1_multi if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -124,8 +119,7 @@ test_AllowFederatedUsers_Correct_V1_multi if { } test_AllowFederatedUsers_Correct_V2_multi if { - ControlNumber := "Teams 2.4" - Requirement := "External access SHALL only be enabled on a per-domain basis" + PolicyId := "MS.TEAMS.4.1v1" Output := tests with input as { "federation_configuration": [ @@ -150,7 +144,7 @@ test_AllowFederatedUsers_Correct_V2_multi if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -159,8 +153,7 @@ test_AllowFederatedUsers_Correct_V2_multi if { test_AllowedDomains_Correct_multi if { - ControlNumber := "Teams 2.4" - Requirement := "External access SHALL only be enabled on a per-domain basis" + PolicyId := "MS.TEAMS.4.1v1" Output := tests with input as { "federation_configuration":[ @@ -185,7 +178,7 @@ test_AllowedDomains_Correct_multi if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -193,8 +186,7 @@ test_AllowedDomains_Correct_multi if { } test_AllowedDomains_Incorrect_multi if { - ControlNumber := "Teams 2.4" - Requirement := "External access SHALL only be enabled on a per-domain basis" + PolicyId := "MS.TEAMS.4.1v1" Output := tests with input as { "federation_configuration":[ @@ -211,7 +203,7 @@ test_AllowedDomains_Incorrect_multi if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet diff --git a/Testing/Unit/Rego/Teams/TeamsConfig2_05_test.rego b/Testing/Unit/Rego/Teams/TeamsConfig_05_test.rego similarity index 69% rename from Testing/Unit/Rego/Teams/TeamsConfig2_05_test.rego rename to Testing/Unit/Rego/Teams/TeamsConfig_05_test.rego index 5f0d3c1d66..a4091fc018 100644 --- a/Testing/Unit/Rego/Teams/TeamsConfig2_05_test.rego +++ b/Testing/Unit/Rego/Teams/TeamsConfig_05_test.rego @@ -6,8 +6,7 @@ import future.keywords # Policy 1 #-- test_AllowTeamsConsumerInbound_Correct_V1 if { - ControlNumber := "Teams 2.5" - Requirement := "Unmanaged users SHALL NOT be enabled to initiate contact with internal users" + PolicyId := "MS.TEAMS.5.1v1" Output := tests with input as { "federation_configuration": [ @@ -19,7 +18,7 @@ test_AllowTeamsConsumerInbound_Correct_V1 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -27,8 +26,7 @@ test_AllowTeamsConsumerInbound_Correct_V1 if { } test_AllowTeamsConsumerInbound_Correct_V1_multi if { - ControlNumber := "Teams 2.5" - Requirement := "Unmanaged users SHALL NOT be enabled to initiate contact with internal users" + PolicyId := "MS.TEAMS.5.1v1" Output := tests with input as { "federation_configuration": [ @@ -45,7 +43,7 @@ test_AllowTeamsConsumerInbound_Correct_V1_multi if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -53,8 +51,7 @@ test_AllowTeamsConsumerInbound_Correct_V1_multi if { } test_AllowTeamsConsumerInbound_Correct_V2 if { - ControlNumber := "Teams 2.5" - Requirement := "Unmanaged users SHALL NOT be enabled to initiate contact with internal users" + PolicyId := "MS.TEAMS.5.1v1" Output := tests with input as { "federation_configuration": [ @@ -66,7 +63,7 @@ test_AllowTeamsConsumerInbound_Correct_V2 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -74,8 +71,7 @@ test_AllowTeamsConsumerInbound_Correct_V2 if { } test_AllowTeamsConsumerInbound_Correct_V2_multi if { - ControlNumber := "Teams 2.5" - Requirement := "Unmanaged users SHALL NOT be enabled to initiate contact with internal users" + PolicyId := "MS.TEAMS.5.1v1" Output := tests with input as { "federation_configuration": [ @@ -92,7 +88,7 @@ test_AllowTeamsConsumerInbound_Correct_V2_multi if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -100,8 +96,7 @@ test_AllowTeamsConsumerInbound_Correct_V2_multi if { } test_AllowTeamsConsumer_Incorrect if { - ControlNumber := "Teams 2.5" - Requirement := "Unmanaged users SHALL NOT be enabled to initiate contact with internal users" + PolicyId := "MS.TEAMS.5.1v1" Output := tests with input as { "federation_configuration": [ @@ -113,7 +108,7 @@ test_AllowTeamsConsumer_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -121,8 +116,7 @@ test_AllowTeamsConsumer_Incorrect if { } test_AllowTeamsConsumer_Incorrect_multi if { - ControlNumber := "Teams 2.5" - Requirement := "Unmanaged users SHALL NOT be enabled to initiate contact with internal users" + PolicyId := "MS.TEAMS.5.1v1" Output := tests with input as { "federation_configuration": [ @@ -139,7 +133,7 @@ test_AllowTeamsConsumer_Incorrect_multi if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -147,8 +141,7 @@ test_AllowTeamsConsumer_Incorrect_multi if { } test_AllowTeamsConsumer_Incorrect if { - ControlNumber := "Teams 2.5" - Requirement := "Unmanaged users SHALL NOT be enabled to initiate contact with internal users" + PolicyId := "MS.TEAMS.5.1v1" Output := tests with input as { "federation_configuration": [ @@ -160,7 +153,7 @@ test_AllowTeamsConsumer_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -168,8 +161,7 @@ test_AllowTeamsConsumer_Incorrect if { } test_AllowTeamsConsumer_Incorrect_multi if { - ControlNumber := "Teams 2.5" - Requirement := "Unmanaged users SHALL NOT be enabled to initiate contact with internal users" + PolicyId := "MS.TEAMS.5.1v1" Output := tests with input as { "federation_configuration": [ @@ -186,7 +178,7 @@ test_AllowTeamsConsumer_Incorrect_multi if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -196,8 +188,7 @@ test_AllowTeamsConsumer_Incorrect_multi if { # Policy 2 #-- test_AllowTeamsConsumer_Correct if { - ControlNumber := "Teams 2.5" - Requirement := "Internal users SHOULD NOT be enabled to initiate contact with unmanaged users" + PolicyId := "MS.TEAMS.5.2v1" Output := tests with input as { "federation_configuration": [ @@ -209,7 +200,7 @@ test_AllowTeamsConsumer_Correct if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -217,8 +208,7 @@ test_AllowTeamsConsumer_Correct if { } test_AllowTeamsConsumer_Correct_multi if { - ControlNumber := "Teams 2.5" - Requirement := "Internal users SHOULD NOT be enabled to initiate contact with unmanaged users" + PolicyId := "MS.TEAMS.5.2v1" Output := tests with input as { "federation_configuration": [ @@ -235,7 +225,7 @@ test_AllowTeamsConsumer_Correct_multi if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -243,8 +233,7 @@ test_AllowTeamsConsumer_Correct_multi if { } test_AllowTeamsConsumer_Incorrect if { - ControlNumber := "Teams 2.5" - Requirement := "Internal users SHOULD NOT be enabled to initiate contact with unmanaged users" + PolicyId := "MS.TEAMS.5.2v1" Output := tests with input as { "federation_configuration": [ @@ -256,7 +245,7 @@ test_AllowTeamsConsumer_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -264,8 +253,7 @@ test_AllowTeamsConsumer_Incorrect if { } test_AllowTeamsConsumer_Incorrect_multi if { - ControlNumber := "Teams 2.5" - Requirement := "Internal users SHOULD NOT be enabled to initiate contact with unmanaged users" + PolicyId := "MS.TEAMS.5.2v1" Output := tests with input as { "federation_configuration": [ @@ -282,7 +270,7 @@ test_AllowTeamsConsumer_Incorrect_multi if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet diff --git a/Testing/Unit/Rego/Teams/TeamsConfig2_06_test.rego b/Testing/Unit/Rego/Teams/TeamsConfig_06_test.rego similarity index 68% rename from Testing/Unit/Rego/Teams/TeamsConfig2_06_test.rego rename to Testing/Unit/Rego/Teams/TeamsConfig_06_test.rego index afc9e5147f..6ba72a4833 100644 --- a/Testing/Unit/Rego/Teams/TeamsConfig2_06_test.rego +++ b/Testing/Unit/Rego/Teams/TeamsConfig_06_test.rego @@ -6,8 +6,7 @@ import future.keywords # Policy 1 #-- test_AllowPublicUsers_Correct if { - ControlNumber := "Teams 2.6" - Requirement := "Contact with Skype users SHALL be blocked" + PolicyId := "MS.TEAMS.6.1v1" Output := tests with input as { "federation_configuration": [ @@ -18,7 +17,7 @@ test_AllowPublicUsers_Correct if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -26,8 +25,7 @@ test_AllowPublicUsers_Correct if { } test_AllowPublicUsers_InCorrect if { - ControlNumber := "Teams 2.6" - Requirement := "Contact with Skype users SHALL be blocked" + PolicyId := "MS.TEAMS.6.1v1" Output := tests with input as { "federation_configuration": [ @@ -38,7 +36,7 @@ test_AllowPublicUsers_InCorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -46,8 +44,7 @@ test_AllowPublicUsers_InCorrect if { } test_AllowPublicUsers_Correct_multi if { - ControlNumber := "Teams 2.6" - Requirement := "Contact with Skype users SHALL be blocked" + PolicyId := "MS.TEAMS.6.1v1" Output := tests with input as { "federation_configuration": [ @@ -62,7 +59,7 @@ test_AllowPublicUsers_Correct_multi if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -70,8 +67,7 @@ test_AllowPublicUsers_Correct_multi if { } test_AllowPublicUsers_InCorrect_multi if { - ControlNumber := "Teams 2.6" - Requirement := "Contact with Skype users SHALL be blocked" + PolicyId := "MS.TEAMS.6.1v1" Output := tests with input as { "federation_configuration": [ @@ -86,7 +82,7 @@ test_AllowPublicUsers_InCorrect_multi if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet diff --git a/Testing/Unit/Rego/Teams/TeamsConfig2_07_test.rego b/Testing/Unit/Rego/Teams/TeamsConfig_07_test.rego similarity index 73% rename from Testing/Unit/Rego/Teams/TeamsConfig2_07_test.rego rename to Testing/Unit/Rego/Teams/TeamsConfig_07_test.rego index d51cf34025..b75c8fbba1 100644 --- a/Testing/Unit/Rego/Teams/TeamsConfig2_07_test.rego +++ b/Testing/Unit/Rego/Teams/TeamsConfig_07_test.rego @@ -6,8 +6,7 @@ import future.keywords # Policy 1 #-- test_AllowEmailIntoChannel_Correct_V1 if { - ControlNumber := "Teams 2.7" - Requirement := "Teams email integration SHALL be disabled" + PolicyId := "MS.TEAMS.7.1v1" Output := tests with input as { "client_configuration": [ @@ -27,15 +26,15 @@ test_AllowEmailIntoChannel_Correct_V1 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + count(RuleOutput) == 1 RuleOutput[0].RequirementMet RuleOutput[0].ReportDetails == "Requirement met" } test_AllowEmailIntoChannel_Correct_V1_multi if { - ControlNumber := "Teams 2.7" - Requirement := "Teams email integration SHALL be disabled" + PolicyId := "MS.TEAMS.7.1v1" Output := tests with input as { "client_configuration": [ @@ -59,15 +58,15 @@ test_AllowEmailIntoChannel_Correct_V1_multi if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + count(RuleOutput) == 1 RuleOutput[0].RequirementMet RuleOutput[0].ReportDetails == "Requirement met" } test_AllowEmailIntoChannel_Incorrect if { - ControlNumber := "Teams 2.7" - Requirement := "Teams email integration SHALL be disabled" + PolicyId := "MS.TEAMS.7.1v1" Output := tests with input as { "client_configuration": [ @@ -87,15 +86,15 @@ test_AllowEmailIntoChannel_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + count(RuleOutput) == 1 not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement not met" + RuleOutput[0].ReportDetails == "1 Requirement not met: Email integration is enabled across domain: Global" } test_AllowEmailIntoChannel_Incorrect_multi if { - ControlNumber := "Teams 2.7" - Requirement := "Teams email integration SHALL be disabled" + PolicyId := "MS.TEAMS.7.1v1" Output := tests with input as { "client_configuration": [ @@ -119,15 +118,15 @@ test_AllowEmailIntoChannel_Incorrect_multi if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + count(RuleOutput) == 1 not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement not met" + RuleOutput[0].ReportDetails == "2 Requirement not met: Email integration is enabled across domain: Global, Tag:AllOn" } test_AllowEmailIntoChannel_Correct_V2 if { - ControlNumber := "Teams 2.7" - Requirement := "Teams email integration SHALL be disabled" + PolicyId := "MS.TEAMS.7.1v1" Output := tests with input as { "client_configuration": [ @@ -147,15 +146,15 @@ test_AllowEmailIntoChannel_Correct_V2 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + count(RuleOutput) == 1 RuleOutput[0].RequirementMet RuleOutput[0].ReportDetails == "N/A: Feature is unavailable in GCC environments" } test_AllowEmailIntoChannel_Correct_V2_multi if { - ControlNumber := "Teams 2.7" - Requirement := "Teams email integration SHALL be disabled" + PolicyId := "MS.TEAMS.7.1v1" Output := tests with input as { "client_configuration": [ @@ -179,15 +178,15 @@ test_AllowEmailIntoChannel_Correct_V2_multi if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + count(RuleOutput) == 1 RuleOutput[0].RequirementMet RuleOutput[0].ReportDetails == "N/A: Feature is unavailable in GCC environments" } test_AllowEmailIntoChannel_Correct_V3 if { - ControlNumber := "Teams 2.7" - Requirement := "Teams email integration SHALL be disabled" + PolicyId := "MS.TEAMS.7.1v1" Output := tests with input as { "client_configuration": [ @@ -207,15 +206,15 @@ test_AllowEmailIntoChannel_Correct_V3 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + count(RuleOutput) == 1 RuleOutput[0].RequirementMet RuleOutput[0].ReportDetails == "N/A: Feature is unavailable in GCC environments" } -test_AllowEmailIntoChannel_Correct_V4 if { - ControlNumber := "Teams 2.7" - Requirement := "Teams email integration SHALL be disabled" +test_AllowEmailIntoChannel_Correct_V3_multi if { + PolicyId := "MS.TEAMS.7.1v1" Output := tests with input as { "client_configuration": [ @@ -239,15 +238,15 @@ test_AllowEmailIntoChannel_Correct_V4 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + count(RuleOutput) == 1 RuleOutput[0].RequirementMet RuleOutput[0].ReportDetails == "N/A: Feature is unavailable in GCC environments" } -test_AllowEmailIntoChannel_Correct_V5 if { - ControlNumber := "Teams 2.7" - Requirement := "Teams email integration SHALL be disabled" +test_AllowEmailIntoChannel_Correct_V4 if { + PolicyId := "MS.TEAMS.7.1v1" Output := tests with input as { "client_configuration": [ @@ -271,7 +270,40 @@ test_AllowEmailIntoChannel_Correct_V5 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "N/A: Feature is unavailable in GCC environments" +} + +test_AllowEmailIntoChannel_Correct_V4_multi if { + PolicyId := "MS.TEAMS.7.1v1" + + Output := tests with input as { + "client_configuration": [ + { + "Identity": "Global", + "AllowEmailIntoChannel": true + }, + { + "Identity": "Tag:AllOn", + "AllowEmailIntoChannel": true + } + ], + "teams_tenant_info": [ + { + "AssignedPlan": [ + "MCOEV", + "Teams_GCCHIGH", + "MCOProfessional" + ] + } + ] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + count(RuleOutput) == 1 RuleOutput[0].RequirementMet RuleOutput[0].ReportDetails == "N/A: Feature is unavailable in GCC environments" diff --git a/Testing/Unit/Rego/Teams/TeamsConfig2_08_test.rego b/Testing/Unit/Rego/Teams/TeamsConfig_08_test.rego similarity index 62% rename from Testing/Unit/Rego/Teams/TeamsConfig2_08_test.rego rename to Testing/Unit/Rego/Teams/TeamsConfig_08_test.rego index 7c40b2efc0..27c32978ef 100644 --- a/Testing/Unit/Rego/Teams/TeamsConfig2_08_test.rego +++ b/Testing/Unit/Rego/Teams/TeamsConfig_08_test.rego @@ -1,13 +1,13 @@ package teams import future.keywords +import data.report.utils.NotCheckedDetails # # Policy 1 #-- test_DefaultCatalogAppsType_Correct_V1 if { - ControlNumber := "Teams 2.8" - Requirement := "Agencies SHOULD allow all apps published by Microsoft, but MAY block specific Microsoft apps as needed" + PolicyId := "MS.TEAMS.8.1v1" Output := tests with input as { "app_policies": [ @@ -18,7 +18,7 @@ test_DefaultCatalogAppsType_Correct_V1 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -26,8 +26,7 @@ test_DefaultCatalogAppsType_Correct_V1 if { } test_DefaultCatalogAppsType_Correct_V2 if { - ControlNumber := "Teams 2.8" - Requirement := "Agencies SHOULD allow all apps published by Microsoft, but MAY block specific Microsoft apps as needed" + PolicyId := "MS.TEAMS.8.1v1" Output := tests with input as { "app_policies": [ @@ -38,7 +37,7 @@ test_DefaultCatalogAppsType_Correct_V2 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -46,8 +45,7 @@ test_DefaultCatalogAppsType_Correct_V2 if { } test_DefaultCatalogAppsType_Incorrect_V1 if { - ControlNumber := "Teams 2.8" - Requirement := "Agencies SHOULD allow all apps published by Microsoft, but MAY block specific Microsoft apps as needed" + PolicyId := "MS.TEAMS.8.1v1" Output := tests with input as { "app_policies": [ @@ -58,7 +56,7 @@ test_DefaultCatalogAppsType_Incorrect_V1 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -66,8 +64,7 @@ test_DefaultCatalogAppsType_Incorrect_V1 if { } test_DefaultCatalogAppsType_Incorrect_V2 if { - ControlNumber := "Teams 2.8" - Requirement := "Agencies SHOULD allow all apps published by Microsoft, but MAY block specific Microsoft apps as needed" + PolicyId := "MS.TEAMS.8.1v1" Output := tests with input as { "app_policies": [ @@ -78,7 +75,7 @@ test_DefaultCatalogAppsType_Incorrect_V2 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -86,8 +83,7 @@ test_DefaultCatalogAppsType_Incorrect_V2 if { } test_DefaultCatalogAppsType_Multiple if { - ControlNumber := "Teams 2.8" - Requirement := "Agencies SHOULD allow all apps published by Microsoft, but MAY block specific Microsoft apps as needed" + PolicyId := "MS.TEAMS.8.1v1" Output := tests with input as { "app_policies": [ @@ -106,7 +102,7 @@ test_DefaultCatalogAppsType_Multiple if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -119,8 +115,7 @@ test_DefaultCatalogAppsType_Multiple if { # Policy 2 #-- test_GlobalCatalogAppsType_Correct_V1 if { - ControlNumber := "Teams 2.8" - Requirement := "Agencies SHOULD NOT allow installation of all third-party apps, but MAY allow specific apps as needed" + PolicyId := "MS.TEAMS.8.2v1" Output := tests with input as { "app_policies": [ @@ -131,7 +126,7 @@ test_GlobalCatalogAppsType_Correct_V1 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -139,8 +134,7 @@ test_GlobalCatalogAppsType_Correct_V1 if { } test_GlobalCatalogAppsType_Correct_V2 if { - ControlNumber := "Teams 2.8" - Requirement := "Agencies SHOULD NOT allow installation of all third-party apps, but MAY allow specific apps as needed" + PolicyId := "MS.TEAMS.8.2v1" Output := tests with input as { "app_policies": [ @@ -151,7 +145,7 @@ test_GlobalCatalogAppsType_Correct_V2 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -159,8 +153,7 @@ test_GlobalCatalogAppsType_Correct_V2 if { } test_GlobalCatalogAppsType_Incorrect_V1 if { - ControlNumber := "Teams 2.8" - Requirement := "Agencies SHOULD NOT allow installation of all third-party apps, but MAY allow specific apps as needed" + PolicyId := "MS.TEAMS.8.2v1" Output := tests with input as { "app_policies": [ @@ -171,7 +164,7 @@ test_GlobalCatalogAppsType_Incorrect_V1 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -179,8 +172,7 @@ test_GlobalCatalogAppsType_Incorrect_V1 if { } test_GlobalCatalogAppsType_Incorrect_V2 if { - ControlNumber := "Teams 2.8" - Requirement := "Agencies SHOULD NOT allow installation of all third-party apps, but MAY allow specific apps as needed" + PolicyId := "MS.TEAMS.8.2v1" Output := tests with input as { "app_policies": [ @@ -191,7 +183,7 @@ test_GlobalCatalogAppsType_Incorrect_V2 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -199,8 +191,7 @@ test_GlobalCatalogAppsType_Incorrect_V2 if { } test_GlobalCatalogAppsType_Multiple if { - ControlNumber := "Teams 2.8" - Requirement := "Agencies SHOULD NOT allow installation of all third-party apps, but MAY allow specific apps as needed" + PolicyId := "MS.TEAMS.8.2v1" Output := tests with input as { "app_policies": [ @@ -219,7 +210,7 @@ test_GlobalCatalogAppsType_Multiple if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -229,8 +220,7 @@ test_GlobalCatalogAppsType_Multiple if { } test_PrivateCatalogAppsType_Correct_V1 if { - ControlNumber := "Teams 2.8" - Requirement := "Agencies SHOULD NOT allow installation of all custom apps, but MAY allow specific apps as needed" + PolicyId := "MS.TEAMS.8.2av1" Output := tests with input as { "app_policies": [ @@ -241,7 +231,7 @@ test_PrivateCatalogAppsType_Correct_V1 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -249,8 +239,7 @@ test_PrivateCatalogAppsType_Correct_V1 if { } test_PrivateCatalogAppsType_Correct_V2 if { - ControlNumber := "Teams 2.8" - Requirement := "Agencies SHOULD NOT allow installation of all custom apps, but MAY allow specific apps as needed" + PolicyId := "MS.TEAMS.8.2av1" Output := tests with input as { "app_policies": [ @@ -261,7 +250,7 @@ test_PrivateCatalogAppsType_Correct_V2 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -269,8 +258,7 @@ test_PrivateCatalogAppsType_Correct_V2 if { } test_PrivateCatalogAppsType_Incorrect_V1 if { - ControlNumber := "Teams 2.8" - Requirement := "Agencies SHOULD NOT allow installation of all custom apps, but MAY allow specific apps as needed" + PolicyId := "MS.TEAMS.8.2av1" Output := tests with input as { "app_policies": [ @@ -281,7 +269,7 @@ test_PrivateCatalogAppsType_Incorrect_V1 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -289,8 +277,7 @@ test_PrivateCatalogAppsType_Incorrect_V1 if { } test_PrivateCatalogAppsType_Incorrect_V2 if { - ControlNumber := "Teams 2.8" - Requirement := "Agencies SHOULD NOT allow installation of all custom apps, but MAY allow specific apps as needed" + PolicyId := "MS.TEAMS.8.2av1" Output := tests with input as { "app_policies": [ @@ -301,7 +288,7 @@ test_PrivateCatalogAppsType_Incorrect_V2 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -309,8 +296,7 @@ test_PrivateCatalogAppsType_Incorrect_V2 if { } test_PrivateCatalogAppsType_Multiple if { - ControlNumber := "Teams 2.8" - Requirement := "Agencies SHOULD NOT allow installation of all custom apps, but MAY allow specific apps as needed" + PolicyId := "MS.TEAMS.8.2av1" Output := tests with input as { "app_policies": [ @@ -329,7 +315,7 @@ test_PrivateCatalogAppsType_Multiple if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -342,14 +328,13 @@ test_PrivateCatalogAppsType_Multiple if { # Policy 3 #-- test_3rdParty_Correct if { - ControlNumber := "Teams 2.8" - Requirement := "Agencies SHALL establish policy dictating the app review and approval process to be used by the agency" + PolicyId := "MS.TEAMS.8.3v1" Output := tests with input as { } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Cannot be checked automatically. See Microsoft Teams Secure Configuration Baseline policy 2.8 for instructions on manual check" + RuleOutput[0].ReportDetails == NotCheckedDetails(PolicyId) } \ No newline at end of file diff --git a/Testing/Unit/Rego/Teams/TeamsConfig2_09_test.rego b/Testing/Unit/Rego/Teams/TeamsConfig_09_test.rego similarity index 64% rename from Testing/Unit/Rego/Teams/TeamsConfig2_09_test.rego rename to Testing/Unit/Rego/Teams/TeamsConfig_09_test.rego index 2513b670aa..3ab6f6ddff 100644 --- a/Testing/Unit/Rego/Teams/TeamsConfig2_09_test.rego +++ b/Testing/Unit/Rego/Teams/TeamsConfig_09_test.rego @@ -6,8 +6,7 @@ import future.keywords # Policy 1 #-- test_AllowCloudRecording_Correct if { - ControlNumber := "Teams 2.9" - Requirement := "Cloud video recording SHOULD be disabled in the global (org-wide default) meeting policy" + PolicyId := "MS.TEAMS.9.1v1" Output := tests with input as { "meeting_policies": [ @@ -18,7 +17,7 @@ test_AllowCloudRecording_Correct if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -26,8 +25,7 @@ test_AllowCloudRecording_Correct if { } test_AllowCloudRecording_Incorrect if { - ControlNumber := "Teams 2.9" - Requirement := "Cloud video recording SHOULD be disabled in the global (org-wide default) meeting policy" + PolicyId := "MS.TEAMS.9.1v1" Output := tests with input as { "meeting_policies": [ @@ -38,7 +36,7 @@ test_AllowCloudRecording_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -46,8 +44,7 @@ test_AllowCloudRecording_Incorrect if { } test_AllowCloudRecording_Multiple if { - ControlNumber := "Teams 2.9" - Requirement := "Cloud video recording SHOULD be disabled in the global (org-wide default) meeting policy" + PolicyId := "MS.TEAMS.9.1v1" Output := tests with input as { "meeting_policies": [ @@ -63,7 +60,7 @@ test_AllowCloudRecording_Multiple if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -74,8 +71,7 @@ test_AllowCloudRecording_Multiple if { # Policy 2 #-- test_AllowCloudRecording_Correct_V1 if { - ControlNumber := "Teams 2.9" - Requirement := "For all meeting polices that allow cloud recording, recordings SHOULD be stored inside the country of that agency's tenant" + PolicyId := "MS.TEAMS.9.3v1" Output := tests with input as { "meeting_policies": [ @@ -87,7 +83,7 @@ test_AllowCloudRecording_Correct_V1 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -95,8 +91,7 @@ test_AllowCloudRecording_Correct_V1 if { } test_AllowCloudRecording_Correct_V2 if { - ControlNumber := "Teams 2.9" - Requirement := "For all meeting polices that allow cloud recording, recordings SHOULD be stored inside the country of that agency's tenant" + PolicyId := "MS.TEAMS.9.3v1" Output := tests with input as { "meeting_policies": [ @@ -108,7 +103,7 @@ test_AllowCloudRecording_Correct_V2 if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -116,8 +111,7 @@ test_AllowCloudRecording_Correct_V2 if { } test_AllowCloudRecording_Incorrect if { - ControlNumber := "Teams 2.9" - Requirement := "For all meeting polices that allow cloud recording, recordings SHOULD be stored inside the country of that agency's tenant" + PolicyId := "MS.TEAMS.9.3v1" Output := tests with input as { "meeting_policies": [ @@ -129,7 +123,7 @@ test_AllowCloudRecording_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -137,8 +131,7 @@ test_AllowCloudRecording_Incorrect if { } test_AllowCloudRecording_Multiple if { - ControlNumber := "Teams 2.9" - Requirement := "For all meeting polices that allow cloud recording, recordings SHOULD be stored inside the country of that agency's tenant" + PolicyId := "MS.TEAMS.9.3v1" Output := tests with input as { "meeting_policies": [ @@ -155,7 +148,7 @@ test_AllowCloudRecording_Multiple if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet diff --git a/Testing/Unit/Rego/Teams/TeamsConfig2_10_test.rego b/Testing/Unit/Rego/Teams/TeamsConfig_10_test.rego similarity index 66% rename from Testing/Unit/Rego/Teams/TeamsConfig2_10_test.rego rename to Testing/Unit/Rego/Teams/TeamsConfig_10_test.rego index 6b94ff69bf..52ae9d59db 100644 --- a/Testing/Unit/Rego/Teams/TeamsConfig2_10_test.rego +++ b/Testing/Unit/Rego/Teams/TeamsConfig_10_test.rego @@ -6,8 +6,7 @@ import future.keywords # Policy 1 #-- test_BroadcastRecordingMode_Correct if { - ControlNumber := "Teams 2.10" - Requirement := "Record an event SHOULD be set to Organizer can record" + PolicyId := "MS.TEAMS.10.1v1" Output := tests with input as { "broadcast_policies": [ @@ -18,7 +17,7 @@ test_BroadcastRecordingMode_Correct if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -26,8 +25,7 @@ test_BroadcastRecordingMode_Correct if { } test_BroadcastRecordingMode_Incorrect if { - ControlNumber := "Teams 2.10" - Requirement := "Record an event SHOULD be set to Organizer can record" + PolicyId := "MS.TEAMS.10.1v1" Output := tests with input as { "broadcast_policies": [ @@ -38,7 +36,7 @@ test_BroadcastRecordingMode_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -47,8 +45,7 @@ test_BroadcastRecordingMode_Incorrect if { test_BroadcastRecordingMode_Multiple if { - ControlNumber := "Teams 2.10" - Requirement := "Record an event SHOULD be set to Organizer can record" + PolicyId := "MS.TEAMS.10.1v1" Output := tests with input as { "broadcast_policies": [ @@ -63,7 +60,7 @@ test_BroadcastRecordingMode_Multiple if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet diff --git a/Testing/Unit/Rego/Teams/TeamsConfig2_13_test.rego b/Testing/Unit/Rego/Teams/TeamsConfig_11_test.rego similarity index 63% rename from Testing/Unit/Rego/Teams/TeamsConfig2_13_test.rego rename to Testing/Unit/Rego/Teams/TeamsConfig_11_test.rego index b1da9e5446..cf2930f589 100644 --- a/Testing/Unit/Rego/Teams/TeamsConfig2_13_test.rego +++ b/Testing/Unit/Rego/Teams/TeamsConfig_11_test.rego @@ -6,12 +6,11 @@ import future.keywords # Policy 1 #-- test_3rdParty_Correct_V1 if { - ControlNumber := "Teams 2.13" - Requirement := "URL comparison with a block-list SHOULD be enabled" + PolicyId := "MS.TEAMS.11.1v1" Output := tests with input as { } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -22,12 +21,11 @@ test_3rdParty_Correct_V1 if { # Policy 2 #-- test_3rdParty_Correct_V2 if { - ControlNumber := "Teams 2.13" - Requirement := "Direct download links SHOULD be scanned for malware" + PolicyId := "MS.TEAMS.11.2v1" Output := tests with input as { } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -38,12 +36,11 @@ test_3rdParty_Correct_V2 if { # Policy 3 #-- test_3rdParty_Correct_V3 if { - ControlNumber := "Teams 2.13" - Requirement := "User click tracking SHOULD be enabled" + PolicyId := "MS.TEAMS.11.4v1" Output := tests with input as { } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet diff --git a/Testing/Unit/Rego/Teams/TeamsConfig2_12_test.rego b/Testing/Unit/Rego/Teams/TeamsConfig_12_test.rego similarity index 61% rename from Testing/Unit/Rego/Teams/TeamsConfig2_12_test.rego rename to Testing/Unit/Rego/Teams/TeamsConfig_12_test.rego index 3a9262c9af..99cbfc672b 100644 --- a/Testing/Unit/Rego/Teams/TeamsConfig2_12_test.rego +++ b/Testing/Unit/Rego/Teams/TeamsConfig_12_test.rego @@ -6,12 +6,11 @@ import future.keywords # Policy 1 #-- test_3rdParty_Correct_V1 if { - ControlNumber := "Teams 2.12" - Requirement := "Attachments included with Teams messages SHOULD be scanned for malware" + PolicyId := "MS.TEAMS.12.1v1" Output := tests with input as { } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet @@ -22,12 +21,11 @@ test_3rdParty_Correct_V1 if { # Policy 2 #-- test_3rdParty_Correct_V2 if { - ControlNumber := "Teams 2.12" - Requirement := "Users SHOULD be prevented from opening or downloading files detected as malware" + PolicyId := "MS.TEAMS.12.2v1" Output := tests with input as { } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet diff --git a/Testing/Unit/Rego/Teams/TeamsConfig_13_test.rego b/Testing/Unit/Rego/Teams/TeamsConfig_13_test.rego new file mode 100644 index 0000000000..aa66765abb --- /dev/null +++ b/Testing/Unit/Rego/Teams/TeamsConfig_13_test.rego @@ -0,0 +1,48 @@ +package teams +import future.keywords + + +# +# Policy 1 +#-- +test_3rdParty_Correct_V1 if { + PolicyId := "MS.TEAMS.13.1v1" + + Output := tests with input as { } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check" +} + +# +# Policy 2 +#-- +test_3rdParty_Correct_V2 if { + PolicyId := "MS.TEAMS.13.2v1" + + Output := tests with input as { } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check" +} + +# +# Policy 3 +#-- +test_3rdParty_Correct_V3 if { + PolicyId := "MS.TEAMS.13.3v1" + + Output := tests with input as { } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check" +} \ No newline at end of file diff --git a/baselines/aad.md b/baselines/aad.md index 8052d30c32..a6ead4a6cb 100644 --- a/baselines/aad.md +++ b/baselines/aad.md @@ -461,7 +461,7 @@ If the Azure AD Provisioning Service is used to provision users to SaaS apps or #### MS.AAD.5.4v1 -The logs SHALL be sent to the agencys SOC for monitoring. +The logs SHALL be sent to the agency's SOC for monitoring. - _Rationale:_ TODO - _Last modified:_ June 2023 diff --git a/baselines/exo.md b/baselines/exo.md index 7e913386f4..43ae38a47b 100644 --- a/baselines/exo.md +++ b/baselines/exo.md @@ -198,8 +198,8 @@ Docs](https://docs.microsoft.com/en-us/microsoft-365/security/office-365-securit 8. Return to the DKIM page on the Defender admin center to finish enabling DKIM. -## 4 Domain-Based Message Authentication, Reporting, and Conformance (DMARC) +## 4. Domain-Based Message Authentication, Reporting, and Conformance (DMARC) Domain-based Message Authentication, Reporting, and Conformance (DMARC) works with SPF and DKIM to authenticate mail senders and ensure that destination email systems can validate messages sent from your domain. diff --git a/baselines/teams.md b/baselines/teams.md index ad0498066d..10c0e1f345 100644 --- a/baselines/teams.md +++ b/baselines/teams.md @@ -750,4 +750,4 @@ Dr. Mukesh Rohatgi (MITRE), Lee Szilagyi (MITRE), Nanda Katikaneni [^1]: Note that B2B guest users and all anonymous users except for external users appear in Teams calls as *John Doe (Guest)*. To avoid any potential confusion this may cause, true guest users are always - referred to as B2B guest users in this document. + referred to as B2B guest users in this document. \ No newline at end of file From b82249ab8d7ff8a8e30333407c1a06b8fa8800bf Mon Sep 17 00:00:00 2001 From: Richard Crutchfield Date: Fri, 2 Jun 2023 15:17:56 -0400 Subject: [PATCH 03/33] Add quiet mode for invoke-scuba (#357) * Add quiet option --- .../ScubaGear/Modules/Orchestrator.psm1 | 35 +++++++++++-------- .../Invoke-ReportCreation.Tests.ps1 | 16 +++++++++ .../Orchestrator/Invoke-Scuba.Tests.ps1 | 10 +++++- 3 files changed, 46 insertions(+), 15 deletions(-) diff --git a/PowerShell/ScubaGear/Modules/Orchestrator.psm1 b/PowerShell/ScubaGear/Modules/Orchestrator.psm1 index 8732885277..d82492f200 100644 --- a/PowerShell/ScubaGear/Modules/Orchestrator.psm1 +++ b/PowerShell/ScubaGear/Modules/Orchestrator.psm1 @@ -78,6 +78,8 @@ function Invoke-SCuBA { tool for use in specific tests. .Parameter DarkMode Set switch to enable report dark mode by default. + .Parameter Quiet + Do not launch external browser for report. .Example Invoke-SCuBA Run an assessment against by default a commercial M365 Tenant against the @@ -199,7 +201,11 @@ function Invoke-SCuBA { [Parameter(Mandatory = $false, ParameterSetName = 'Report')] [ValidateNotNullOrEmpty()] [switch] - $DarkMode + $DarkMode, + + [Parameter(Mandatory = $false, ParameterSetName = 'Report')] + [switch] + $Quiet ) process { # Retrive ScubaGear Module versions @@ -313,14 +319,15 @@ function Invoke-SCuBA { # Converted back from JSON String for PS Object use $TenantDetails = $TenantDetails | ConvertFrom-Json $ReportParams = @{ - 'ProductNames' = $ScubaConfig.ProductNames; - 'TenantDetails' = $TenantDetails; - 'ModuleVersion' = $ModuleVersion; - 'OutFolderPath' = $OutFolderPath; - 'OutProviderFileName' = $ScubaConfig.OutProviderFileName; - 'OutRegoFileName' = $ScubaConfig.OutRegoFileName; - 'OutReportName' = $ScubaConfig.OutReportName; - 'DarkMode' = $DarkMode; + 'ProductNames' = $ScubaConfig.ProductNames + 'TenantDetails' = $TenantDetails + 'ModuleVersion' = $ModuleVersion + 'OutFolderPath' = $OutFolderPath + 'OutProviderFileName' = $ScubaConfig.OutProviderFileName + 'OutRegoFileName' = $ScubaConfig.OutRegoFileName + 'OutReportName' = $ScubaConfig.OutReportName + 'DarkMode' = $DarkMode + 'Quiet' = $Quiet } Invoke-ReportCreation @ReportParams } @@ -730,8 +737,8 @@ function Invoke-ReportCreation { [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] - [boolean] - $Quiet = $false, + [switch] + $Quiet, [Parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] @@ -851,7 +858,7 @@ function Invoke-ReportCreation { Add-Type -AssemblyName System.Web -ErrorAction 'Stop' $ReportFileName = Join-Path -Path $OutFolderPath "$($OutReportName).html" -ErrorAction 'Stop' [System.Web.HttpUtility]::HtmlDecode($ReportHTML) | Out-File $ReportFileName -ErrorAction 'Stop' - if ($Quiet -eq $False) { + if (-Not $Quiet) { Invoke-Item $ReportFileName } } @@ -1280,8 +1287,8 @@ function Invoke-RunCached { [Parameter(Mandatory = $false, ParameterSetName = 'Report')] [ValidateNotNullOrEmpty()] [ValidateSet($true, $false)] - [boolean] - $Quiet = $false, + [switch] + $Quiet, [Parameter(Mandatory = $false, ParameterSetName = 'Report')] [switch] diff --git a/Testing/Unit/PowerShell/Orchestrator/Invoke-ReportCreation.Tests.ps1 b/Testing/Unit/PowerShell/Orchestrator/Invoke-ReportCreation.Tests.ps1 index d21798612d..ddaea82eb1 100644 --- a/Testing/Unit/PowerShell/Orchestrator/Invoke-ReportCreation.Tests.ps1 +++ b/Testing/Unit/PowerShell/Orchestrator/Invoke-ReportCreation.Tests.ps1 @@ -35,6 +35,22 @@ InModuleScope Orchestrator { OutReportName = "BaselineReports" } } + It 'Do it quietly (Do not automatically show report)' { + $ProviderParameters += @{ + ProductNames = @("aad") + } + { Invoke-ReportCreation @ProviderParameters -Quiet} | Should -Not -Throw + Should -Invoke -CommandName Invoke-Item -Exactly -Times 0 + $ProviderParameters.ProductNames = @() + } + It 'Show report' { + $ProviderParameters += @{ + ProductNames = @("aad") + } + { Invoke-ReportCreation @ProviderParameters} | Should -Not -Throw + Should -Invoke -CommandName Invoke-Item -Exactly -Times 1 -ParameterFilter {-Not [string]::IsNullOrEmpty($Path) } + $ProviderParameters.ProductNames = @() + } It 'With -ProductNames "aad", should not throw' { $ProviderParameters += @{ ProductNames = @("aad") diff --git a/Testing/Unit/PowerShell/Orchestrator/Invoke-Scuba.Tests.ps1 b/Testing/Unit/PowerShell/Orchestrator/Invoke-Scuba.Tests.ps1 index bf747f26db..453a2d8fdf 100644 --- a/Testing/Unit/PowerShell/Orchestrator/Invoke-Scuba.Tests.ps1 +++ b/Testing/Unit/PowerShell/Orchestrator/Invoke-Scuba.Tests.ps1 @@ -16,7 +16,7 @@ InModuleScope Orchestrator { Mock -ModuleName Orchestrator Invoke-ProviderList {} function Invoke-RunRego {} Mock -ModuleName Orchestrator Invoke-RunRego {} - function Invoke-ReportCreation {} + Mock -ModuleName Orchestrator Invoke-ReportCreation {} function Disconnect-SCuBATenant {} Mock -ModuleName Orchestrator Disconnect-SCuBATenant {} @@ -31,6 +31,14 @@ InModuleScope Orchestrator { M365Environment = 'commercial'; } } + It 'Do it quietly (Do not automatically show report)' { + {Invoke-Scuba -Quiet} | Should -Not -Throw + Should -Invoke -CommandName Invoke-ReportCreation -Exactly -Times 1 -ParameterFilter {$Quiet -eq $true} + } + It 'Show report' { + {Invoke-Scuba} | Should -Not -Throw + Should -Invoke -CommandName Invoke-ReportCreation -Exactly -Times 1 -ParameterFilter {$Quiet -eq $false} + } It 'Given -ProductNames aad should not throw' { $SplatParams += @{ ProductNames = @("aad") From 825861ddb018bace0a2c565afa169e0c0218b0d4 Mon Sep 17 00:00:00 2001 From: Alden Hilton <106177711+adhilto@users.noreply.github.com> Date: Wed, 7 Jun 2023 08:47:12 -0400 Subject: [PATCH 04/33] Invert Stance on Defender Preset Policies in Markdown (#355) * Inverted 2.1, removed applicable controls * Ironed out baselines for the using the preset policies * Minor wording updates to MS.DEFENDER.1.1v1 rationale * Minor wording updates to MS.DEFENDER.2.3v1 policy statement * Minor wording updates to MS.DEFENDER.2.3v1 rationale * Update to MS.DEFENDER.2.4v1 license restrictions in GCC high and DoD regions * Minor wording updates to MS.DEFENDER.3.1v1 rationale * Minor wording update to MS.DEFENDER.2.3v1 rationale * Minor wording change to Safe Attachments group text * Remove hyphen from Safe Attachments policy group title. * Added new policy item 1.1v1 and renumered others; added sensitive accounts language --------- Co-authored-by: Addam Schroll <108814318+schrolla@users.noreply.github.com> Co-authored-by: Addam Schroll --- baselines/defender.md | 784 ++++++++---------------------------------- 1 file changed, 151 insertions(+), 633 deletions(-) diff --git a/baselines/defender.md b/baselines/defender.md index da3a9a79fa..781a6e80a1 100644 --- a/baselines/defender.md +++ b/baselines/defender.md @@ -24,6 +24,8 @@ trust principles. ## Assumptions +The agency has identified a set of user accounts that have access to sensitive and high value information. As a result, these accounts may be at a higher risk of being targeted. These accounts are referred to as sensitive accounts for the purposes of the Defender policies in this baseline. + The **License Requirements** sections of this document assume the organization is using an [M365 E3](https://www.microsoft.com/en-us/microsoft-365/compare-microsoft-365-enterprise-plans) @@ -52,30 +54,155 @@ strengthen the security of widely used cloud-based software services. ## 1. Preset Security Profiles Microsoft Defender defines two [preset security -profiles](https://docs.microsoft.com/en-us/microsoft-365/security/office-365-security/preset-security-policies?view=o365-worldwide): -standard and strict. While most of the settings in this baseline mirror -the settings of the standard profile, this baseline recommends against -the use of the preset profiles. Instead, it enumerates all relevant -settings, as the preset security profiles are inflexible and take -precedence over all other present policies. +profiles](https://docs.microsoft.com/en-us/microsoft-365/security/office-365-security/preset-security-policies): +standard and strict. These preset policies are informed by observations made by Microsoft and are designed to strike the balance between usability and security. They allow administrators to enable the full feature set of Defender by simply adding users to the policies rather than manually configuring each setting. + +Within the preset policies, users can be enrolled in [Exchange Online Protection](https://learn.microsoft.com/en-us/microsoft-365/security/office-365-security/eop-about?view=o365-worldwide) and [Defender for Office 365 protection](https://learn.microsoft.com/en-us/microsoft-365/security/office-365-security/microsoft-defender-for-office-365-product-overview?view=o365-worldwide), and [Impersonation Protection](https://learn.microsoft.com/en-us/microsoft-365/security/office-365-security/anti-phishing-policies-about?view=o365-worldwide#impersonation-settings-in-anti-phishing-policies-in-microsoft-defender-for-office-365) can be configured. ### Policies #### MS.DEFENDER.1.1v1 -Preset security profiles SHOULD NOT be used. -- _Rationale:_ TODO +The standard and strict preset security policies SHALL be enabled. +- _Rationale:_ Defender includes a large number of features and settings to protect users against threats. Using the preset security policies, administrators can easily ensure that all new and existing users automatically have secure defaults applied. + +- _Last modified:_ June 2023 +#### MS.DEFENDER.1.2v1 +All users SHALL be added to Exchange Online Protection in either the standard or strict preset security policy. +- _Rationale:_ Important user protections are provided by Exchange Online Protection, including anti-spam, anti-malware, and anti-phishing protections. By using the preset policies, administrators can easily ensure that all new and existing users automatically have secure defaults applied. + +- _Last modified:_ June 2023 + +#### MS.DEFENDER.1.3v1 +All users SHALL be added to Defender for Office 365 Protection in either the standard or strict preset security policy. +- _Rationale:_ Important user protections are provided by Defender for Office 365 Protection, including safe attachments and safe links. By using the preset policies, administrators can easily ensure that all new and existing users automatically have secure defaults applied. +- _Last modified:_ June 2023 + +#### MS.DEFENDER.1.4v1 +Sensitive accounts SHALL be added to Exchange Online Protection in the strict preset security policy. +- _Rationale:_ The increased protection offered by the strict preset policy helps mitigate the greater harm that could result from the compromise of a sensitive account. +- _Last modified:_ June 2023 + +#### MS.DEFENDER.1.5v1 +Sensitive accounts SHALL be added to Defender for Office 365 Protection in the strict preset security policy. +- _Rationale:_ The increased protection offered by the strict preset policy helps mitigate the greater harm that could result from the compromise of a sensitive account. +- _Last modified:_ June 2023 + +#### MS.DEFENDER.1.6v1 +Specific user accounts, except for sensitive accounts, MAY be exempt from the preset policies, provided that they are added to a custom policy that offers comparable protection. +- _Rationale:_ In some cases, specific users might need flexibility that is not offered by the preset policies. In these cases, these users' accounts should be added to a custom policy that conforms as closely as possible to the settings used by the preset policies (see the **Resources** section for more details). - _Last modified:_ June 2023 ### Resources - [Recommended settings for EOP and Microsoft Defender for Office 365 security \| Microsoft - Docs](https://docs.microsoft.com/en-us/microsoft-365/security/office-365-security/recommended-settings-for-eop-and-office365?view=o365-worldwide#eop-anti-spam-policy-settings) + Docs](https://learn.microsoft.com/en-us/microsoft-365/security/office-365-security/recommended-settings-for-eop-and-office365) ### License Requirements - N/A -## 2. Data Loss Prevention +### Implementation +To add users to the preset policies, follow the instructions listed under [Use the Microsoft 365 Defender portal to assign Standard and Strict preset security policies to users \| Microsoft Docs](https://learn.microsoft.com/en-us/microsoft-365/security/office-365-security/preset-security-policies?view=o365-worldwide#use-the-microsoft-365-defender-portal-to-assign-standard-and-strict-preset-security-policies-to-users). + +To apply a preset policy to all users, under "Apply protection to," select "All recipients." + +## 2. Impersonation Protection +Impersonation protection checks incoming emails to see if the sender +address is similar to the users or domains on an agency-defined list. If +the sender address is significantly similar, as to indicate an +impersonation attempt, the email is quarantined. + +### Policies +#### MS.DEFENDER.2.1v1 +User impersonation protection SHOULD be enabled for sensitive accounts in both the standard and strict preset policies. +- _Rationale:_ User impersonation, especially the impersonation of users with access to sensitive or high value information and resources, has the potential to result in serious harm. Impersonation protection mitigates this risk. By configuring impersonation protection in both preset policies, administrators ensure that all email recipients are protected from impersonated emails, regardless of whether they are added to the standard or strict policy. +- _Last modified:_ June 2023 + +#### MS.DEFENDER.2.2v1 +Domain impersonation protection SHOULD be enabled for domains owned by the agency in both the standard and strict preset policies. +- _Rationale:_ By configuring domain impersonation protection for all agency domains, the risk of a user being deceived by a look-alike domain may be reduced. By configuring impersonation protection in both preset policies, administrators ensure that all email recipients are protected from impersonated emails, regardless of whether they are added to the standard or strict policy. +- _Last modified:_ June 2023 + +#### MS.DEFENDER.2.3v1 +Domain impersonation protection SHOULD be added for important partners in both the standard and strict preset policies. +- _Rationale:_ By configuring domain impersonation protection for domains owned by important partners, the risk of a user being deceived by a look-alike domain may be reduced. By configuring impersonation protection in both preset policies, administrators ensure that all email recipients are protected from impersonated emails, regardless of whether they are added to the standard or strict policy. +- _Last modified:_ June 2023 + +#### MS.DEFENDER.2.4v1 +Trusted senders and domains MAY be added in the event of false positives. +- _Rationale:_ It is possible that false positives may be raised by the impersonation protection system. In these cases, consider marking legitimate senders as trusted to prevent protection from flagging them in the future. +- _Last modified:_ June 2023 + +### Resources + +- [Impersonation settings in anti-phishing policies in Microsoft Defender for Office 365 \| Microsoft Docs](https://learn.microsoft.com/en-us/microsoft-365/security/office-365-security/anti-phishing-policies-about?view=o365-worldwide#impersonation-settings-in-anti-phishing-policies-in-microsoft-defender-for-office-365). + +### License Requirements + +- Impersonation protection and advanced phishing thresholds require + Defender for Office 365 Plan 1 or 2. These are included with E5 and G5 + and are available as add-ons for E3 and G3. As of April 25, 2023 + anti-phishing for user and domain impersonation and spoof intelligence + are not yet available in GCC High and DoD (see [Platform features \| + Microsoft + Docs](https://docs.microsoft.com/en-us/office365/servicedescriptions/office-365-platform-service-description/office-365-us-government/office-365-us-government#platform-features) + for current offerings). + +### Implementation +To add email addresses and domains to flag when impersonated by attackers, follow the instructions listed under [Use the Microsoft 365 Defender portal to assign Standard and Strict preset security policies to users \| Microsoft Docs](https://learn.microsoft.com/en-us/microsoft-365/security/office-365-security/preset-security-policies?view=o365-worldwide#use-the-microsoft-365-defender-portal-to-assign-standard-and-strict-preset-security-policies-to-users). + +## 3. Safe Attachments + +The Safe Attachments feature will scan messages for attachments with malicious +content. It routes all messages and attachments that do not have a +virus or malware signature to a special environment. It then uses machine +learning and analysis techniques to detect malicious intent. +While safe attachments for Exchange Online is automatically +configured in the preset policies, separate action needs to be taken to +enable it for other products. + +### Policies +#### MS.DEFENDER.3.1v1 +Safe attachments SHOULD be enabled for SharePoint, OneDrive, and Microsoft Teams. +- _Rationale:_ Users clicking malicious links makes them vulnerable to attacks. However, this danger is not limited to links included in emails. Other Microsoft products, such as Microsoft Teams, can be used to present users with malicious links. As such, it is important to protect users on these other Microsoft products as well. +- _Last modified:_ June 2023 + +### Resources + +- [Safe Attachments in Microsoft Defender for Office 365 \| Microsoft + Docs](https://docs.microsoft.com/en-us/microsoft-365/security/office-365-security/safe-attachments?view=o365-worldwide#safe-attachments-policy-settings) + +- [Turn on Safe Attachments for SharePoint, OneDrive, and Microsoft + Teams \| Microsoft + Docs](https://docs.microsoft.com/en-us/microsoft-365/security/office-365-security/turn-on-mdo-for-spo-odb-and-teams?view=o365-worldwide) + +### License Requirements + +- Requires Defender for Office 365 Plan 1 or 2. These are included with + E5 and G5 and are available as add-ons for E3 and G3. + +### Implementation + +To enable Safe Attachments for SharePoint, OneDrive, and Microsoft +Teams, follow the instructions listed at [Turn on Safe Attachments for +SharePoint, OneDrive, and Microsoft Teams \| Microsoft +Docs](https://docs.microsoft.com/en-us/microsoft-365/security/office-365-security/turn-on-mdo-for-spo-odb-and-teams?view=o365-worldwide). + +1. Sign in to [Microsoft 365 + Defender](https://security.microsoft.com/). + +2. Under **Email & collaboration**, select **Policies & rules**. + +3. Select **Threat policies**. + +4. Under **Policies**, select **Safe Attachments**. + +5. Select **Global settings**. + +6. Set **Turn on Defender for Office 365 for SharePoint, OneDrive, and + Microsoft Teams** to on. + +## 4. Data Loss Prevention There are multiple, different ways to secure sensitive information, such as warning users, encryption, or blocking attempts to share. The @@ -83,32 +210,32 @@ agency’s data loss prevention (DLP) policy will dictate what agency information is sensitive and how that information is handled. ### Policies -#### MS.DEFENDER.2.1v1 +#### MS.DEFENDER.4.1v1 A custom policy SHALL be configured to protect PII and sensitive information, as defined by the agency. At a minimum, credit card numbers, Taxpayer Identification Numbers (TIN), and Social Security Numbers (SSN) SHALL be blocked. - _Rationale:_ TODO - _Last modified:_ June 2023 -#### MS.DEFENDER.2.2v1 +#### MS.DEFENDER.4.2v1 The custom policy SHOULD be applied in Exchange, OneDrive, Teams Chat, and Microsoft Defender. - _Rationale:_ TODO - _Last modified:_ June 2023 -#### MS.DEFENDER.2.3v1 +#### MS.DEFENDER.4.3v1 The action for the DLP policy SHOULD be set to block sharing sensitive information with everyone when DLP conditions are met. - _Rationale:_ TODO - _Last modified:_ June 2023 -#### MS.DEFENDER.2.4v1 +#### MS.DEFENDER.4.4v1 Notifications to inform users and help educate them on the proper use of sensitive information SHOULD be enabled. - _Rationale:_ TODO - _Last modified:_ June 2023 -#### MS.DEFENDER.2.5v1 +#### MS.DEFENDER.4.5v1 A list of apps that are not allowed to access files protected by DLP policy SHOULD be defined. - _Rationale:_ TODO - _Last modified:_ June 2023 -#### MS.DEFENDER.2.6v1 +#### MS.DEFENDER.4.6v1 A list of browsers that are not allowed to access files protected by DLP policy SHOULD be defined. - _Rationale:_ TODO - _Last modified:_ June 2023 @@ -220,628 +347,19 @@ A list of browsers that are not allowed to access files protected by DLP policy 8. Switch **Always audit file activity for devices** to **ON**. -## 3. Common Attachments Filter - -Filtering emails by attachment file types will flag emails as malware if -the file type has been put in a predefined list of disallowed file -types. The Common Attachments Filter also attempts to look beyond just -the file extension and automatically detect the file type using true -typing. - -### Policies -#### MS.DEFENDER.3.1v1 -The common attachments filter SHALL be enabled in the default anti-malware policy and in all existing policies. -- _Rationale:_ TODO -- _Last modified:_ June 2023 - -#### MS.DEFENDER.3.2v1 -Disallowed file types SHALL be determined and set. At a minimum, click-to-run files SHOULD be blocked (e.g., .exe, .cmd, and .vbe). -- _Rationale:_ TODO -- _Last modified:_ June 2023 - -### Resources - -- [Configure anti-malware policies in EOP \| Microsoft - Docs](https://docs.microsoft.com/en-us/microsoft-365/security/office-365-security/configure-anti-malware-policies?view=o365-worldwide) - -- [Anti-malware policies \| Microsoft - Docs](https://docs.microsoft.com/en-us/microsoft-365/security/office-365-security/anti-malware-protection?view=o365-worldwide#anti-malware-policies) - -### License Requirements - -- Requires Defender for Office 365 Plan 1 or 2. These are included with - E5 and G5 and are available as add-ons for E3 and G3. - -### Implementation - -To enable common attachments filter in the default policy: - -1. Sign in to [Microsoft 365 - Defender](https://security.microsoft.com/). - -2. Under **Email & collaboration**, select **Policies & rules**. - -3. Select **Threat policies**. - -4. Under **Policies**, select **Anti-malware**. - -5. Select the **Default (Default)** policy. - -6. Click **Edit protection settings**. - -7. Check **Enable the common attachments filter**. - -8. Click **Customize file types** as needed. - -9. Click **Save**. - -To create a new, custom policy, follow the instructions on [Use the -Microsoft 365 Defender portal to create anti-malware -policies](https://docs.microsoft.com/en-us/microsoft-365/security/office-365-security/configure-anti-malware-policies?view=o365-worldwide#use-the-microsoft-365-defender-portal-to-create-anti-malware-policies). - -## 4. Zero-Hour Auto Purge - -This setting determines whether emails can be quarantined automatically -after delivery to a user’s mailbox (e.g., in the case of a match with an -updated malware classification rule). - -### Policies - -#### MS.DEFENDER.4.1v1 -Zero-hour Auto Purge (ZAP) for malware SHOULD be enabled in the default anti-malware policy and in all existing custom policies. -- _Rationale:_ TODO -- _Last modified:_ June 2023 - -### Resources - -- [Configure anti-malware policies in EOP \| Microsoft - Docs](https://docs.microsoft.com/en-us/microsoft-365/security/office-365-security/configure-anti-malware-policies?view=o365-worldwide) - -- [Anti-malware policies \| Microsoft - Docs](https://docs.microsoft.com/en-us/microsoft-365/security/office-365-security/anti-malware-protection?view=o365-worldwide#anti-malware-policies) - -### 2.4.3 License Requirements - -- Requires Defender for Office 365 Plan 1 or 2. These are included with - E5 and G5 and are available as add-ons for E3 and G3. - -### Implementation - -To enable ZAP: - -1. Sign in to [Microsoft 365 - Defender](https://security.microsoft.com/). - -2. Under **Email & collaboration**, select **Policies & rules**. - -3. Select **Threat policies**. - -4. Under **Policies**, select **Anti-malware**. - -5. Select the **Default (Default)** policy. - -6. Click **Edit protection settings**. - -7. Check **Enable zero-hour auto purge for malware (Recommended)**. - -8. Click **Save**. - -## 5. Phishing Protections - -There are multiple ways to protect against phishing, including -impersonation protection, mailbox intelligence and safety tips. -Impersonation protection checks incoming emails to see if the sender -address is similar to the users or domains on an agency-defined list. If -the sender address is significantly similar, as to indicate an -impersonation attempt, the email is quarantined. Mailbox intelligence is -an AI-based tool for identifying potential impersonation attempts. - -### Policies -#### MS.DEFENDER.5.1v1 -User impersonation protection SHOULD be enabled for key agency - leaders. -- _Rationale:_ TODO -- _Last modified:_ June 2023 - -#### MS.DEFENDER.5.2v1 -Domain impersonation protection SHOULD be enabled for domains owned by - the agency. -- _Rationale:_ TODO -- _Last modified:_ June 2023 - -#### MS.DEFENDER.5.3v1 -Domain impersonation protection SHOULD be added for frequent partners. -- _Rationale:_ TODO -- _Last modified:_ June 2023 - -#### MS.DEFENDER.5.4v1 -Trusted senders and domains MAY be added in the event of false - positives. -- _Rationale:_ TODO -- _Last modified:_ June 2023 - -#### MS.DEFENDER.5.5v1 -Intelligence for impersonation protection SHALL be enabled. -- _Rationale:_ TODO -- _Last modified:_ June 2023 - -#### MS.DEFENDER.5.6v1 -Message action SHALL be set to quarantine if the message is detected - as impersonated. -- _Rationale:_ TODO -- _Last modified:_ June 2023 - -#### MS.DEFENDER.5.7v1 -Mail classified as spoofed SHALL be quarantined. -- _Rationale:_ TODO -- _Last modified:_ June 2023 - -#### MS.DEFENDER.5.8v1 -All safety tips SHALL be enabled, including: - - - first contact, - - - user impersonation, - - - domain impersonation, - - - user impersonation unusual characters, - - - ? for unauthenticated senders for spoof, and - - - via tag. -- _Rationale:_ TODO -- _Last modified:_ June 2023 - -#### MS.DEFENDER.5.9v1 -The above configurations SHALL be set in the default policy and SHOULD - be set in all existing custom policies. -- _Rationale:_ TODO -- _Last modified:_ June 2023 - -### Resources - -- [Configure anti-phishing policies in EOP \| Microsoft - Docs](https://docs.microsoft.com/en-us/microsoft-365/security/office-365-security/configure-anti-phishing-policies-eop?view=o365-worldwide) - -- [EOP anti-phishing policy settings \| Microsoft - Docs](https://docs.microsoft.com/en-us/microsoft-365/security/office-365-security/recommended-settings-for-eop-and-office365?view=o365-worldwide#eop-anti-phishing-policy-settings) - -### License Requirements - -- Impersonation protection and advanced phishing thresholds require - Defender for Office 365 Plan 1 or 2. These are included with E5 and G5 - and are available as add-ons for E3 and G3. As of September 1, 2022 - anti-phishing for user and domain impersonation and spoof intelligence - are not yet available in GCC High and DoD (see [Platform features \| - Microsoft - Docs](https://docs.microsoft.com/en-us/office365/servicedescriptions/office-365-platform-service-description/office-365-us-government/office-365-us-government#platform-features) - for current offerings). - -### Implementation - -1. Sign in to [Microsoft 365 - Defender](https://security.microsoft.com/). - -2. Under **Email & collaboration**, select **Policies & rules**. - -3. Select **Threat policies**. - -4. Under **Policies**, select **Anti-phishing**. - -5. Select the **Office365 AntiPhish Default (Default)** policy. - -6. Click **Edit protection settings**. - -7. Check **Enable users to protect**. - -8. Click **Manage sender(s)**, then add users that merit impersonation - protection. - -9. Check **Enable domains to protect**. - -10. Check **Include domains I own**. - -11. Check **Include custom domains**. - -12. Click **Manage custom domains(s)** to add the domains of frequent - partners. - -13. Check **Enable mailbox intelligence (Recommended)**. - -14. Check **Enable Intelligence for impersonation protection - (Recommended)**. - -15. Click **Save**. - -16. Click **Edit actions**. - -17. Set **If message is detected as an impersonated user** to - **Quarantine the message**. - -18. Set **If message is detected as an impersonated domain** to - **Quarantine the message**. - -19. Set **If Mailbox Intelligence detects an impersonated user** to - **Quarantine the message**. - -20. Set **If message is detected as spoof** to **Quarantine the - message**. - -21. Under **Safety tips & indicators**, check: - -1. **Show first contact safety tip (Recommended)** - -2. **Show user impersonation safety tip** - -3. **Show domain impersonation safety tip** - -4. **Show user impersonation unusual characters safety tip** - -5. **Show (?) for unauthenticated senders for spoof** - -6. **Show “via” tag** - -22. Click **Save**. - -## 6. Inbound Anti-Spam Protections - -There are several features that protect against inbound spam. Bulk -compliant level, quarantines, safety tips, and zero-hour auto purge. - -### Policies - -#### MS.DEFENDER.6.1v1 -The bulk complaint level (BCL) threshold SHOULD be set to six or lower. -- _Rationale:_ TODO -- _Last modified:_ June 2023 - -#### MS.DEFENDER.6.2v1 -Spam and high confidence spam SHALL be moved to either the junk email folder or the quarantine folder. -- _Rationale:_ TODO -- _Last modified:_ June 2023 - -#### MS.DEFENDER.6.3v1 -Phishing and high confidence phishing SHALL be quarantined. -- _Rationale:_ TODO -- _Last modified:_ June 2023 - -#### MS.DEFENDER.6.4v1 -Bulk email SHOULD be moved to either the junk email folder or the quarantine folder. -- _Rationale:_ TODO -- _Last modified:_ June 2023 - -#### MS.DEFENDER.6.5v1 -Spam in quarantine SHOULD be retained for at least 30 days. -- _Rationale:_ TODO -- _Last modified:_ June 2023 - -#### MS.DEFENDER.6.6v1 -Spam safety tips SHOULD be turned on. -- _Rationale:_ TODO -- _Last modified:_ June 2023 - -#### MS.DEFENDER.6.7v1 -Zero-hour auto purge (ZAP) SHALL be enabled for both phishing and spam messages. -- _Rationale:_ TODO -- _Last modified:_ June 2023 - -#### MS.DEFENDER.6.8v1 -Allowed senders MAY be added but allowed domains SHALL NOT be added. -- _Rationale:_ TODO -- _Last modified:_ June 2023 - -#### MS.DEFENDER.6.9v1 -The previously listed configurations SHALL be set in the default policy and SHOULD be set in all existing custom policies. -- _Rationale:_ TODO -- _Last modified:_ June 2023 - -### Resources - -- [Bulk complaint level (BCL) in EOP \| Microsoft - Docs](https://docs.microsoft.com/en-us/microsoft-365/security/office-365-security/bulk-complaint-level-values?view=o365-worldwide) - -- [EOP anti-spam policy settings \| Microsoft - Docs](https://docs.microsoft.com/en-us/microsoft-365/security/office-365-security/recommended-settings-for-eop-and-office365?view=o365-worldwide#eop-anti-spam-policy-settings) - -- [Configure anti-spam policies in EOP \| Microsoft - Docs](https://docs.microsoft.com/en-us/microsoft-365/security/office-365-security/configure-your-spam-filter-policies?view=o365-worldwide) - -### License Requirements - -- N/A - -### Implementation - -1. Sign in to [Microsoft 365 - Defender](https://security.microsoft.com/). - -2. Under **Email & collaboration**, select **Policies & rules**. - -3. Select **Threat policies**. - -4. Under Policies, select **Anti-spam**. - -5. Select **Anti-spam inbound policy (Default)**. - -6. Under **Bulk email threshold & spam properties**, click **Edit spam - threshold and properties**. - -7. Set **Bulk email threshold** to six or lower. - -8. Click **Save**. - -9. Under **Actions**, click **Edit actions**. - -10. In the **Message actions** section: - -1. For **Spam, High confidence spam**, and **Bulk**, set the action to - either **Move message to Junk Email folder** or **Quarantine - message**. - -2. Set the action for both **Phishin**g and **High confidence - phishing** to **Quarantine message**. - -3. Set **Retain spam in quarantine for this many days** to “30.” - -4. Check **Enable spam safety tips**. - -5. Check **Enable zero-hour auto purge (ZAP)**, **Enable for phishing - messages,** and **Enable for spam messages**. - -11. Click **Save.** - -## 7. Safe Links - -When enabled, URLs in emails are rewritten by prepending - -`https://*.safelinks.protection.outlook.com/?url=` - -to the original URL. This change can only be seen by either clicking the -URL or copying and pasting it; the end-user, even when hovering over the -URL in their email, will still only see the original URL. By prepending -the safe links URL, Microsoft can proxy the initial URL through their -scanning service. Their proxy can perform the following: - -- Compare the URL will a block list. - -- Compare the URL with a list of know malicious sites. - -- If the URL points to a downloadable file, apply real-time file - scanning. - -If all checks pass, the user is redirected to the original URL. - -### Policies -#### MS.DEFENDER.7.1v1 -The Safe Links Policy SHALL include all agency domains and by extension all users. -- _Rationale:_ TODO -- _Last modified:_ June 2023 - -#### MS.DEFENDER.7.2v1 -URL rewriting and malicious link click checking SHALL be enabled. -- _Rationale:_ TODO -- _Last modified:_ June 2023 - -#### MS.DEFENDER.7.3v1 -Malicious link click checking SHALL be enabled with Microsoft Teams. -- _Rationale:_ TODO -- _Last modified:_ June 2023 - -#### MS.DEFENDER.7.4v1 -Real-time suspicious URL and file-link scanning SHALL be enabled. -- _Rationale:_ TODO -- _Last modified:_ June 2023 - -#### MS.DEFENDER.7.5v1 -URLs SHALL be scanned completely before message delivery. -- _Rationale:_ TODO -- _Last modified:_ June 2023 - -#### MS.DEFENDER.7.6v1 -Internal agency email messages SHALL have safe links enabled. -- _Rationale:_ TODO -- _Last modified:_ June 2023 - -#### MS.DEFENDER.7.7v1 -User click tracking SHALL be enabled. -- _Rationale:_ TODO -- _Last modified:_ June 2023 - -#### MS.DEFENDER.7.8v1 -Safe Links in Office 365 apps SHALL be turned on. -- _Rationale:_ TODO -- _Last modified:_ June 2023 - -#### MS.DEFENDER.7.9v1 -Users SHALL NOT be enabled to click through to the original URL. -- _Rationale:_ TODO -- _Last modified:_ June 2023 - -### Resources - -- [Safe Links in Microsoft Defender for Office 365 \| Microsoft - Docs](https://docs.microsoft.com/en-us/microsoft-365/security/office-365-security/safe-links?view=o365-worldwide) - -- [Set up Safe Links policies in Microsoft Defender for Office 365 \| - Microsoft - Docs](https://docs.microsoft.com/en-us/microsoft-365/security/office-365-security/set-up-safe-links-policies?view=o365-worldwide) - -### License Requirements - -- Requires Defender for Office 365 Plan 1 or 2. These are included with - E5 and G5 and are available as add-ons for E3 and G3. - -### Implementation - -For more information about recommended Safe Links settings, see -[Safe](https://docs.microsoft.com/en-us/microsoft-365/security/office-365-security/recommended-settings-for-eop-and-office365?view=o365-worldwide#safe-links-settings) -Links settings. - -1. Sign in to [Microsoft 365 - Defender](https://security.microsoft.com/). - -2. Under **Email & collaboration**, select **Policies & rules**. - -3. Select **Threat policies**. - -4. Under **Policies**, select **Safe Links**. - -5. Create a Safe Links Policy. - -1. Assign the new policy an appropriate name and description. - -2. Include all tenant domains. All users under those domains will be - added. - -3. On the **URL & click protection settings** page: - - -1. Select **On: Safe Links cehcks a list of known, malicious links when -users click links in email. URLs are rewritten by default.** - -2. Select **Apply Safe Links to email messages sent within the -organization** - -3. Select **Apply real-time URL scanning for suspicious links and links -that point to files.** - -4. Select **Wait for URL scanning to complete before delivering the -message.** - - -1. On the **URL & click protection settings** page, under **Teams**, - select **On: Safe Links checks a list of known, malicious links when - users click links in Microsoft Teams. URLs are not rewritten**. - -2. On the **URL & click protection settings** page, under **Office 365 - Apps**, select **On: Safe Links checks a list of known, malicious - links when users click links in Microsoft Office Apps. URLs are not - rewritten**. - -3. On the **URL & click protestion settings** page, under **Click - protestion settings**: - - 1. Select **Track User Clicks** - - 2. Do not select **Let users click through to the original URL**. - - -5. Review the new policy, then click **Submit**. - -## 8. Safe-Attachments - -The Safe Attachments will scan messages for attachments with malicious -content. It routes all messages and attachments that do not have a -virus/malware signature to a special environment. It then uses machine -learning and analysis techniques to detect malicious intent. Enabling -this feature may slow down message delivery to the user due to the -scanning. - -### Policies -#### MS.DEFENDER.8.1v1 -At least one Safe Attachments Policy SHALL include all agency domains and by extension all users. -- _Rationale:_ TODO -- _Last modified:_ June 2023 - -#### MS.DEFENDER.8.2v1 -The action for malware in email attachments SHALL be set to block. -- _Rationale:_ TODO -- _Last modified:_ June 2023 - -#### MS.DEFENDER.8.3v1 -Redirect emails with detected attachments to an agency-specified email SHOULD be enabled. -- _Rationale:_ TODO -- _Last modified:_ June 2023 - -#### MS.DEFENDER.8.4v1 -Safe attachments SHOULD be enabled for SharePoint, OneDrive, and Microsoft Teams. -- _Rationale:_ TODO -- _Last modified:_ June 2023 - -### Resources - -- [Safe Attachments in Microsoft Defender for Office 365 \| Microsoft - Docs](https://docs.microsoft.com/en-us/microsoft-365/security/office-365-security/safe-attachments?view=o365-worldwide#safe-attachments-policy-settings) - -- [Safe Attachments Policy Settings \| Microsoft - Docs](https://docs.microsoft.com/en-us/microsoft-365/security/office-365-security/safe-attachments?view=o365-worldwide#safe-attachments-policy-settings) - -- [Use the Microsoft 365 Defender portal to create Safe Attachments - policies \| Microsoft - Docs](https://docs.microsoft.com/en-us/microsoft-365/security/office-365-security/set-up-safe-attachments-policies?view=o365-worldwide#use-the-microsoft-365-defender-portal-to-create-safe-attachments-policies) - -- [Turn on Safe Attachments for SharePoint, OneDrive, and Microsoft - Teams \| Microsoft - Docs](https://docs.microsoft.com/en-us/microsoft-365/security/office-365-security/turn-on-mdo-for-spo-odb-and-teams?view=o365-worldwide) - -### License Requirements - -- Requires Defender for Office 365 Plan 1 or 2. These are included with - E5 and G5 and are available as add-ons for E3 and G3. - -### Implementation - -To configure safe attachments for Exchange Online, follow the -instructions listed on [Use the Microsoft 365 Defender portal to create -Safe Attachments -policies](https://docs.microsoft.com/en-us/microsoft-365/security/office-365-security/set-up-safe-attachments-policies?view=o365-worldwide#use-the-microsoft-365-defender-portal-to-create-safe-attachments-policies). - -1. Sign in to [Microsoft 365 - Defender](https://security.microsoft.com/). - -2. Under **Email & collaboration**, select **Policies & rules**. - -3. Select **Threat policies**. - -4. Under **Policies**, select **Safe Attachments**. - -5. Click **Create** to start a new policy. - -6. Give the new policy an appropriate name and description. - -7. Under domains, enter all agency tenant domains. All users under - these domains will be added to the policy. - -8. Under **Safe Attachments unknown malware response**, select - **Block**. - -9. Set the **Quarantine policy** to **AdminOnlyAccessPolicy**. - -10. Click **Next**, then **Submit**. - -To enable Safe Attachments for SharePoint, OneDrive, and Microsoft -Teams, follow the instructions listed at [Turn on Safe Attachments for -SharePoint, OneDrive, and Microsoft Teams \| Microsoft -Docs](https://docs.microsoft.com/en-us/microsoft-365/security/office-365-security/turn-on-mdo-for-spo-odb-and-teams?view=o365-worldwide). - -1. Sign in to [Microsoft 365 - Defender](https://security.microsoft.com/). - -2. Under **Email & collaboration**, select **Policies & rules**. - -3. Select **Threat policies**. - -4. Under **Policies**, select **Safe Attachments**. - -5. Select **Global settings**. - -6. Set **Turn on Defender for Office 365 for SharePoint, OneDrive, and - Microsoft Teams** to on. - -## 9. Alerts +## 5. Alerts There are several pre-built alert policies available pertaining to -various apps in the M365 suite. These alerts give admins better +various apps in the M365 suite. These alerts give administrators better real-time insight into possible security incidents. ### Policies -#### MS.DEFENDER.9.1v1 +#### MS.DEFENDER.5.1v1 At a minimum, the alerts required by the *Exchange Online Minimum Viable Secure Configuration Baseline* SHALL be enabled. - _Rationale:_ TODO - _Last modified:_ June 2023 -#### MS.DEFENDER.9.2v1 +#### MS.DEFENDER.5.2v1 The alerts SHOULD be sent to a monitored address or incorporated into a SIEM. - _Rationale:_ TODO - _Last modified:_ June 2023 @@ -870,7 +388,7 @@ The alerts SHOULD be sent to a monitored address or incorporated into a SIEM. 6. Ensure **Email recipients** includes at least one monitored address. -## 10. Microsoft Purview Audit +## 6. Microsoft Purview Audit Unified audit logging generates logs of user activity in M365 services. These logs are essential for conducting incident response and threat detection activity. @@ -887,17 +405,17 @@ policy](https://docs.microsoft.com/en-us/microsoft-365/compliance/audit-log-rete OMB M-21-13 also requires Advanced Audit be configured in M365. Advanced Audit adds additional event types to the Unified Audit Log. ### Policies -#### MS.DEFENDER.10.1v1 +#### MS.DEFENDER.6.1v1 Microsoft Purview Audit (Standard) logging SHALL be enabled. - _Rationale:_ TODO - _Last modified:_ June 2023 -#### MS.DEFENDER.10.2v1 +#### MS.DEFENDER.6.2v1 Microsoft Purview Audit (Premium) logging SHALL be enabled. - _Rationale:_ TODO - _Last modified:_ June 2023 -#### MS.DEFENDER.10.3v1 +#### MS.DEFENDER.6.3v1 Audit logs SHALL be maintained for at least the minimum duration dictated by OMB M-21-31. - _Rationale:_ TODO - _Last modified:_ June 2023 From 2c950f081191c1a4ec888a7cfa99e3e87d06e9e7 Mon Sep 17 00:00:00 2001 From: Cassandra Diaz <47129205+Sloane4@users.noreply.github.com> Date: Wed, 7 Jun 2023 11:54:29 -0400 Subject: [PATCH 05/33] Substantiative changes to Sharepoint Baseline minus Rationale (#360) * Structural baseline updates (cleaned up) (#334) --------- * Split policies for testing purposes * Addition for github issue: Add a new SharePoint Guest sign in Policy #307 * Updated for github issue: Direct the user to save in policy implementation SharePoint #301 * Initial drop of secure baseline automation (#336) * initial teams drop * Add markdown check * Structural baseline updates (cleaned up) (#334) * Update aad.md all updates * Update defender.md all updates * Update exchange.md all updates * Rename exchange.md to exo.md * Update onedrive.md * Update powerbi.md all updates all updates * Update sharepoint.md all updates * Update teams.md all updates * Update baselines/defender.md * Structural baseline updates (cleaned up) (#334) * Update aad.md all updates * Update defender.md all updates * Update exchange.md all updates * Rename exchange.md to exo.md * Update onedrive.md * Update powerbi.md all updates * Update powerplatform.md all updates * Update sharepoint.md all updates * Update teams.md all updates * Update baselines/defender.md good catch! Co-authored-by: Addam Schroll <108814318+schrolla@users.noreply.github.com> * Update baselines/powerbi.md Co-authored-by: Addam Schroll <108814318+schrolla@users.noreply.github.com> * Update baselines/powerbi.md Co-authored-by: Addam Schroll <108814318+schrolla@users.noreply.github.com> * Update baselines/aad.md Co-authored-by: Addam Schroll <108814318+schrolla@users.noreply.github.com> * Update aad.md referenced old policy number * Update powerbi.md --------- Co-authored-by: Addam Schroll <108814318+schrolla@users.noreply.github.com> * initial teams drop * Update AAD * WIP * WIP * WIP * WIP * WIP * Structural baseline updates (cleaned up) (#334) * Update aad.md all updates * Update defender.md all updates * Update exchange.md all updates * Rename exchange.md to exo.md * Update onedrive.md * Update powerbi.md all updates * Update powerplatform.md all updates * Update sharepoint.md all updates * Update teams.md all updates * Update baselines/defender.md good catch! Co-authored-by: Addam Schroll <108814318+schrolla@users.noreply.github.com> * Update baselines/powerbi.md Co-authored-by: Addam Schroll <108814318+schrolla@users.noreply.github.com> * Update baselines/powerbi.md Co-authored-by: Addam Schroll <108814318+schrolla@users.noreply.github.com> * Update baselines/aad.md Co-authored-by: Addam Schroll <108814318+schrolla@users.noreply.github.com> * Update aad.md referenced old policy number * Update powerbi.md --------- Co-authored-by: Addam Schroll <108814318+schrolla@users.noreply.github.com> * initial teams drop * Update AAD * WIP * Structural baseline updates (cleaned up) (#334) * Update aad.md all updates * Update defender.md all updates * Update exchange.md all updates * Rename exchange.md to exo.md * Update onedrive.md * Update powerbi.md all updates * Update powerplatform.md all updates * Update sharepoint.md all updates * Update teams.md all updates * Update baselines/defender.md good catch! Co-authored-by: Addam Schroll <108814318+schrolla@users.noreply.github.com> * Update baselines/powerbi.md Co-authored-by: Addam Schroll <108814318+schrolla@users.noreply.github.com> * Update baselines/powerbi.md Co-authored-by: Addam Schroll <108814318+schrolla@users.noreply.github.com> * Update baselines/aad.md Co-authored-by: Addam Schroll <108814318+schrolla@users.noreply.github.com> * Update aad.md referenced old policy number * Update powerbi.md --------- Co-authored-by: Addam Schroll <108814318+schrolla@users.noreply.github.com> * Fix UT errors * Default baseline for testing * Updates based on review comments * Call Import-SecureBaseline once * Update for review comments * Review updates * Add help comment * remove unused import * Fix OPA check issues * fix opa tests action * Update action to test * Action update * Sum PS/Bug as Errors * Update darkmode colors * Fix UT after Rebase * Fix UT * Fix error log * Update UT for NewReport * Update link color --------- Co-authored-by: Andrew Huynh <113476170+ahuynhMITRE@users.noreply.github.com> Co-authored-by: Addam Schroll <108814318+schrolla@users.noreply.github.com> Co-authored-by: Sloane4 * Update for github issue Sharepoint 2.3 Sharing settings cannot be more restrictive than the tenant level #288 * Updat for github issue Update SharePoint Policy 2.4 Code #300 * Additional changes for #288 * Update with correct implementations * Update for github issue #303 * Added some rational & fixed policy numbers * Split policy 5 to improve setting check & report. * Updated for duplicates with onedrive * Add resource for details about reauthentication github issue #299 * Removed Should & Shall from intro paragraphs. * Split implementation for each policy item * Updated code to match baseline TODO Unit tests * Updated unit tests * Fixed policy 4 * Update commandlet for MS.SHAREPOINT.5.2v1 * Updated content style guide for new rego structure * Readded comments to MS.SHAREPOINT.5.2v1 * Baseline updated with requested fixes (addam) * Move updates to content style guide to new branch (not part of current scope) * Update ErrMsg for MS.SHAREPOINT.4 to be more readable --------- Co-authored-by: Andrew Huynh <113476170+ahuynhMITRE@users.noreply.github.com> Co-authored-by: Addam Schroll <108814318+schrolla@users.noreply.github.com> Co-authored-by: Richard Crutchfield --- Rego/SharepointConfig.rego | 250 +- .../CreateReportStubs/TestResults.json | 4632 ++++++++--------- .../Import-SecureBaseline.Tests.ps1 | 2 +- .../CreateReport/New-Report.Tests.ps1 | 2 +- .../Sharepoint/SharepointConfig_01_test.rego | 144 +- .../Sharepoint/SharepointConfig_02_test.rego | 35 +- .../Sharepoint/SharepointConfig_03_test.rego | 10 +- .../Sharepoint/SharepointConfig_04_test.rego | 352 +- .../Sharepoint/SharepointConfig_05_test.rego | 25 +- baselines/sharepoint.md | 245 +- 10 files changed, 2833 insertions(+), 2864 deletions(-) diff --git a/Rego/SharepointConfig.rego b/Rego/SharepointConfig.rego index 459b7b46e9..43d6d1e20c 100644 --- a/Rego/SharepointConfig.rego +++ b/Rego/SharepointConfig.rego @@ -2,96 +2,123 @@ package sharepoint import future.keywords import data.report.utils.NotCheckedDetails import data.report.utils.ReportDetailsBoolean +import data.report.utils.ReportDetailsString + +################### +# MS.SHAREPOINT.1 # +################### # # MS.SHAREPOINT.1.1v1 #-- + +# SharingCapability == 0 Only People In Organization +# SharingCapability == 3 Existing Guests +# SharingCapability == 1 New and Existing Guests +# SharingCapability == 2 Anyone + tests[{ "PolicyId" : "MS.SHAREPOINT.1.1v1", - "Criticality" : "Shall", + "Criticality" : "Should", "Commandlet" : ["Get-SPOTenant", "Get-PnPTenant"], - "ActualValue" : Policy.DefaultSharingLinkType, + "ActualValue" : [Policy.SharingCapability], "ReportDetails" : ReportDetailsBoolean(Status), "RequirementMet" : Status }] { Policy := input.SPO_tenant[_] - Status := Policy.DefaultSharingLinkType == 1 + Conditions := [Policy.SharingCapability == 0, Policy.SharingCapability == 3] + Status := count([Condition | Condition = Conditions[_]; Condition == true]) == 1 } #-- + # # MS.SHAREPOINT.1.2v1 #-- + +# SharingDomainRestrictionMode == 0 Unchecked +# SharingDomainRestrictionMode == 1 Checked +# SharingAllowedDomainList == "domains" Domain list + +tests[{ + "PolicyId" : "MS.SHAREPOINT.1.2v1", + "Criticality" : "Should", + "Commandlet" : ["Get-SPOTenant", "Get-PnPTenant"], + "ActualValue" : [Policy.SharingDomainRestrictionMode], + "ReportDetails" : ReportDetailsBoolean(Status), + "RequirementMet" : Status +}] { + Policy := input.SPO_tenant[_] + Status := Policy.SharingDomainRestrictionMode == 1 +} +#-- + +# +# MS.SHAREPOINT.1.3v1 +#-- +# At this time we are unable to test for approved security groups +# because we have yet to find the setting to check tests[{ "PolicyId" : PolicyId, - "Criticality" : "Shall/Not-Implemented", + "Criticality" : "Should/Not-Implemented", "Commandlet" : [], "ActualValue" : [], "ReportDetails" : NotCheckedDetails(PolicyId), "RequirementMet" : false }] { - PolicyId := "MS.SHAREPOINT.1.2v1" + PolicyId := "MS.SHAREPOINT.1.3v1" true } #-- # -# MS.SHAREPOINT.1.3v1 +# MS.SHAREPOINT.1.4v1 #-- tests[{ - "PolicyId" : "MS.SHAREPOINT.1.3v1", + "PolicyId" : "MS.SHAREPOINT.1.4v1", "Criticality" : "Should", "Commandlet" : ["Get-SPOTenant", "Get-PnPTenant"], - "ActualValue" : Policy.SharingCapability, + "ActualValue" : [Policy.RequireAcceptingAccountMatchInvitedAccount], "ReportDetails" : ReportDetailsBoolean(Status), "RequirementMet" : Status }] { Policy := input.SPO_tenant[_] - Status := Policy.SharingCapability != 2 + Status := Policy.RequireAcceptingAccountMatchInvitedAccount == true } #-- -# -# Baseline 2.2: Policy 2 -#-- -#tests[{ -# "Requirement" : "External sharing SHOULD be limited to approved domains and security groups per interagency collaboration needs", -# "Control" : "Sharepoint 2.2", -# "Criticality" : "Should", -# "Commandlet" : ["Get-SPOTenant", "Get-PnPTenant"], -# "ActualValue" : Policy.SharingDomainRestrictionMode, -# "ReportDetails" : ReportDetailsBoolean(Status), -# "RequirementMet" : Status -#}] { -# Policy := input.SPO_tenant[_] -# Status := Policy.SharingDomainRestrictionMode == 1 -#} -#-- +################### +# MS.SHAREPOINT.2 # +################### # -# Baseline 2.2: Policy 3 +# MS.SHAREPOINT.2.1v1 #-- -#tests[{ -# "Requirement" : "External sharing SHOULD be limited to approved domains and security groups per interagency collaboration needs", -# "Control" : "Sharepoint 2.2", -# "Criticality" : "Should", -# "Commandlet" : ["Get-SPOTenant", "Get-PnPTenant"], -# "ActualValue" : [Policy.SharingCapability, Policy.SharingDomainRestrictionMode], -# "ReportDetails" : ReportDetails2_2(Policy), -# "RequirementMet" : Status -#}] { -# Policy := input.SPO_tenant[_] - # TODO: Missing Allow only users in specific security groups to share externally -#} + +# DefaultSharingLinkType == 1 for Specific People +# DefaultSharingLinkType == 2 for Only people in your organization + +tests[{ + "PolicyId" : "MS.SHAREPOINT.2.1v1", + "Criticality" : "Shall", + "Commandlet" : ["Get-SPOTenant", "Get-PnPTenant"], + "ActualValue" : [Policy.DefaultSharingLinkType], + "ReportDetails" : ReportDetailsBoolean(Status), + "RequirementMet" : Status +}] { + Policy := input.SPO_tenant[_] + Status := Policy.DefaultSharingLinkType == 1 +} #-- -################ -# Baseline 2.3 # -################ +################### +# MS.SHAREPOINT.3 # +################### # -# MS.SHAREPOINT.2.1v1 +# MS.SHAREPOINT.3.1v1 #-- -# At this time we are unable to test for X because of Y +# At this time we are unable to test for sharing settings of specific SharePoint sites +# because we have yet to find the setting to check tests[{ "PolicyId" : PolicyId, "Criticality" : "Should/Not-Implemented", @@ -100,131 +127,131 @@ tests[{ "ReportDetails" : NotCheckedDetails(PolicyId), "RequirementMet" : false }] { - PolicyId := "MS.SHAREPOINT.2.1v1" + PolicyId := "MS.SHAREPOINT.3.1v1" true } #-- +################### +# MS.SHAREPOINT.4 # +################### + # -# MS.SHAREPOINT.3.1v1 +# MS.SHAREPOINT.4.1v1 #-- -ReportDetails2_4_1(Policy) = Description if { +ExpirationTimersGuestAccess(Policy) = [ErrMsg, Status] if { Policy.SharingCapability == 0 - Description := "Requirement met" + ErrMsg := "" + Status := true } -ReportDetails2_4_1(Policy) = Description if { +ExpirationTimersGuestAccess(Policy) = [ErrMsg, Status] if { Policy.SharingCapability != 0 Policy.ExternalUserExpirationRequired == true - Policy.ExternalUserExpireInDays == 30 - Description := "Requirement met" + Policy.ExternalUserExpireInDays <= 30 + ErrMsg := "" + Status := true } -ReportDetails2_4_1(Policy) = Description if { +ExpirationTimersGuestAccess(Policy) = [ErrMsg, Status] if { Policy.SharingCapability != 0 Policy.ExternalUserExpirationRequired == false - Policy.ExternalUserExpireInDays == 30 - Description := "Requirement not met: Expiration timer for 'Guest access to a site or OneDrive' NOT enabled" + Policy.ExternalUserExpireInDays <= 30 + ErrMsg := "Requirement not met: Expiration timer for 'Guest access to a site or OneDrive' NOT enabled" + Status := false } -ReportDetails2_4_1(Policy) = Description if { +ExpirationTimersGuestAccess(Policy) = [ErrMsg, Status] if { Policy.SharingCapability != 0 Policy.ExternalUserExpirationRequired == true - Policy.ExternalUserExpireInDays != 30 - Description := "Requirement not met: Expiration timer for 'Guest access to a site or OneDrive' NOT set to 30 days" + Policy.ExternalUserExpireInDays > 30 + ErrMsg := "Requirement not met: Expiration timer for 'Guest access to a site or OneDrive' NOT set to 30 days or less" + Status := false } -ReportDetails2_4_1(Policy) = Description if { +ExpirationTimersGuestAccess(Policy) = [ErrMsg, Status] if { Policy.SharingCapability != 0 Policy.ExternalUserExpirationRequired == false - Policy.ExternalUserExpireInDays != 30 - Description := "Requirement not met" + Policy.ExternalUserExpireInDays > 30 + ErrMsg := "Requirement not met: Expiration timer for 'Guest access to a site or OneDrive' NOT enabled and set to greater 30 days" + Status := false } - tests[{ - "PolicyId" : "MS.SHAREPOINT.3.1v1", + "PolicyId" : "MS.SHAREPOINT.4.1v1", "Criticality" : "Should", "Commandlet" : ["Get-SPOTenant", "Get-PnPTenant"], "ActualValue" : [Policy.SharingCapability, Policy.ExternalUserExpirationRequired, Policy.ExternalUserExpireInDays], - "ReportDetails" : ReportDetails2_4_1(Policy), + "ReportDetails" : ReportDetailsString(Status, ErrMsg), "RequirementMet" : Status }] { Policy := input.SPO_tenant[_] - - # Role policy requires assignment expiration, but maximum duration is 30 days - Conditions1 := [Policy.ExternalUserExpirationRequired == true, Policy.ExternalUserExpireInDays == 30] - Case := count([Condition | Condition = Conditions1[_]; Condition == false]) == 0 - - # Filter: only include rules that meet one of the two cases - Conditions2 := [Policy.SharingCapability == 0, Case] - Status := count([Condition | Condition = Conditions2[_]; Condition == true]) > 0 + [ErrMsg, Status] := ExpirationTimersGuestAccess(Policy) } #-- -# TODO: Resolve Policy Id -# Baseline 2.4: Policy 2 +# +# MS.SHAREPOINT.4.2v1 #-- -ReportDetails2_4_2(Policy) = Description if { +ExpirationTimersVerificationCode(Policy) = [ErrMsg, Status] if { Policy.SharingCapability == 0 - Description := "Requirement met" + ErrMsg := "" + Status := true } -ReportDetails2_4_2(Policy) = Description if { +ExpirationTimersVerificationCode(Policy) = [ErrMsg, Status] if { Policy.SharingCapability != 0 Policy.EmailAttestationRequired == true - Policy.EmailAttestationReAuthDays == 30 - Description := "Requirement met" + Policy.EmailAttestationReAuthDays <= 30 + ErrMsg := "" + Status := true } -ReportDetails2_4_2(Policy) = Description if { +ExpirationTimersVerificationCode(Policy) = [ErrMsg, Status] if { Policy.SharingCapability != 0 Policy.EmailAttestationRequired == false - Policy.EmailAttestationReAuthDays == 30 - Description := "Requirement not met: Expiration timer for 'People who use a verification code' NOT enabled" + Policy.EmailAttestationReAuthDays <= 30 + ErrMsg := "Requirement not met: Expiration timer for 'People who use a verification code' NOT enabled" + Status := false } -ReportDetails2_4_2(Policy) = Description if { +ExpirationTimersVerificationCode(Policy) = [ErrMsg, Status] if { Policy.SharingCapability != 0 Policy.EmailAttestationRequired == true - Policy.EmailAttestationReAuthDays != 30 - Description := "Requirement not met: Expiration timer for 'People who use a verification code' NOT set to 30 days" + Policy.EmailAttestationReAuthDays > 30 + ErrMsg := "Requirement not met: Expiration timer for 'People who use a verification code' NOT set to 30 days" + Status := false } -ReportDetails2_4_2(Policy) = Description if { +ExpirationTimersVerificationCode(Policy) = [ErrMsg, Status] if { Policy.SharingCapability != 0 Policy.EmailAttestationRequired == false - Policy.EmailAttestationReAuthDays != 30 - Description := "Requirement not met" + Policy.EmailAttestationReAuthDays > 30 + ErrMsg := "Requirement not met: Expiration timer for 'People who use a verification code' NOT enabled and set to greater 30 days" + Status := false } - tests[{ - "Requirement" : "Expiration timer for 'People who use a verification code' should be set to 30 days", - "Control" : "Sharepoint 2.4", + "PolicyId" : "MS.SHAREPOINT.4.2v1", "Criticality" : "Should", "Commandlet" : ["Get-SPOTenant", "Get-PnPTenant"], "ActualValue" : [Policy.SharingCapability, Policy.EmailAttestationRequired, Policy.EmailAttestationReAuthDays], - "ReportDetails" : ReportDetails2_4_2(Policy), + "ReportDetails" : ReportDetailsString(Status, ErrMsg), "RequirementMet" : Status }] { Policy := input.SPO_tenant[_] - - # Role policy requires assignment expiration, but maximum duration is 30 days - Conditions1 := [Policy.EmailAttestationRequired == true, Policy.EmailAttestationReAuthDays == 30] - Case := count([Condition | Condition = Conditions1[_]; Condition == false]) == 0 - - # Filter: only include rules that meet one of the two cases - Conditions2 := [Policy.SharingCapability == 0, Case] - Status := count([Condition | Condition = Conditions2[_]; Condition == true]) > 0 + [ErrMsg, Status] := ExpirationTimersVerificationCode(Policy) } #-- -# TODO: Resolve Policy Id -# Baseline 2.5: Policy 1 +################### +# MS.SHAREPOINT.5 # +################### + +# +# MS.SHAREPOINT.5.1v1 #-- -# At this time we are unable to test for X because of Y +# At this time we are unable to test for running custom scripts on personal sites +# because we have yet to find the setting to check tests[{ - "Requirement" : "Users SHALL be prevented from running custom scripts on personal sites (OneDrive)", - "Control" : "Sharepoint 2.5", "PolicyId" : PolicyId, "Criticality" : "Shall/Not-Implemented", "Commandlet" : [], @@ -232,26 +259,27 @@ tests[{ "ReportDetails" : NotCheckedDetails(PolicyId), "RequirementMet" : false }] { - PolicyId := "MS.SHAREPOINT.TBD" + PolicyId := "MS.SHAREPOINT.5.1v1" true } #-- -# TODO: Resolve Policy Id -# Baseline 2.5: Policy 2 +# +# MS.SHAREPOINT.5.2v1 #-- + +# 1 == Allow users to run custom script on self-service created sites +# 2 == Prevent users from running custom script on self-service created sites + tests[{ - "Requirement" : "Users SHALL be prevented from running custom scripts on self-service created sites", - "Control" : "Sharepoint 2.5", + "PolicyId" : "MS.SHAREPOINT.5.2v1", "Criticality" : "Shall", "Commandlet" : ["Get-SPOSite", "Get-PnPTenantSite"], - "ActualValue" : Policy.DenyAddAndCustomizePages, + "ActualValue" : [Policy.DenyAddAndCustomizePages], "ReportDetails" : ReportDetailsBoolean(Status), "RequirementMet" : Status }] { Policy := input.SPO_site[_] - # 1 == Allow users to run custom script on self-service created sites - # 2 == Prevent users from running custom script on self-service created sites Status := Policy.DenyAddAndCustomizePages == 2 } #-- \ No newline at end of file diff --git a/Testing/Unit/PowerShell/CreateReport/CreateReportStubs/TestResults.json b/Testing/Unit/PowerShell/CreateReport/CreateReportStubs/TestResults.json index ed79cc0e36..917da84cd7 100644 --- a/Testing/Unit/PowerShell/CreateReport/CreateReportStubs/TestResults.json +++ b/Testing/Unit/PowerShell/CreateReport/CreateReportStubs/TestResults.json @@ -1,2318 +1,2318 @@ [ - { - "ActualValue": "", - "Commandlet": [ - "Get-MgSubscribedSku", - "Get-PrivilegedUser" - ], - "Criticality": "Shall", - "PolicyId": "MS.AAD.12.1v1", - "ReportDetails": "0 admin(s) that are not cloud-only found", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Shall/Not-Implemented", - "PolicyId": "MS.AAD.4.2v1", - "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Shall/Not-Implemented", - "PolicyId": "MS.AAD.4.3v1", - "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Shall/Not-Implemented", - "PolicyId": "MS.AAD.4.4v1", - "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Shall/Not-Implemented", - "PolicyId": "MS.AAD.5.1v1", - "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Shall/Not-Implemented", - "PolicyId": "MS.AAD.5.4v1", - "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Shall/Not-Implemented", - "PolicyId": "MS.AAD.8.1v1", - "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Should/Not-Implemented", - "PolicyId": "MS.AAD.18.2v1", - "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Should/Not-Implemented", - "PolicyId": "MS.AAD.2.2v1", - "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Should/Not-Implemented", - "PolicyId": "MS.AAD.5.2v1", - "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Should/Not-Implemented", - "PolicyId": "MS.AAD.5.3v1", - "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", - "RequirementMet": false - }, - { - "ActualValue": { - "all_allow_invite_values": [ - { - "AllowInvitesFromValue": "everyone", - "PolicyId": "authorizationPolicy" - } - ] - }, - "Commandlet": [ - "Get-MgPolicyAuthorizationPolicy" - ], - "Criticality": "Should", - "PolicyId": "MS.AAD.18.1v1", - "ReportDetails": "Permission level set to \"everyone\" (authorizationPolicy)", - "RequirementMet": false - }, - { - "ActualValue": { - "all_allowed_create_values": [ - { - "DefaultUser_AllowedToCreateApps": true, - "PolicyId": "authorizationPolicy" - } - ] - }, - "Commandlet": [ - "Get-MgPolicyAuthorizationPolicy" - ], - "Criticality": "Shall", - "PolicyId": "MS.AAD.6.1v1", - "ReportDetails": "1 authorization policies found that allow non-admin users to register third-party applications:
authorizationPolicy", - "RequirementMet": false - }, - { - "ActualValue": { - "all_consent_policies": [ - { - "IsEnabled": true, - "PolicyId": null - } - ] - }, - "Commandlet": [ - "Get-MgPolicyAdminConsentRequestPolicy" - ], - "Criticality": "Shall", - "PolicyId": "MS.AAD.7.2v1", - "ReportDetails": "Requirement met", - "RequirementMet": true - }, - { - "ActualValue": { - "all_grant_policy_values": [ - { - "DefaultUser_DefaultGrantPolicy": [ - "ManagePermissionGrantsForSelf.microsoft-user-default-legacy" - ], - "PolicyId": "authorizationPolicy" - } - ] - }, - "Commandlet": [ - "Get-MgPolicyAuthorizationPolicy" - ], - "Criticality": "Shall", - "PolicyId": "MS.AAD.7.1v1", - "ReportDetails": "1 authorization policies found that allow non-admin users to consent to third-party applications:
authorizationPolicy", - "RequirementMet": false - }, - { - "ActualValue": { - "all_roleid_values": [ - { - "GuestUserRoleId": "10dae51f-b6af-4016-8d66-8c2a99b929b3", - "GuestUserRoleIdString": "Limited access", - "Id": "authorizationPolicy" - } - ] - }, - "Commandlet": [ - "Get-MgPolicyAuthorizationPolicy" - ], - "Criticality": "Should", - "PolicyId": "MS.AAD.18.3v1", - "ReportDetails": "Permission level set to \"Limited access\" (authorizationPolicy)", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-MgIdentityConditionalAccessPolicy" - ], - "Criticality": "Shall", - "PolicyId": "MS.AAD.9.1v1", - "ReportDetails": "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies.", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-MgIdentityConditionalAccessPolicy" - ], - "Criticality": "Should", - "PolicyId": "MS.AAD.17.1v1", - "ReportDetails": "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies.", - "RequirementMet": false - }, - { - "ActualValue": [ - "Addam Schroll", - "Andrew Huynh", - "Grant Dasher", - "Nanda Katikaneni", - "Shanti Satyapal", - "Ted Kolovos", - "Thomas Comeau" - ], - "Commandlet": [ - "Get-MgSubscribedSku", - "Get-PrivilegedUser" - ], - "Criticality": "Shall", - "PolicyId": "MS.AAD.11.1v1", - "ReportDetails": "7 global admin(s) found:
Addam Schroll, Andrew Huynh, Grant Dasher, Nanda Katikaneni, Shanti Satyapal, Ted Kolovos, Thomas Comeau", - "RequirementMet": false - }, - { - "ActualValue": [ - "Application Administrator", - "Cloud Application Administrator", - "Hybrid Identity Administrator", - "Privileged Role Administrator", - "SharePoint Administrator" - ], - "Commandlet": [ - "Get-MgSubscribedSku", - "Get-PrivilegedRole" - ], - "Criticality": "Should", - "PolicyId": "MS.AAD.15.1v1", - "ReportDetails": "5 role(s) that do not require approval to activate found:
Application Administrator, Cloud Application Administrator, Hybrid Identity Administrator, Privileged Role Administrator, SharePoint Administrator", - "RequirementMet": false - }, - { - "ActualValue": [ - "Exchange Administrator", - "Global Administrator", - "Privileged Role Administrator", - "SharePoint Administrator" - ], - "Commandlet": [ - "Get-MgSubscribedSku", - "Get-PrivilegedRole" - ], - "Criticality": "Shall", - "PolicyId": "MS.AAD.14.2v1", - "ReportDetails": "4 role(s) assigned to users outside of PIM:
Exchange Administrator, Global Administrator, Privileged Role Administrator, SharePoint Administrator", - "RequirementMet": false - }, - { - "ActualValue": [ - "Global Administrator", - "SharePoint Administrator", - "User Administrator" - ], - "Commandlet": [ - "Get-MgSubscribedSku", - "Get-PrivilegedRole" - ], - "Criticality": "Shall", - "PolicyId": "MS.AAD.14.1v1", - "ReportDetails": "3 role(s) configured to allow permanent active assignment or expiration period too long:
Global Administrator, SharePoint Administrator, User Administrator", - "RequirementMet": false - }, - { - "ActualValue": [ - "Live - Block legacy authentication" - ], - "Commandlet": [ - "Get-MgIdentityConditionalAccessPolicy" - ], - "Criticality": "Shall", - "PolicyId": "MS.AAD.1.1v1", - "ReportDetails": "1 conditional access policy(s) found that meet(s) all requirements:
Live - Block legacy authentication. View all CA policies.", - "RequirementMet": true - }, - { - "ActualValue": [ - "Live - MFA Required for Everyone" - ], - "Commandlet": [ - "Get-MgIdentityConditionalAccessPolicy" - ], - "Criticality": "Shall", - "PolicyId": "MS.AAD.4.1v1", - "ReportDetails": "1 conditional access policy(s) found that meet(s) all requirements:
Live - MFA Required for Everyone. View all CA policies.", - "RequirementMet": true - }, - { - "ActualValue": [ - "Live - MFA required for Highly Privileged Roles" - ], - "Commandlet": [ - "Get-MgSubscribedSku", - "Get-PrivilegedRole", - "Get-MgIdentityConditionalAccessPolicy" - ], - "Criticality": "Shall", - "PolicyId": "MS.AAD.13.1v1", - "ReportDetails": "1 conditional access policy(s) found that meet(s) all requirements:
Live - MFA required for Highly Privileged Roles. View all CA policies.", - "RequirementMet": true - }, - { - "ActualValue": [ - "Live - Prevent Persistent Sessions u0026 Enforce Sign-in Frequency" - ], - "Commandlet": [ - "Get-MgIdentityConditionalAccessPolicy" - ], - "Criticality": "Shall", - "PolicyId": "MS.AAD.10.1v1", - "ReportDetails": "1 conditional access policy(s) found that meet(s) all requirements:
Live - Prevent Persistent Sessions u0026 Enforce Sign-in Frequency. View all CA policies.", - "RequirementMet": true - }, - { - "ActualValue": [ - "Live - Risky Sign Ins Block Access" - ], - "Commandlet": [ - "Get-MgIdentityConditionalAccessPolicy" - ], - "Criticality": "Shall", - "PolicyId": "MS.AAD.3.1v1", - "ReportDetails": "1 conditional access policy(s) found that meet(s) all requirements:
Live - Risky Sign Ins Block Access. View all CA policies.", - "RequirementMet": true - }, - { - "ActualValue": [ - "Live - Risky Users Block Access" - ], - "Commandlet": [ - "Get-MgIdentityConditionalAccessPolicy" - ], - "Criticality": "Shall", - "PolicyId": "MS.AAD.2.1v1", - "ReportDetails": "1 conditional access policy(s) found that meet(s) all requirements:
Live - Risky Users Block Access. View all CA policies.", - "RequirementMet": true - }, - { - "ActualValue": [ - "Privileged Role Administrator" - ], - "Commandlet": [ - "Get-MgSubscribedSku", - "Get-PrivilegedRole" - ], - "Criticality": "Shall", - "PolicyId": "MS.AAD.16.2v1", - "ReportDetails": "Requirement met", - "RequirementMet": true - }, - { - "ActualValue": [ - "Privileged Role Administrator" - ], - "Commandlet": [ - "Get-MgSubscribedSku", - "Get-PrivilegedRole" - ], - "Criticality": "Should", - "PolicyId": "MS.AAD.16.3v1", - "ReportDetails": "1 role(s) without notification e-mail configured for role activations found:
Privileged Role Administrator", - "RequirementMet": false - }, - { - "ActualValue": [ - "Privileged Role Administrator", - "User Administrator" - ], - "Commandlet": [ - "Get-MgSubscribedSku", - "Get-PrivilegedRole" - ], - "Criticality": "Shall", - "PolicyId": "MS.AAD.16.1v1", - "ReportDetails": "2 role(s) without notification e-mail configured for role assignments found:
Privileged Role Administrator, User Administrator", - "RequirementMet": false - }, - { - "ActualValue": [ - { - "Name": "EnableGroupSpecificConsent", - "SettingsGroup": "Consent Policy Settings", - "Value": "false" - } - ], - "Commandlet": [ - "Get-MgDirectorySetting" - ], - "Criticality": "Shall", - "PolicyId": "MS.AAD.7.3v1", - "ReportDetails": "Requirement met", - "RequirementMet": true - }, - { - "ActualValue": false, - "Commandlet": [ - "Get-AntiPhishPolicy" - ], - "Control": "Defender 2.5", - "Criticality": "Shall", - "ReportDetails": "Requirement not met", - "Requirement": "All safety tips SHALL be enabled: domain impersonation default policy", - "RequirementMet": false - }, - { - "ActualValue": false, - "Commandlet": [ - "Get-AntiPhishPolicy" - ], - "Control": "Defender 2.5", - "Criticality": "Shall", - "ReportDetails": "Requirement not met", - "Requirement": "All safety tips SHALL be enabled: user impersonation default policy", - "RequirementMet": false - }, - { - "ActualValue": false, - "Commandlet": [ - "Get-AntiPhishPolicy" - ], - "Control": "Defender 2.5", - "Criticality": "Shall", - "ReportDetails": "Requirement not met", - "Requirement": "All safety tips SHALL be enabled: user impersonation unusual characters default policy", - "RequirementMet": false - }, - { - "ActualValue": false, - "Commandlet": [ - "Get-AntiPhishPolicy" - ], - "Criticality": "Shall", - "PolicyId": "MS.DEFENDER.5.8v1", - "ReportDetails": "Requirement not met", - "RequirementMet": false - }, - { - "ActualValue": true, - "Commandlet": [ - "Get-AntiPhishPolicy" - ], - "Control": "Defender 2.5", - "Criticality": "Shall", - "ReportDetails": "Requirement met", - "Requirement": "All safety tips SHALL be enabled: \"?\" for unauthenticated senders for spoof default policy", - "RequirementMet": true - }, - { - "ActualValue": true, - "Commandlet": [ - "Get-AntiPhishPolicy" - ], - "Control": "Defender 2.5", - "Criticality": "Shall", - "ReportDetails": "Requirement met", - "Requirement": "All safety tips SHALL be enabled: \"via\" tag default policy", - "RequirementMet": true - }, - { - "ActualValue": true, - "Commandlet": [ - "Get-HostedContentFilterPolicy" - ], - "Control": "Defender 2.6", - "Criticality": "Shall", - "ReportDetails": "Requirement met", - "Requirement": "Zero-hour auto purge (ZAP) SHALL be enabled for phishing: default policy", - "RequirementMet": true - }, - { - "ActualValue": true, - "Commandlet": [ - "Get-HostedContentFilterPolicy" - ], - "Control": "Defender 2.6", - "Criticality": "Shall", - "ReportDetails": "Requirement met", - "Requirement": "Zero-hour auto purge (ZAP) SHALL be enabled for spam messages: default policy", - "RequirementMet": true - }, - { - "ActualValue": true, - "Commandlet": [ - "Get-HostedContentFilterPolicy" - ], - "Criticality": "Shall", - "PolicyId": "MS.DEFENDER.6.7v1", - "ReportDetails": "Requirement met", - "RequirementMet": true - }, - { - "ActualValue": true, - "Commandlet": [ - "Get-HostedContentFilterPolicy" - ], - "Criticality": "Should", - "PolicyId": "MS.DEFENDER.6.6v1", - "ReportDetails": "Requirement met", - "RequirementMet": true - }, - { - "ActualValue": 7, - "Commandlet": [ - "Get-HostedContentFilterPolicy" - ], - "Criticality": "Should", - "PolicyId": "MS.DEFENDER.6.1v1", - "ReportDetails": "Requirement not met", - "RequirementMet": false - }, - { - "ActualValue": 15, - "Commandlet": [ - "Get-HostedContentFilterPolicy" - ], - "Criticality": "Should", - "PolicyId": "MS.DEFENDER.6.5v1", - "ReportDetails": "Requirement not met", - "RequirementMet": false - }, - { - "ActualValue": "MoveToJmf", - "Commandlet": [ - "Get-AntiPhishPolicy" - ], - "Criticality": "Shall", - "PolicyId": "MS.DEFENDER.5.7v1", - "ReportDetails": "Requirement not met", - "RequirementMet": false - }, - { - "ActualValue": "MoveToJmf", - "Commandlet": [ - "Get-HostedContentFilterPolicy" - ], - "Control": "Defender 2.6", - "Criticality": "Shall", - "ReportDetails": "Requirement met", - "Requirement": "High confidence spam SHALL be moved to either the junk email folder or the quarantine folder: default policy", - "RequirementMet": true - }, - { - "ActualValue": "MoveToJmf", - "Commandlet": [ - "Get-HostedContentFilterPolicy" - ], - "Criticality": "Shall", - "PolicyId": "MS.DEFENDER.6.2v1", - "ReportDetails": "Requirement met", - "RequirementMet": true - }, - { - "ActualValue": "MoveToJmf", - "Commandlet": [ - "Get-HostedContentFilterPolicy" - ], - "Criticality": "Shall", - "PolicyId": "MS.DEFENDER.6.3v1", - "ReportDetails": "Requirement not met", - "RequirementMet": false - }, - { - "ActualValue": "MoveToJmf", - "Commandlet": [ - "Get-HostedContentFilterPolicy" - ], - "Criticality": "Should", - "PolicyId": "MS.DEFENDER.6.4v1", - "ReportDetails": "Requirement met", - "RequirementMet": true - }, - { - "ActualValue": "NoAction", - "Commandlet": [ - "Get-AntiPhishPolicy" - ], - "Control": "Defender 2.5", - "Criticality": "Shall", - "ReportDetails": "Requirement not met", - "Requirement": "Message action SHALL be set to quarantine if the message is detected as impersonated: domains default policy", - "RequirementMet": false - }, - { - "ActualValue": "NoAction", - "Commandlet": [ - "Get-AntiPhishPolicy" - ], - "Control": "Defender 2.5", - "Criticality": "Shall", - "ReportDetails": "Requirement not met", - "Requirement": "Message action SHALL be set to quarantine if the message is detected as impersonated: mailbox default policy", - "RequirementMet": false - }, - { - "ActualValue": "NoAction", - "Commandlet": [ - "Get-AntiPhishPolicy" - ], - "Criticality": "Shall", - "PolicyId": "MS.DEFENDER.5.6v1", - "ReportDetails": "Requirement not met", - "RequirementMet": false - }, - { - "ActualValue": "Quarantine", - "Commandlet": [ - "Get-HostedContentFilterPolicy" - ], - "Control": "Defender 2.6", - "Criticality": "Shall", - "ReportDetails": "Requirement met", - "Requirement": "High confidence phishing SHALL be quarantined: default policy", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Shall/Not-Implemented", - "PolicyId": "MS.DEFENDER.10.2v1", - "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Shall/Not-Implemented", - "PolicyId": "MS.DEFENDER.10.3v1", - "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Should/Not-Implemented", - "PolicyId": "MS.DEFENDER.2.5v1", - "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Should/Not-Implemented", - "PolicyId": "MS.DEFENDER.2.6v1", - "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Should/Not-Implemented", - "PolicyId": "MS.DEFENDER.9.2v1", - "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-AntiPhishPolicy" - ], - "Control": "Defender 2.5", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "All safety tips SHOULD be enabled: \"?\" for unauthenticated senders for spoof non-default policies", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-AntiPhishPolicy" - ], - "Control": "Defender 2.5", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "All safety tips SHOULD be enabled: \"via\" tag non-default policies", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-AntiPhishPolicy" - ], - "Control": "Defender 2.5", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "All safety tips SHOULD be enabled: domain impersonation non-default policies", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-AntiPhishPolicy" - ], - "Control": "Defender 2.5", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "All safety tips SHOULD be enabled: first contact non-default policies", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-AntiPhishPolicy" - ], - "Control": "Defender 2.5", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "All safety tips SHOULD be enabled: user impersonation non-default policies", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-AntiPhishPolicy" - ], - "Control": "Defender 2.5", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "All safety tips SHOULD be enabled: user impersonation unusual characters non-default policies", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-AntiPhishPolicy" - ], - "Control": "Defender 2.5", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "Mail classified as spoofed SHOULD be quarantined: non-default policies", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-AntiPhishPolicy" - ], - "Control": "Defender 2.5", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "Message action SHOULD be set to quarantine if the message is detected as impersonated: domains non-default policies", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-AntiPhishPolicy" - ], - "Control": "Defender 2.5", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "Message action SHOULD be set to quarantine if the message is detected as impersonated: mailbox non-default policies", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-AntiPhishPolicy" - ], - "Control": "Defender 2.5", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "Message action SHOULD be set to quarantine if the message is detected as impersonated: users non-default policies", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-AntiPhishPolicy" - ], - "Criticality": "Should", - "PolicyId": "MS.DEFENDER.5.1v1", - "ReportDetails": "No users are included for targeted user protection.", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-AntiPhishPolicy" - ], - "Criticality": "Should", - "PolicyId": "MS.DEFENDER.5.2v1", - "ReportDetails": "Requirement not met", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-AntiPhishPolicy" - ], - "Criticality": "Should", - "PolicyId": "MS.DEFENDER.5.3v1", - "ReportDetails": "The Custom Domains protection policies: Enabled, EnableTargetedDomainsProtection, and TargetedDomainsToProtect are not set correctly", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-AntiPhishPolicy" - ], - "Criticality": "Should", - "PolicyId": "MS.DEFENDER.5.5v1", - "ReportDetails": "Requirement not met", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-DLPCompliancePolicy" - ], - "Control": "Defender 2.2", - "Criticality": "Should", - "ReportDetails": "No policy found that applies to OneDrive.", - "Requirement": "The custom policy SHOULD be applied in OneDrive", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-DLPCompliancePolicy" - ], - "Control": "Defender 2.2", - "Criticality": "Should", - "ReportDetails": "No policy found that applies to SharePoint.", - "Requirement": "The custom policy SHOULD be applied in SharePoint", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-DLPCompliancePolicy" - ], - "Control": "Defender 2.2", - "Criticality": "Should", - "ReportDetails": "No policy found that applies to Teams.", - "Requirement": "The custom policy SHOULD be applied in Teams", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-DLPCompliancePolicy" - ], - "Criticality": "Should", - "PolicyId": "MS.DEFENDER.2.2v1", - "ReportDetails": "No policy found that applies to Exchange.", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-DlpComplianceRule" - ], - "Control": "Defender 2.2", - "Criticality": "Shall", - "ReportDetails": "No matching rule found for Credit Card Number", - "Requirement": "A custom policy SHALL be configured to protect PII and sensitive information, as defined by the agency: Credit Card Number", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-DlpComplianceRule" - ], - "Control": "Defender 2.2", - "Criticality": "Shall", - "ReportDetails": "No matching rule found for U.S. Individual Taxpayer Identification Number (ITIN)", - "Requirement": "A custom policy SHALL be configured to protect PII and sensitive information, as defined by the agency: U.S. Individual Taxpayer Identification Number (ITIN)", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-DlpComplianceRule" - ], - "Criticality": "Shall", - "PolicyId": "MS.DEFENDER.2.1v1", - "ReportDetails": "No matching rule found for U.S. Social Security Number (SSN)", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-DlpComplianceRule" - ], - "Criticality": "Should", - "PolicyId": "MS.DEFENDER.2.3v1", - "ReportDetails": "Requirement met", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-DlpComplianceRule" - ], - "Criticality": "Should", - "PolicyId": "MS.DEFENDER.2.4v1", - "ReportDetails": "Requirement met", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-EOPProtectionPolicyRule" - ], - "Control": "Defender 2.1", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "Strict Preset security profiles SHOULD NOT be used", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-EOPProtectionPolicyRule" - ], - "Criticality": "Should", - "PolicyId": "MS.DEFENDER.1.1v1", - "ReportDetails": "Requirement met", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-HostedContentFilterPolicy" - ], - "Control": "Defender 2.6", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "Allowed senders MAY be added but allowed domains SHOULD NOT be added: non-default", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-HostedContentFilterPolicy" - ], - "Control": "Defender 2.6", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "Bulk email SHOULD be moved to either the junk email folder or the quarantine folder: non-default policies", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-HostedContentFilterPolicy" - ], - "Control": "Defender 2.6", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "High confidence phishing SHOULD be quarantined: non-default policies", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-HostedContentFilterPolicy" - ], - "Control": "Defender 2.6", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "High confidence spam SHOULD be moved to either the junk email folder or the quarantine folder: non-default policies", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-HostedContentFilterPolicy" - ], - "Control": "Defender 2.6", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "Phishing SHOULD be quarantined: non-default policies", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-HostedContentFilterPolicy" - ], - "Control": "Defender 2.6", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "Spam SHOULD be moved to either the junk email folder or the quarantine folder: non-default policies", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-HostedContentFilterPolicy" - ], - "Control": "Defender 2.6", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "Spam in quarantine SHOULD be retained for at least 30 days: non-default policies", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-HostedContentFilterPolicy" - ], - "Control": "Defender 2.6", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "Spam safety tips SHOULD be turned on: non-default policies", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-HostedContentFilterPolicy" - ], - "Control": "Defender 2.6", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "The bulk complaint level (BCL) threshold SHOULD be set to six or lower: non-default policies", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-HostedContentFilterPolicy" - ], - "Control": "Defender 2.6", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "Zero-hour auto purge (ZAP) SHOULD be enabled for Spam: non-default", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-HostedContentFilterPolicy" - ], - "Control": "Defender 2.6", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "Zero-hour auto purge (ZAP) SHOULD be enabled for phishing: non-default", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-HostedContentFilterPolicy" - ], - "Control": "Defender 2.6", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "Zero-hour auto purge (ZAP) SHOULD be enabled: non-default", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-HostedContentFilterPolicy" - ], - "Criticality": "Shall", - "PolicyId": "MS.DEFENDER.6.8v1", - "ReportDetails": "Requirement met", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-MalwareFilterPolicy" - ], - "Criticality": "Shall", - "PolicyId": "MS.DEFENDER.3.1v1", - "ReportDetails": "Requirement met", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-MalwareFilterPolicy" - ], - "Criticality": "Should", - "PolicyId": "MS.DEFENDER.4.1v1", - "ReportDetails": "Requirement met", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-SafeAttachmentPolicy", - "Get-SafeAttachmentRule", - "Get-AcceptedDomain" - ], - "Criticality": "Shall", - "PolicyId": "MS.DEFENDER.8.2v1", - "ReportDetails": "No enabled policy found with action set to block that apply to all domains", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-SafeAttachmentPolicy", - "Get-SafeAttachmentRule", - "Get-AcceptedDomain" - ], - "Criticality": "Should", - "PolicyId": "MS.DEFENDER.8.3v1", - "ReportDetails": "No enabled policy found with action set to block and at least one contact specified", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-SafeAttachmentRule", - "Get-AcceptedDomain" - ], - "Criticality": "Shall", - "PolicyId": "MS.DEFENDER.8.1v1", - "ReportDetails": "No policy found that applies to all domains: alexwilber.myo365.site, y2zj1.onmicrosoft.com", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-SafeLinksPolicy", - "Get-SafeLinksRule" - ], - "Criticality": "Shall", - "PolicyId": "MS.DEFENDER.7.2v1", - "ReportDetails": "Requirement not met", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-SafeLinksPolicy", - "Get-SafeLinksRule" - ], - "Criticality": "Shall", - "PolicyId": "MS.DEFENDER.7.3v1", - "ReportDetails": "Requirement not met", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-SafeLinksPolicy", - "Get-SafeLinksRule" - ], - "Criticality": "Shall", - "PolicyId": "MS.DEFENDER.7.4v1", - "ReportDetails": "Requirement not met", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-SafeLinksPolicy", - "Get-SafeLinksRule" - ], - "Criticality": "Shall", - "PolicyId": "MS.DEFENDER.7.5v1", - "ReportDetails": "Requirement not met", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-SafeLinksPolicy", - "Get-SafeLinksRule" - ], - "Criticality": "Shall", - "PolicyId": "MS.DEFENDER.7.6v1", - "ReportDetails": "Requirement not met", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-SafeLinksPolicy", - "Get-SafeLinksRule" - ], - "Criticality": "Shall", - "PolicyId": "MS.DEFENDER.7.7v1", - "ReportDetails": "Requirement not met", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-SafeLinksPolicy", - "Get-SafeLinksRule" - ], - "Criticality": "Shall", - "PolicyId": "MS.DEFENDER.7.8v1", - "ReportDetails": "Requirement not met", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-SafeLinksPolicy", - "Get-SafeLinksRule" - ], - "Criticality": "Shall", - "PolicyId": "MS.DEFENDER.7.9v1", - "ReportDetails": "Requirement not met", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-SafeLinksRule", - "Get-AcceptedDomain" - ], - "Criticality": "Shall", - "PolicyId": "MS.DEFENDER.7.1v1", - "ReportDetails": "No policy found that applies to all domains: alexwilber.myo365.site, y2zj1.onmicrosoft.com", - "RequirementMet": false - }, - { - "ActualValue": [ - "A potentially malicious URL click was detected", - "Malware campaign detected after delivery", - "Messages have been delayed", - "Suspicious Email Forwarding Activity", - "Suspicious connector activity", - "Suspicious email sending patterns detected", - "Tenant restricted from sending unprovisioned email", - "Unusual increase in email reported as phish", - "User restricted from sending email" - ], - "Commandlet": [ - "Get-ProtectionAlert" - ], - "Criticality": "Shall", - "PolicyId": "MS.DEFENDER.9.1v1", - "ReportDetails": "9 disabled required alert(s) found: A potentially malicious URL click was detected, Malware campaign detected after delivery, Messages have been delayed, Suspicious Email Forwarding Activity, Suspicious connector activity, Suspicious email sending patterns detected, Tenant restricted from sending unprovisioned email, Unusual increase in email reported as phish, User restricted from sending email", - "RequirementMet": false - }, - { - "ActualValue": [ - "Default" - ], - "Commandlet": [ - "Get-MalwareFilterPolicy" - ], - "Control": "Defender 2.3", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "Disallowed file types SHALL be determined and set. At a minimum, click-to-run files SHOULD be blocked: cmd files", - "RequirementMet": true - }, - { - "ActualValue": [ - "Default" - ], - "Commandlet": [ - "Get-MalwareFilterPolicy" - ], - "Control": "Defender 2.3", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "Disallowed file types SHALL be determined and set. At a minimum, click-to-run files SHOULD be blocked: vbe files", - "RequirementMet": true - }, - { - "ActualValue": [ - "Default" - ], - "Commandlet": [ - "Get-MalwareFilterPolicy" - ], - "Criticality": "Should", - "PolicyId": "MS.DEFENDER.3.2v1", - "ReportDetails": "Requirement met", - "RequirementMet": true - }, - { - "ActualValue": [ - { - "EnableATPForSPOTeamsODB": true, - "Identity": "Default" - } - ], - "Commandlet": [ - "Get-AtpPolicyForO365" - ], - "Criticality": "Should", - "PolicyId": "MS.DEFENDER.8.4v1", - "ReportDetails": "Requirement met", - "RequirementMet": true - }, - { - "ActualValue": [ - { - "Identity": "Admin Audit Log Settings", - "UnifiedAuditLogIngestionEnabled": true - } - ], - "Commandlet": [ - "Get-AdminAuditLogConfig" - ], - "Criticality": "Shall", - "PolicyId": "MS.DEFENDER.10.1v1", - "ReportDetails": "Requirement met", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Shall/3rd Party", - "PolicyId": "MS.EXO.10.1v1", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Shall/3rd Party", - "PolicyId": "MS.EXO.10.2v1", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Shall/3rd Party", - "PolicyId": "MS.EXO.14.1v1", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Shall/3rd Party", - "PolicyId": "MS.EXO.14.2v1", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Shall/3rd Party", - "PolicyId": "MS.EXO.14.3v1", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Shall/3rd Party", - "PolicyId": "MS.EXO.16.1v1", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Shall/3rd Party", - "PolicyId": "MS.EXO.17.1v1", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Shall/3rd Party", - "PolicyId": "MS.EXO.17.2v1", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Shall/3rd Party", - "PolicyId": "MS.EXO.17.3v1", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Shall/3rd Party", - "PolicyId": "MS.EXO.8.1v1", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Shall/3rd Party", - "PolicyId": "MS.EXO.8.2v1", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Shall/3rd Party", - "PolicyId": "MS.EXO.9.1v1", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Shall/3rd Party", - "PolicyId": "MS.EXO.9.3v1", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Shall/Not-Implemented", - "PolicyId": "MS.EXO.2.1v1", - "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Should/3rd Party", - "PolicyId": "MS.EXO.10.3v1", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Should/3rd Party", - "PolicyId": "MS.EXO.11.1v1", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Should/3rd Party", - "PolicyId": "MS.EXO.11.2v1", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Should/3rd Party", - "PolicyId": "MS.EXO.11.3v1", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Should/3rd Party", - "PolicyId": "MS.EXO.15.1v1", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Should/3rd Party", - "PolicyId": "MS.EXO.15.2v1", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Should/3rd Party", - "PolicyId": "MS.EXO.15.3v1", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Should/3rd Party", - "PolicyId": "MS.EXO.16.2v1", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Should/3rd Party", - "PolicyId": "MS.EXO.9.2v1", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-ScubaDmarcRecords", - "Get-AcceptedDomain" - ], - "Criticality": "Shall", - "PolicyId": "MS.EXO.4.1v1", - "ReportDetails": "Requirement met", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-ScubaDmarcRecords", - "Get-AcceptedDomain" - ], - "Criticality": "Shall", - "PolicyId": "MS.EXO.4.2v1", - "ReportDetails": "Requirement met", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-ScubaDmarcRecords", - "Get-AcceptedDomain" - ], - "Criticality": "Shall", - "PolicyId": "MS.EXO.4.3v1", - "ReportDetails": "Requirement met", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-ScubaDmarcRecords", - "Get-AcceptedDomain" - ], - "Criticality": "Should", - "PolicyId": "MS.EXO.4.4v1", - "ReportDetails": "Requirement met", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-TransportRule" - ], - "Criticality": "Shall", - "PolicyId": "MS.EXO.7.1v1", - "ReportDetails": "No transport rule found that applies warnings to emails received from outside the organization", - "RequirementMet": false - }, - { - "ActualValue": [ - [], - [ - null - ] - ], - "Commandlet": [ - "Get-DkimSigningConfig", - "Get-ScubaDkimRecords", - "Get-AcceptedDomain" - ], - "Criticality": "Should", - "PolicyId": "MS.EXO.3.1v1", - "ReportDetails": "1 of 1 agency domain(s) found in violation: alexwilber.myo365.site", - "RequirementMet": false - }, - { - "ActualValue": [ - { - "AddressBookPolicyRoutingEnabled": false, - "AdminDisplayName": "", - "AgentGeneratedMessageLoopDetectionInSmtpEnabled": true, - "AgentGeneratedMessageLoopDetectionInSubmissionEnabled": true, - "AllowLegacyTLSClients": false, - "AnonymousSenderToRecipientRatePerHour": 1800, - "AttributionRejectBeforeMServRequest": false, - "AttributionRejectConsumerMessages": false, - "ClearCategories": true, - "ConvertDisclaimerWrapperToEml": false, - "ConvertReportToMessage": false, - "CurrentTransportSystemState": "Green", - "DSNConversionMode": "PreserveDSNBody", - "DiagnosticsAggregationServicePort": 9710, - "DistinguishedName": "CN=Transport Settings,CN=Configuration,CN=y2zj1.onmicrosoft.com,CN=ConfigurationUnits,DC=NAMPR10A008,DC=PROD,DC=OUTLOOK,DC=COM", - "EnableExternalHTTPMailDelivery": false, - "ExchangeObjectId": "b4f29764-fa61-4718-ac8d-29e1ad3007b9", - "ExchangeVersion": "0.1 (8.0.535.0)", - "ExternalDelayDsnEnabled": true, - "ExternalDsnDefaultLanguage": null, - "ExternalDsnLanguageDetectionEnabled": true, - "ExternalDsnMaxMessageAttachSize": "10 MB (10,485,760 bytes)", - "ExternalDsnReportingAuthority": null, - "ExternalDsnSendHtml": true, - "ExternalPostmasterAddress": null, - "GenerateCopyOfDSNFor": [], - "Guid": "b4f29764-fa61-4718-ac8d-29e1ad3007b9", - "HeaderPromotionModeSetting": "NoCreate", - "HygieneSuite": "Premium", - "Id": "Transport Settings", - "Identity": "Transport Settings", - "InternalDelayDsnEnabled": true, - "InternalDsnDefaultLanguage": null, - "InternalDsnLanguageDetectionEnabled": true, - "InternalDsnMaxMessageAttachSize": "10 MB (10,485,760 bytes)", - "InternalDsnReportingAuthority": null, - "InternalDsnSendHtml": true, - "InternalSMTPServers": [], - "IsValid": true, - "JournalArchivingEnabled": false, - "JournalMessageExpirationDays": 0, - "JournalReportDLMemberSubstitutionEnabled": false, - "JournalingReportNdrTo": "u003cu003e", - "LegacyArchiveJournalingEnabled": false, - "LegacyArchiveLiveJournalingEnabled": false, - "LegacyJournalingMigrationEnabled": false, - "MaxAllowedAgentGeneratedMessageDepth": 3, - "MaxAllowedAgentGeneratedMessageDepthPerAgent": 2, - "MaxDumpsterSizePerDatabase": "18 MB (18,874,368 bytes)", - "MaxDumpsterTime": "7.00:00:00", - "MaxReceiveSize": "Unlimited", - "MaxRecipientEnvelopeLimit": "Unlimited", - "MaxSendSize": "Unlimited", - "MessageExpiration": "1.00:00:00", - "MigrationEnabled": true, - "Name": "Transport Settings", - "ObjectCategory": "NAMPR10A008.PROD.OUTLOOK.COM/Configuration/Schema/ms-Exch-Transport-Settings", - "ObjectClass": [ - "top", - "container", - "msExchTransportSettings" - ], - "ObjectState": "Unchanged", - "OpenDomainRoutingEnabled": false, - "OrganizationFederatedMailbox": "FederatedEmail.4c1f4d8b-8179-4148-93bf-00a95fa1e042@y2zj1.onmicrosoft.com", - "OrganizationId": "NAMPR10A008.PROD.OUTLOOK.COM/Microsoft Exchange Hosted Organizations/y2zj1.onmicrosoft.com - NAMPR10A008.PROD.OUTLOOK.COM/ConfigurationUnits/y2zj1.onmicrosoft.com/Configuration", - "OrganizationalUnitRoot": "y2zj1.onmicrosoft.com", - "OriginatingServer": "DM5PR10A08DC002.NAMPR10A008.PROD.OUTLOOK.COM", - "OtherWellKnownObjects": [], - "PreserveReportBodypart": true, - "QueueDiagnosticsAggregationInterval": "00:01:00", - "RedirectDLMessagesForLegacyArchiveJournaling": false, - "RedirectUnprovisionedUserMessagesForLegacyArchiveJournaling": false, - "ReplyAllStormBlockDurationHours": 6, - "ReplyAllStormDetectionMinimumRecipients": 2500, - "ReplyAllStormDetectionMinimumReplies": 10, - "ReplyAllStormProtectionEnabled": true, - "Rfc2231EncodingEnabled": false, - "SafetyNetHoldTime": "7.00:00:00", - "SmtpClientAuthenticationDisabled": true, - "SupervisionTags": [ - "Reject", - "Allow" - ], - "TLSReceiveDomainSecureList": [], - "TLSSendDomainSecureList": [], - "TransportRuleAttachmentTextScanLimit": "1 MB (1,048,576 bytes)", - "TransportRuleCollectionAddedRecipientsLimit": 100, - "TransportRuleCollectionRegexCharsLimit": "20 KB (20,480 bytes)", - "TransportRuleConfig": [ - "TransportRuleMinProductVersion:14.0.0.0", - "TransportRuleRegexValidationTimeout:00:00:00.3000000", - "TransportRuleAttachmentTextScanLimit:1 MB (1,048,576 bytes)", - "TransportRuleSizeLimit:8 KB (8,192 bytes)", - "TransportRuleCollectionRegexCharsLimit:20 KB (20,480 bytes)", - "TransportRuleLimit:300", - "TransportRuleCollectionAddedRecipientsLimit:100" - ], - "TransportRuleLimit": 300, - "TransportRuleMinProductVersion": { - "Build": 0, - "Major": 14, - "MajorRevision": 0, - "Minor": 0, - "MinorRevision": 0, - "Revision": 0 - }, - "TransportRuleRegexValidationTimeout": "00:00:00.3000000", - "TransportRuleSizeLimit": "8 KB (8,192 bytes)", - "TransportSystemState": "", - "VerifySecureSubmitEnabled": false, - "VoicemailJournalingEnabled": true, - "WhenChanged": "/Date(1643184486000)/", - "WhenChangedUTC": "/Date(1643184486000)/", - "WhenCreated": "/Date(1643059670000)/", - "WhenCreatedUTC": "/Date(1643059670000)/", - "Xexch50Enabled": true - } - ], - "Commandlet": [ - "Get-TransportConfig" - ], - "Criticality": "Shall", - "PolicyId": "MS.EXO.5.1v1", - "ReportDetails": "Requirement met", - "RequirementMet": true - }, - { - "ActualValue": [ - { - "AdminDisplayName": "", - "Default": true, - "DistinguishedName": "CN=Default Sharing Policy,CN=Federation,CN=Configuration,CN=y2zj1.onmicrosoft.com,CN=ConfigurationUnits,DC=NAMPR10A008,DC=PROD,DC=OUTLOOK,DC=COM", - "Domains": [ - "Anonymous:CalendarSharingFreeBusyReviewer", - "*:CalendarSharingFreeBusySimple" - ], - "Enabled": true, - "ExchangeObjectId": "2f1ca8cf-5ba5-45e3-b73a-1405ff552a2e", - "ExchangeVersion": "0.10 (14.0.100.0)", - "Guid": "2f1ca8cf-5ba5-45e3-b73a-1405ff552a2e", - "Id": "Default Sharing Policy", - "Identity": "Default Sharing Policy", - "IsValid": true, - "Name": "Default Sharing Policy", - "ObjectCategory": "NAMPR10A008.PROD.OUTLOOK.COM/Configuration/Schema/ms-Exch-Sharing-Policy", - "ObjectClass": [ - "top", - "msExchSharingPolicy" - ], - "ObjectState": "Changed", - "OrganizationId": "NAMPR10A008.PROD.OUTLOOK.COM/Microsoft Exchange Hosted Organizations/y2zj1.onmicrosoft.com - NAMPR10A008.PROD.OUTLOOK.COM/ConfigurationUnits/y2zj1.onmicrosoft.com/Configuration", - "OrganizationalUnitRoot": "y2zj1.onmicrosoft.com", - "OriginatingServer": "DM5PR10A08DC002.NAMPR10A008.PROD.OUTLOOK.COM", - "WhenChanged": "/Date(1645650761000)/", - "WhenChangedUTC": "/Date(1645650761000)/", - "WhenCreated": "/Date(1645650752000)/", - "WhenCreatedUTC": "/Date(1645650752000)/" - } - ], - "Commandlet": [ - "Get-SharingPolicy" - ], - "Criticality": "Shall", - "PolicyId": "MS.EXO.6.1v1", - "ReportDetails": "Requirement met", - "RequirementMet": true - }, - { - "ActualValue": [ - { - "AdminDisplayName": "", - "Default": true, - "DistinguishedName": "CN=Default Sharing Policy,CN=Federation,CN=Configuration,CN=y2zj1.onmicrosoft.com,CN=ConfigurationUnits,DC=NAMPR10A008,DC=PROD,DC=OUTLOOK,DC=COM", - "Domains": [ - "Anonymous:CalendarSharingFreeBusyReviewer", - "*:CalendarSharingFreeBusySimple" - ], - "Enabled": true, - "ExchangeObjectId": "2f1ca8cf-5ba5-45e3-b73a-1405ff552a2e", - "ExchangeVersion": "0.10 (14.0.100.0)", - "Guid": "2f1ca8cf-5ba5-45e3-b73a-1405ff552a2e", - "Id": "Default Sharing Policy", - "Identity": "Default Sharing Policy", - "IsValid": true, - "Name": "Default Sharing Policy", - "ObjectCategory": "NAMPR10A008.PROD.OUTLOOK.COM/Configuration/Schema/ms-Exch-Sharing-Policy", - "ObjectClass": [ - "top", - "msExchSharingPolicy" - ], - "ObjectState": "Changed", - "OrganizationId": "NAMPR10A008.PROD.OUTLOOK.COM/Microsoft Exchange Hosted Organizations/y2zj1.onmicrosoft.com - NAMPR10A008.PROD.OUTLOOK.COM/ConfigurationUnits/y2zj1.onmicrosoft.com/Configuration", - "OrganizationalUnitRoot": "y2zj1.onmicrosoft.com", - "OriginatingServer": "DM5PR10A08DC002.NAMPR10A008.PROD.OUTLOOK.COM", - "WhenChanged": "/Date(1645650761000)/", - "WhenChangedUTC": "/Date(1645650761000)/", - "WhenCreated": "/Date(1645650752000)/", - "WhenCreatedUTC": "/Date(1645650752000)/" - } - ], - "Commandlet": [ - "Get-SharingPolicy" - ], - "Criticality": "Shall", - "PolicyId": "MS.EXO.6.2v1", - "ReportDetails": "Requirement met", - "RequirementMet": true - }, - { - "ActualValue": [ - { - "AdminDisplayName": "", - "DirectoryBasedEdgeBlockMode": "Default", - "DistinguishedName": "CN=Default,CN=Hosted Connection Filter,CN=Transport Settings,CN=Configuration,CN=y2zj1.onmicrosoft.com,CN=ConfigurationUnits,DC=NAMPR10A008,DC=PROD,DC=OUTLOOK,DC=COM", - "EnableSafeList": false, - "ExchangeObjectId": "3843aef3-f3bd-49c1-a674-4d6741ac11b6", - "ExchangeVersion": "0.20 (15.0.0.0)", - "Guid": "3843aef3-f3bd-49c1-a674-4d6741ac11b6", - "IPAllowList": [], - "IPBlockList": [], - "Id": "Default", - "Identity": "Default", - "IsDefault": true, - "IsValid": true, - "Name": "Default", - "ObjectCategory": "NAMPR10A008.PROD.OUTLOOK.COM/Configuration/Schema/ms-Exch-Hosted-Connection-Filter-Policy", - "ObjectClass": [ - "top", - "msExchHostedConnectionFilterPolicy" - ], - "ObjectState": "Unchanged", - "OrganizationId": "NAMPR10A008.PROD.OUTLOOK.COM/Microsoft Exchange Hosted Organizations/y2zj1.onmicrosoft.com - NAMPR10A008.PROD.OUTLOOK.COM/ConfigurationUnits/y2zj1.onmicrosoft.com/Configuration", - "OrganizationalUnitRoot": "y2zj1.onmicrosoft.com", - "OriginatingServer": "DM5PR10A08DC002.NAMPR10A008.PROD.OUTLOOK.COM", - "WhenChanged": "/Date(1645650833000)/", - "WhenChangedUTC": "/Date(1645650833000)/", - "WhenCreated": "/Date(1645650828000)/", - "WhenCreatedUTC": "/Date(1645650828000)/" - } - ], - "Commandlet": [ - "Get-HostedConnectionFilterPolicy" - ], - "Criticality": "Should", - "PolicyId": "MS.EXO.12.1v1", - "ReportDetails": "Requirement met", - "RequirementMet": true - }, - { - "ActualValue": [ - { - "AdminDisplayName": "", - "DirectoryBasedEdgeBlockMode": "Default", - "DistinguishedName": "CN=Default,CN=Hosted Connection Filter,CN=Transport Settings,CN=Configuration,CN=y2zj1.onmicrosoft.com,CN=ConfigurationUnits,DC=NAMPR10A008,DC=PROD,DC=OUTLOOK,DC=COM", - "EnableSafeList": false, - "ExchangeObjectId": "3843aef3-f3bd-49c1-a674-4d6741ac11b6", - "ExchangeVersion": "0.20 (15.0.0.0)", - "Guid": "3843aef3-f3bd-49c1-a674-4d6741ac11b6", - "IPAllowList": [], - "IPBlockList": [], - "Id": "Default", - "Identity": "Default", - "IsDefault": true, - "IsValid": true, - "Name": "Default", - "ObjectCategory": "NAMPR10A008.PROD.OUTLOOK.COM/Configuration/Schema/ms-Exch-Hosted-Connection-Filter-Policy", - "ObjectClass": [ - "top", - "msExchHostedConnectionFilterPolicy" - ], - "ObjectState": "Unchanged", - "OrganizationId": "NAMPR10A008.PROD.OUTLOOK.COM/Microsoft Exchange Hosted Organizations/y2zj1.onmicrosoft.com - NAMPR10A008.PROD.OUTLOOK.COM/ConfigurationUnits/y2zj1.onmicrosoft.com/Configuration", - "OrganizationalUnitRoot": "y2zj1.onmicrosoft.com", - "OriginatingServer": "DM5PR10A08DC002.NAMPR10A008.PROD.OUTLOOK.COM", - "WhenChanged": "/Date(1645650833000)/", - "WhenChangedUTC": "/Date(1645650833000)/", - "WhenCreated": "/Date(1645650828000)/", - "WhenCreatedUTC": "/Date(1645650828000)/" - } - ], - "Commandlet": [ - "Get-HostedConnectionFilterPolicy" - ], - "Criticality": "Should", - "PolicyId": "MS.EXO.12.2v1", - "ReportDetails": "Requirement met", - "RequirementMet": true - }, - { - "ActualValue": [ - { - "AuditDisabled": false, - "DisplayName": "y2zj1", - "Name": "y2zj1.onmicrosoft.com" - } - ], - "Commandlet": [ - "Get-OrganizationConfig" - ], - "Criticality": "Shall", - "PolicyId": "MS.EXO.13.1v1", - "ReportDetails": "Requirement met", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-ScubaSpfRecords", - "Get-AcceptedDomain" - ], - "Criticality": "Shall", - "PolicyId": "MS.EXO.2.2v1", - "ReportDetails": "Requirement met", - "RequirementMet": true - }, - { - "ActualValue": [ - "*" - ], - "Commandlet": [ - "Get-RemoteDomain" - ], - "Criticality": "Shall", - "PolicyId": "MS.EXO.1.1v1", - "ReportDetails": "1 remote domain(s) that allows automatic forwarding: *", - "RequirementMet": false - }, - { - "ActualValue": "PowerShell Error", - "Commandlet": [ - "Get-DlpPolicy" - ], - "Criticality": "Should", - "PolicyId": "MS.POWERPLATFORM.2.2v1", - "ReportDetails": "PowerShell Error", - "RequirementMet": false - }, - { - "ActualValue": "PowerShell Error", - "Commandlet": [ - "Get-PowerAppTenantIsolationPolicy" - ], - "Criticality": "Shall", - "PolicyId": "MS.POWERPLATFORM.3.1v1", - "ReportDetails": "PowerShell Error", - "RequirementMet": false - }, - { - "ActualValue": "PowerShell Error", - "Commandlet": [ - "Get-TenantSettings" - ], - "Control": "Power Platform 2.1", - "Criticality": "Shall", - "ReportDetails": "PowerShell Error", - "Requirement": "The ability to create trial environments SHALL be restricted to admins", - "RequirementMet": false - }, - { - "ActualValue": "PowerShell Error", - "Commandlet": [ - "Get-TenantSettings" - ], - "Criticality": "Shall", - "PolicyId": "MS.POWERPLATFORM.1.1v1", - "ReportDetails": "PowerShell Error", - "RequirementMet": false - }, - { - "ActualValue": "PowerShell error", - "Commandlet": [ - "Get-DlpPolicy" - ], - "Criticality": "Should", - "PolicyId": "MS.POWERPLATFORM.2.3v1", - "ReportDetails": "PowerShell error", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Shall/Not-Implemented", - "PolicyId": "MS.POWERPLATFORM.4.1v1", - "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Should/Not-Implemented", - "PolicyId": "MS.POWERPLATFORM.3.2v1", - "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Should/Not-Implemented", - "PolicyId": "MS.POWERPLATFORM.3.3v1", - "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-DlpPolicy" - ], - "Criticality": "Shall", - "PolicyId": "MS.POWERPLATFORM.2.1v1", - "ReportDetails": "No policy found that applies to default environment", - "RequirementMet": false - }, - { - "ActualValue": 1, - "Commandlet": [ - "Get-SPOTenant", - "Get-PnPTenant" - ], - "Criticality": "Should", - "PolicyId": "MS.SHAREPOINT.1.3v1", - "ReportDetails": "Requirement met", - "RequirementMet": true - }, - { - "ActualValue": 2, - "Commandlet": [ - "Get-SPOSite", - "Get-PnPTenantSite" - ], - "Control": "Sharepoint 2.5", - "Criticality": "Shall", - "ReportDetails": "Requirement met", - "Requirement": "Users SHALL be prevented from running custom scripts on self-service created sites", - "RequirementMet": true - }, - { - "ActualValue": 2, - "Commandlet": [ - "Get-SPOTenant", - "Get-PnPTenant" - ], - "Criticality": "Shall", - "PolicyId": "MS.SHAREPOINT.1.1v1", - "ReportDetails": "Requirement not met", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Control": "Sharepoint 2.5", - "Criticality": "Shall/Not-Implemented", - "PolicyId": "MS.SHAREPOINT.TBD", - "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", - "Requirement": "Users SHALL be prevented from running custom scripts on personal sites (OneDrive)", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Shall/Not-Implemented", - "PolicyId": "MS.SHAREPOINT.1.2v1", - "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Should/Not-Implemented", - "PolicyId": "MS.SHAREPOINT.2.1v1", - "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", - "RequirementMet": false - }, - { - "ActualValue": [ - 1, - true, - 29 - ], - "Commandlet": [ - "Get-SPOTenant", - "Get-PnPTenant" - ], - "Control": "Sharepoint 2.4", - "Criticality": "Should", - "ReportDetails": "Requirement not met: Expiration timer for 'People who use a verification code' NOT set to 30 days", - "Requirement": "Expiration timer for 'People who use a verification code' should be set to 30 days", - "RequirementMet": false - }, - { - "ActualValue": [ - 1, - true, - 31 - ], - "Commandlet": [ - "Get-SPOTenant", - "Get-PnPTenant" - ], - "Criticality": "Should", - "PolicyId": "MS.SHAREPOINT.3.1v1", - "ReportDetails": "Requirement not met: Expiration timer for 'Guest access to a site or OneDrive' NOT set to 30 days", - "RequirementMet": false - }, - { - "ActualValue": true, - "Commandlet": [ - "Get-CsTeamsMeetingPolicy" - ], - "Criticality": "Should", - "PolicyId": "MS.TEAMS.9.1v1", - "ReportDetails": "Requirement not met", - "RequirementMet": false - }, - { - "ActualValue": "AlwaysEnabled", - "Commandlet": [ - "Get-CsTeamsMeetingBroadcastPolicy" - ], - "Criticality": "Should", - "PolicyId": "MS.TEAMS.10.1v1", - "ReportDetails": "Requirement not met", - "RequirementMet": false - }, - { - "ActualValue": "EveryoneInCompany", - "Commandlet": [ - "Get-CsTeamsMeetingPolicy" - ], - "Criticality": "Should", - "PolicyId": "MS.TEAMS.3.2v1", - "ReportDetails": "Requirement met", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Shall/3rd Party", - "PolicyId": "MS.TEAMS.11.1v1", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Shall/3rd Party", - "PolicyId": "MS.TEAMS.11.4v1", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Shall/3rd Party", - "PolicyId": "MS.TEAMS.8.3v1", - "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Should/3rd Party", - "PolicyId": "MS.TEAMS.11.2v1", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Should/3rd Party", - "PolicyId": "MS.TEAMS.12.1v1", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Should/3rd Party", - "PolicyId": "MS.TEAMS.12.2v1", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Should/3rd Party", - "PolicyId": "MS.TEAMS.13.1v1", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Should/3rd Party", - "PolicyId": "MS.TEAMS.13.2v1", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Should/3rd Party", - "PolicyId": "MS.TEAMS.13.3v1", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "RequirementMet": false - }, - { - "ActualValue": [ - "EveryoneInCompany", - false - ], - "Commandlet": [ - "Get-CsTeamsMeetingPolicy" - ], - "Criticality": "Should", - "PolicyId": "MS.TEAMS.3.1v1", - "ReportDetails": "Requirement met", - "RequirementMet": true - }, - { - "ActualValue": [ - [], - "MicrosoftCommunicationsOnline/NOAM-ED6-A7" - ], - "Commandlet": [ - "Get-CsTeamsClientConfiguration" - ], - "Criticality": "Shall", - "PolicyId": "MS.TEAMS.7.1v1", - "ReportDetails": "Requirement met", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-CsTeamsAppPermissionPolicy" - ], - "Criticality": "Should", - "PolicyId": "MS.TEAMS.8.1v1", - "ReportDetails": "Requirement met", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-CsTeamsMeetingPolicy" - ], - "Control": "Teams 2.4", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "Anonymous users SHOULD be enabled to join meetings", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-CsTeamsMeetingPolicy" - ], - "Criticality": "Shall", - "PolicyId": "MS.TEAMS.2.1v1", - "ReportDetails": "Requirement met", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-CsTeamsMeetingPolicy" - ], - "Criticality": "Should", - "PolicyId": "MS.TEAMS.1.1v1", - "ReportDetails": "Requirement met", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-CsTeamsMeetingPolicy" - ], - "Criticality": "Should", - "PolicyId": "MS.TEAMS.9.3v1", - "ReportDetails": "Requirement met", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-CsTenantFederationConfiguration" - ], - "Criticality": "Shall", - "PolicyId": "MS.TEAMS.4.1v1", - "ReportDetails": "Requirement met", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-CsTenantFederationConfiguration" - ], - "Criticality": "Shall", - "PolicyId": "MS.TEAMS.6.1v1", - "ReportDetails": "Requirement met", - "RequirementMet": true - }, - { - "ActualValue": [ - "Global" - ], - "Commandlet": [ - "Get-CsTeamsAppPermissionPolicy" - ], - "Criticality": "Should", - "PolicyId": "MS.TEAMS.8.2av1", - "ReportDetails": "1 meeting policy(ies) found that allow custom apps by default: Global", - "RequirementMet": false - }, - { - "ActualValue": [ - "Global" - ], - "Commandlet": [ - "Get-CsTeamsAppPermissionPolicy" - ], - "Criticality": "Should", - "PolicyId": "MS.TEAMS.8.2v1", - "ReportDetails": "1 meeting policy(ies) found that allow third-party apps by default: Global", - "RequirementMet": false - }, - { - "ActualValue": [ - "Global" - ], - "Commandlet": [ - "Get-CsTenantFederationConfiguration" - ], - "Criticality": "Shall", - "PolicyId": "MS.TEAMS.5.1v1", - "ReportDetails": "1 Configuration allowed unmanaged users to initiate contact with internal user across domains: Global", - "RequirementMet": false - }, - { - "ActualValue": [ - "Global" - ], - "Commandlet": [ - "Get-CsTenantFederationConfiguration" - ], - "Criticality": "Should", - "PolicyId": "MS.TEAMS.5.2v1", - "ReportDetails": "1 Internal users are enabled to initiate contact with unmanaged users across domains: Global", - "RequirementMet": false - } + { + "ActualValue": "", + "Commandlet": [ + "Get-MgSubscribedSku", + "Get-PrivilegedUser" + ], + "Criticality": "Shall", + "PolicyId": "MS.AAD.12.1v1", + "ReportDetails": "0 admin(s) that are not cloud-only found", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Shall/Not-Implemented", + "PolicyId": "MS.AAD.4.2v1", + "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Shall/Not-Implemented", + "PolicyId": "MS.AAD.4.3v1", + "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Shall/Not-Implemented", + "PolicyId": "MS.AAD.4.4v1", + "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Shall/Not-Implemented", + "PolicyId": "MS.AAD.5.1v1", + "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Shall/Not-Implemented", + "PolicyId": "MS.AAD.5.4v1", + "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Shall/Not-Implemented", + "PolicyId": "MS.AAD.8.1v1", + "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Should/Not-Implemented", + "PolicyId": "MS.AAD.18.2v1", + "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Should/Not-Implemented", + "PolicyId": "MS.AAD.2.2v1", + "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Should/Not-Implemented", + "PolicyId": "MS.AAD.5.2v1", + "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Should/Not-Implemented", + "PolicyId": "MS.AAD.5.3v1", + "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", + "RequirementMet": false + }, + { + "ActualValue": { + "all_allow_invite_values": [ + { + "AllowInvitesFromValue": "everyone", + "PolicyId": "authorizationPolicy" + } + ] + }, + "Commandlet": [ + "Get-MgPolicyAuthorizationPolicy" + ], + "Criticality": "Should", + "PolicyId": "MS.AAD.18.1v1", + "ReportDetails": "Permission level set to \"everyone\" (authorizationPolicy)", + "RequirementMet": false + }, + { + "ActualValue": { + "all_allowed_create_values": [ + { + "DefaultUser_AllowedToCreateApps": true, + "PolicyId": "authorizationPolicy" + } + ] + }, + "Commandlet": [ + "Get-MgPolicyAuthorizationPolicy" + ], + "Criticality": "Shall", + "PolicyId": "MS.AAD.6.1v1", + "ReportDetails": "1 authorization policies found that allow non-admin users to register third-party applications:
authorizationPolicy", + "RequirementMet": false + }, + { + "ActualValue": { + "all_consent_policies": [ + { + "IsEnabled": true, + "PolicyId": null + } + ] + }, + "Commandlet": [ + "Get-MgPolicyAdminConsentRequestPolicy" + ], + "Criticality": "Shall", + "PolicyId": "MS.AAD.7.2v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": { + "all_grant_policy_values": [ + { + "DefaultUser_DefaultGrantPolicy": [ + "ManagePermissionGrantsForSelf.microsoft-user-default-legacy" + ], + "PolicyId": "authorizationPolicy" + } + ] + }, + "Commandlet": [ + "Get-MgPolicyAuthorizationPolicy" + ], + "Criticality": "Shall", + "PolicyId": "MS.AAD.7.1v1", + "ReportDetails": "1 authorization policies found that allow non-admin users to consent to third-party applications:
authorizationPolicy", + "RequirementMet": false + }, + { + "ActualValue": { + "all_roleid_values": [ + { + "GuestUserRoleId": "10dae51f-b6af-4016-8d66-8c2a99b929b3", + "GuestUserRoleIdString": "Limited access", + "Id": "authorizationPolicy" + } + ] + }, + "Commandlet": [ + "Get-MgPolicyAuthorizationPolicy" + ], + "Criticality": "Should", + "PolicyId": "MS.AAD.18.3v1", + "ReportDetails": "Permission level set to \"Limited access\" (authorizationPolicy)", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-MgIdentityConditionalAccessPolicy" + ], + "Criticality": "Shall", + "PolicyId": "MS.AAD.9.1v1", + "ReportDetails": "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies.", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-MgIdentityConditionalAccessPolicy" + ], + "Criticality": "Should", + "PolicyId": "MS.AAD.17.1v1", + "ReportDetails": "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies.", + "RequirementMet": false + }, + { + "ActualValue": [ + "Addam Schroll", + "Andrew Huynh", + "Grant Dasher", + "Nanda Katikaneni", + "Shanti Satyapal", + "Ted Kolovos", + "Thomas Comeau" + ], + "Commandlet": [ + "Get-MgSubscribedSku", + "Get-PrivilegedUser" + ], + "Criticality": "Shall", + "PolicyId": "MS.AAD.11.1v1", + "ReportDetails": "7 global admin(s) found:
Addam Schroll, Andrew Huynh, Grant Dasher, Nanda Katikaneni, Shanti Satyapal, Ted Kolovos, Thomas Comeau", + "RequirementMet": false + }, + { + "ActualValue": [ + "Application Administrator", + "Cloud Application Administrator", + "Hybrid Identity Administrator", + "Privileged Role Administrator", + "SharePoint Administrator" + ], + "Commandlet": [ + "Get-MgSubscribedSku", + "Get-PrivilegedRole" + ], + "Criticality": "Should", + "PolicyId": "MS.AAD.15.1v1", + "ReportDetails": "5 role(s) that do not require approval to activate found:
Application Administrator, Cloud Application Administrator, Hybrid Identity Administrator, Privileged Role Administrator, SharePoint Administrator", + "RequirementMet": false + }, + { + "ActualValue": [ + "Exchange Administrator", + "Global Administrator", + "Privileged Role Administrator", + "SharePoint Administrator" + ], + "Commandlet": [ + "Get-MgSubscribedSku", + "Get-PrivilegedRole" + ], + "Criticality": "Shall", + "PolicyId": "MS.AAD.14.2v1", + "ReportDetails": "4 role(s) assigned to users outside of PIM:
Exchange Administrator, Global Administrator, Privileged Role Administrator, SharePoint Administrator", + "RequirementMet": false + }, + { + "ActualValue": [ + "Global Administrator", + "SharePoint Administrator", + "User Administrator" + ], + "Commandlet": [ + "Get-MgSubscribedSku", + "Get-PrivilegedRole" + ], + "Criticality": "Shall", + "PolicyId": "MS.AAD.14.1v1", + "ReportDetails": "3 role(s) configured to allow permanent active assignment or expiration period too long:
Global Administrator, SharePoint Administrator, User Administrator", + "RequirementMet": false + }, + { + "ActualValue": [ + "Live - Block legacy authentication" + ], + "Commandlet": [ + "Get-MgIdentityConditionalAccessPolicy" + ], + "Criticality": "Shall", + "PolicyId": "MS.AAD.1.1v1", + "ReportDetails": "1 conditional access policy(s) found that meet(s) all requirements:
Live - Block legacy authentication. View all CA policies.", + "RequirementMet": true + }, + { + "ActualValue": [ + "Live - MFA Required for Everyone" + ], + "Commandlet": [ + "Get-MgIdentityConditionalAccessPolicy" + ], + "Criticality": "Shall", + "PolicyId": "MS.AAD.4.1v1", + "ReportDetails": "1 conditional access policy(s) found that meet(s) all requirements:
Live - MFA Required for Everyone. View all CA policies.", + "RequirementMet": true + }, + { + "ActualValue": [ + "Live - MFA required for Highly Privileged Roles" + ], + "Commandlet": [ + "Get-MgSubscribedSku", + "Get-PrivilegedRole", + "Get-MgIdentityConditionalAccessPolicy" + ], + "Criticality": "Shall", + "PolicyId": "MS.AAD.13.1v1", + "ReportDetails": "1 conditional access policy(s) found that meet(s) all requirements:
Live - MFA required for Highly Privileged Roles. View all CA policies.", + "RequirementMet": true + }, + { + "ActualValue": [ + "Live - Prevent Persistent Sessions u0026 Enforce Sign-in Frequency" + ], + "Commandlet": [ + "Get-MgIdentityConditionalAccessPolicy" + ], + "Criticality": "Shall", + "PolicyId": "MS.AAD.10.1v1", + "ReportDetails": "1 conditional access policy(s) found that meet(s) all requirements:
Live - Prevent Persistent Sessions u0026 Enforce Sign-in Frequency. View all CA policies.", + "RequirementMet": true + }, + { + "ActualValue": [ + "Live - Risky Sign Ins Block Access" + ], + "Commandlet": [ + "Get-MgIdentityConditionalAccessPolicy" + ], + "Criticality": "Shall", + "PolicyId": "MS.AAD.3.1v1", + "ReportDetails": "1 conditional access policy(s) found that meet(s) all requirements:
Live - Risky Sign Ins Block Access. View all CA policies.", + "RequirementMet": true + }, + { + "ActualValue": [ + "Live - Risky Users Block Access" + ], + "Commandlet": [ + "Get-MgIdentityConditionalAccessPolicy" + ], + "Criticality": "Shall", + "PolicyId": "MS.AAD.2.1v1", + "ReportDetails": "1 conditional access policy(s) found that meet(s) all requirements:
Live - Risky Users Block Access. View all CA policies.", + "RequirementMet": true + }, + { + "ActualValue": [ + "Privileged Role Administrator" + ], + "Commandlet": [ + "Get-MgSubscribedSku", + "Get-PrivilegedRole" + ], + "Criticality": "Shall", + "PolicyId": "MS.AAD.16.2v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [ + "Privileged Role Administrator" + ], + "Commandlet": [ + "Get-MgSubscribedSku", + "Get-PrivilegedRole" + ], + "Criticality": "Should", + "PolicyId": "MS.AAD.16.3v1", + "ReportDetails": "1 role(s) without notification e-mail configured for role activations found:
Privileged Role Administrator", + "RequirementMet": false + }, + { + "ActualValue": [ + "Privileged Role Administrator", + "User Administrator" + ], + "Commandlet": [ + "Get-MgSubscribedSku", + "Get-PrivilegedRole" + ], + "Criticality": "Shall", + "PolicyId": "MS.AAD.16.1v1", + "ReportDetails": "2 role(s) without notification e-mail configured for role assignments found:
Privileged Role Administrator, User Administrator", + "RequirementMet": false + }, + { + "ActualValue": [ + { + "Name": "EnableGroupSpecificConsent", + "SettingsGroup": "Consent Policy Settings", + "Value": "false" + } + ], + "Commandlet": [ + "Get-MgDirectorySetting" + ], + "Criticality": "Shall", + "PolicyId": "MS.AAD.7.3v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": false, + "Commandlet": [ + "Get-AntiPhishPolicy" + ], + "Control": "Defender 2.5", + "Criticality": "Shall", + "ReportDetails": "Requirement not met", + "Requirement": "All safety tips SHALL be enabled: domain impersonation default policy", + "RequirementMet": false + }, + { + "ActualValue": false, + "Commandlet": [ + "Get-AntiPhishPolicy" + ], + "Control": "Defender 2.5", + "Criticality": "Shall", + "ReportDetails": "Requirement not met", + "Requirement": "All safety tips SHALL be enabled: user impersonation default policy", + "RequirementMet": false + }, + { + "ActualValue": false, + "Commandlet": [ + "Get-AntiPhishPolicy" + ], + "Control": "Defender 2.5", + "Criticality": "Shall", + "ReportDetails": "Requirement not met", + "Requirement": "All safety tips SHALL be enabled: user impersonation unusual characters default policy", + "RequirementMet": false + }, + { + "ActualValue": false, + "Commandlet": [ + "Get-AntiPhishPolicy" + ], + "Criticality": "Shall", + "PolicyId": "MS.DEFENDER.5.8v1", + "ReportDetails": "Requirement not met", + "RequirementMet": false + }, + { + "ActualValue": true, + "Commandlet": [ + "Get-AntiPhishPolicy" + ], + "Control": "Defender 2.5", + "Criticality": "Shall", + "ReportDetails": "Requirement met", + "Requirement": "All safety tips SHALL be enabled: \"?\" for unauthenticated senders for spoof default policy", + "RequirementMet": true + }, + { + "ActualValue": true, + "Commandlet": [ + "Get-AntiPhishPolicy" + ], + "Control": "Defender 2.5", + "Criticality": "Shall", + "ReportDetails": "Requirement met", + "Requirement": "All safety tips SHALL be enabled: \"via\" tag default policy", + "RequirementMet": true + }, + { + "ActualValue": true, + "Commandlet": [ + "Get-HostedContentFilterPolicy" + ], + "Control": "Defender 2.6", + "Criticality": "Shall", + "ReportDetails": "Requirement met", + "Requirement": "Zero-hour auto purge (ZAP) SHALL be enabled for phishing: default policy", + "RequirementMet": true + }, + { + "ActualValue": true, + "Commandlet": [ + "Get-HostedContentFilterPolicy" + ], + "Control": "Defender 2.6", + "Criticality": "Shall", + "ReportDetails": "Requirement met", + "Requirement": "Zero-hour auto purge (ZAP) SHALL be enabled for spam messages: default policy", + "RequirementMet": true + }, + { + "ActualValue": true, + "Commandlet": [ + "Get-HostedContentFilterPolicy" + ], + "Criticality": "Shall", + "PolicyId": "MS.DEFENDER.6.7v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": true, + "Commandlet": [ + "Get-HostedContentFilterPolicy" + ], + "Criticality": "Should", + "PolicyId": "MS.DEFENDER.6.6v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": 7, + "Commandlet": [ + "Get-HostedContentFilterPolicy" + ], + "Criticality": "Should", + "PolicyId": "MS.DEFENDER.6.1v1", + "ReportDetails": "Requirement not met", + "RequirementMet": false + }, + { + "ActualValue": 15, + "Commandlet": [ + "Get-HostedContentFilterPolicy" + ], + "Criticality": "Should", + "PolicyId": "MS.DEFENDER.6.5v1", + "ReportDetails": "Requirement not met", + "RequirementMet": false + }, + { + "ActualValue": "MoveToJmf", + "Commandlet": [ + "Get-AntiPhishPolicy" + ], + "Criticality": "Shall", + "PolicyId": "MS.DEFENDER.5.7v1", + "ReportDetails": "Requirement not met", + "RequirementMet": false + }, + { + "ActualValue": "MoveToJmf", + "Commandlet": [ + "Get-HostedContentFilterPolicy" + ], + "Control": "Defender 2.6", + "Criticality": "Shall", + "ReportDetails": "Requirement met", + "Requirement": "High confidence spam SHALL be moved to either the junk email folder or the quarantine folder: default policy", + "RequirementMet": true + }, + { + "ActualValue": "MoveToJmf", + "Commandlet": [ + "Get-HostedContentFilterPolicy" + ], + "Criticality": "Shall", + "PolicyId": "MS.DEFENDER.6.2v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": "MoveToJmf", + "Commandlet": [ + "Get-HostedContentFilterPolicy" + ], + "Criticality": "Shall", + "PolicyId": "MS.DEFENDER.6.3v1", + "ReportDetails": "Requirement not met", + "RequirementMet": false + }, + { + "ActualValue": "MoveToJmf", + "Commandlet": [ + "Get-HostedContentFilterPolicy" + ], + "Criticality": "Should", + "PolicyId": "MS.DEFENDER.6.4v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": "NoAction", + "Commandlet": [ + "Get-AntiPhishPolicy" + ], + "Control": "Defender 2.5", + "Criticality": "Shall", + "ReportDetails": "Requirement not met", + "Requirement": "Message action SHALL be set to quarantine if the message is detected as impersonated: domains default policy", + "RequirementMet": false + }, + { + "ActualValue": "NoAction", + "Commandlet": [ + "Get-AntiPhishPolicy" + ], + "Control": "Defender 2.5", + "Criticality": "Shall", + "ReportDetails": "Requirement not met", + "Requirement": "Message action SHALL be set to quarantine if the message is detected as impersonated: mailbox default policy", + "RequirementMet": false + }, + { + "ActualValue": "NoAction", + "Commandlet": [ + "Get-AntiPhishPolicy" + ], + "Criticality": "Shall", + "PolicyId": "MS.DEFENDER.5.6v1", + "ReportDetails": "Requirement not met", + "RequirementMet": false + }, + { + "ActualValue": "Quarantine", + "Commandlet": [ + "Get-HostedContentFilterPolicy" + ], + "Control": "Defender 2.6", + "Criticality": "Shall", + "ReportDetails": "Requirement met", + "Requirement": "High confidence phishing SHALL be quarantined: default policy", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Shall/Not-Implemented", + "PolicyId": "MS.DEFENDER.10.2v1", + "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Shall/Not-Implemented", + "PolicyId": "MS.DEFENDER.10.3v1", + "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Should/Not-Implemented", + "PolicyId": "MS.DEFENDER.2.5v1", + "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Should/Not-Implemented", + "PolicyId": "MS.DEFENDER.2.6v1", + "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Should/Not-Implemented", + "PolicyId": "MS.DEFENDER.9.2v1", + "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-AntiPhishPolicy" + ], + "Control": "Defender 2.5", + "Criticality": "Should", + "ReportDetails": "Requirement met", + "Requirement": "All safety tips SHOULD be enabled: \"?\" for unauthenticated senders for spoof non-default policies", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-AntiPhishPolicy" + ], + "Control": "Defender 2.5", + "Criticality": "Should", + "ReportDetails": "Requirement met", + "Requirement": "All safety tips SHOULD be enabled: \"via\" tag non-default policies", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-AntiPhishPolicy" + ], + "Control": "Defender 2.5", + "Criticality": "Should", + "ReportDetails": "Requirement met", + "Requirement": "All safety tips SHOULD be enabled: domain impersonation non-default policies", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-AntiPhishPolicy" + ], + "Control": "Defender 2.5", + "Criticality": "Should", + "ReportDetails": "Requirement met", + "Requirement": "All safety tips SHOULD be enabled: first contact non-default policies", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-AntiPhishPolicy" + ], + "Control": "Defender 2.5", + "Criticality": "Should", + "ReportDetails": "Requirement met", + "Requirement": "All safety tips SHOULD be enabled: user impersonation non-default policies", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-AntiPhishPolicy" + ], + "Control": "Defender 2.5", + "Criticality": "Should", + "ReportDetails": "Requirement met", + "Requirement": "All safety tips SHOULD be enabled: user impersonation unusual characters non-default policies", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-AntiPhishPolicy" + ], + "Control": "Defender 2.5", + "Criticality": "Should", + "ReportDetails": "Requirement met", + "Requirement": "Mail classified as spoofed SHOULD be quarantined: non-default policies", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-AntiPhishPolicy" + ], + "Control": "Defender 2.5", + "Criticality": "Should", + "ReportDetails": "Requirement met", + "Requirement": "Message action SHOULD be set to quarantine if the message is detected as impersonated: domains non-default policies", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-AntiPhishPolicy" + ], + "Control": "Defender 2.5", + "Criticality": "Should", + "ReportDetails": "Requirement met", + "Requirement": "Message action SHOULD be set to quarantine if the message is detected as impersonated: mailbox non-default policies", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-AntiPhishPolicy" + ], + "Control": "Defender 2.5", + "Criticality": "Should", + "ReportDetails": "Requirement met", + "Requirement": "Message action SHOULD be set to quarantine if the message is detected as impersonated: users non-default policies", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-AntiPhishPolicy" + ], + "Criticality": "Should", + "PolicyId": "MS.DEFENDER.5.1v1", + "ReportDetails": "No users are included for targeted user protection.", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-AntiPhishPolicy" + ], + "Criticality": "Should", + "PolicyId": "MS.DEFENDER.5.2v1", + "ReportDetails": "Requirement not met", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-AntiPhishPolicy" + ], + "Criticality": "Should", + "PolicyId": "MS.DEFENDER.5.3v1", + "ReportDetails": "The Custom Domains protection policies: Enabled, EnableTargetedDomainsProtection, and TargetedDomainsToProtect are not set correctly", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-AntiPhishPolicy" + ], + "Criticality": "Should", + "PolicyId": "MS.DEFENDER.5.5v1", + "ReportDetails": "Requirement not met", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-DLPCompliancePolicy" + ], + "Control": "Defender 2.2", + "Criticality": "Should", + "ReportDetails": "No policy found that applies to OneDrive.", + "Requirement": "The custom policy SHOULD be applied in OneDrive", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-DLPCompliancePolicy" + ], + "Control": "Defender 2.2", + "Criticality": "Should", + "ReportDetails": "No policy found that applies to SharePoint.", + "Requirement": "The custom policy SHOULD be applied in SharePoint", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-DLPCompliancePolicy" + ], + "Control": "Defender 2.2", + "Criticality": "Should", + "ReportDetails": "No policy found that applies to Teams.", + "Requirement": "The custom policy SHOULD be applied in Teams", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-DLPCompliancePolicy" + ], + "Criticality": "Should", + "PolicyId": "MS.DEFENDER.2.2v1", + "ReportDetails": "No policy found that applies to Exchange.", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-DlpComplianceRule" + ], + "Control": "Defender 2.2", + "Criticality": "Shall", + "ReportDetails": "No matching rule found for Credit Card Number", + "Requirement": "A custom policy SHALL be configured to protect PII and sensitive information, as defined by the agency: Credit Card Number", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-DlpComplianceRule" + ], + "Control": "Defender 2.2", + "Criticality": "Shall", + "ReportDetails": "No matching rule found for U.S. Individual Taxpayer Identification Number (ITIN)", + "Requirement": "A custom policy SHALL be configured to protect PII and sensitive information, as defined by the agency: U.S. Individual Taxpayer Identification Number (ITIN)", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-DlpComplianceRule" + ], + "Criticality": "Shall", + "PolicyId": "MS.DEFENDER.2.1v1", + "ReportDetails": "No matching rule found for U.S. Social Security Number (SSN)", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-DlpComplianceRule" + ], + "Criticality": "Should", + "PolicyId": "MS.DEFENDER.2.3v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-DlpComplianceRule" + ], + "Criticality": "Should", + "PolicyId": "MS.DEFENDER.2.4v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-EOPProtectionPolicyRule" + ], + "Control": "Defender 2.1", + "Criticality": "Should", + "ReportDetails": "Requirement met", + "Requirement": "Strict Preset security profiles SHOULD NOT be used", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-EOPProtectionPolicyRule" + ], + "Criticality": "Should", + "PolicyId": "MS.DEFENDER.1.1v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-HostedContentFilterPolicy" + ], + "Control": "Defender 2.6", + "Criticality": "Should", + "ReportDetails": "Requirement met", + "Requirement": "Allowed senders MAY be added but allowed domains SHOULD NOT be added: non-default", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-HostedContentFilterPolicy" + ], + "Control": "Defender 2.6", + "Criticality": "Should", + "ReportDetails": "Requirement met", + "Requirement": "Bulk email SHOULD be moved to either the junk email folder or the quarantine folder: non-default policies", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-HostedContentFilterPolicy" + ], + "Control": "Defender 2.6", + "Criticality": "Should", + "ReportDetails": "Requirement met", + "Requirement": "High confidence phishing SHOULD be quarantined: non-default policies", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-HostedContentFilterPolicy" + ], + "Control": "Defender 2.6", + "Criticality": "Should", + "ReportDetails": "Requirement met", + "Requirement": "High confidence spam SHOULD be moved to either the junk email folder or the quarantine folder: non-default policies", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-HostedContentFilterPolicy" + ], + "Control": "Defender 2.6", + "Criticality": "Should", + "ReportDetails": "Requirement met", + "Requirement": "Phishing SHOULD be quarantined: non-default policies", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-HostedContentFilterPolicy" + ], + "Control": "Defender 2.6", + "Criticality": "Should", + "ReportDetails": "Requirement met", + "Requirement": "Spam SHOULD be moved to either the junk email folder or the quarantine folder: non-default policies", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-HostedContentFilterPolicy" + ], + "Control": "Defender 2.6", + "Criticality": "Should", + "ReportDetails": "Requirement met", + "Requirement": "Spam in quarantine SHOULD be retained for at least 30 days: non-default policies", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-HostedContentFilterPolicy" + ], + "Control": "Defender 2.6", + "Criticality": "Should", + "ReportDetails": "Requirement met", + "Requirement": "Spam safety tips SHOULD be turned on: non-default policies", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-HostedContentFilterPolicy" + ], + "Control": "Defender 2.6", + "Criticality": "Should", + "ReportDetails": "Requirement met", + "Requirement": "The bulk complaint level (BCL) threshold SHOULD be set to six or lower: non-default policies", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-HostedContentFilterPolicy" + ], + "Control": "Defender 2.6", + "Criticality": "Should", + "ReportDetails": "Requirement met", + "Requirement": "Zero-hour auto purge (ZAP) SHOULD be enabled for Spam: non-default", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-HostedContentFilterPolicy" + ], + "Control": "Defender 2.6", + "Criticality": "Should", + "ReportDetails": "Requirement met", + "Requirement": "Zero-hour auto purge (ZAP) SHOULD be enabled for phishing: non-default", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-HostedContentFilterPolicy" + ], + "Control": "Defender 2.6", + "Criticality": "Should", + "ReportDetails": "Requirement met", + "Requirement": "Zero-hour auto purge (ZAP) SHOULD be enabled: non-default", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-HostedContentFilterPolicy" + ], + "Criticality": "Shall", + "PolicyId": "MS.DEFENDER.6.8v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-MalwareFilterPolicy" + ], + "Criticality": "Shall", + "PolicyId": "MS.DEFENDER.3.1v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-MalwareFilterPolicy" + ], + "Criticality": "Should", + "PolicyId": "MS.DEFENDER.4.1v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-SafeAttachmentPolicy", + "Get-SafeAttachmentRule", + "Get-AcceptedDomain" + ], + "Criticality": "Shall", + "PolicyId": "MS.DEFENDER.8.2v1", + "ReportDetails": "No enabled policy found with action set to block that apply to all domains", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-SafeAttachmentPolicy", + "Get-SafeAttachmentRule", + "Get-AcceptedDomain" + ], + "Criticality": "Should", + "PolicyId": "MS.DEFENDER.8.3v1", + "ReportDetails": "No enabled policy found with action set to block and at least one contact specified", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-SafeAttachmentRule", + "Get-AcceptedDomain" + ], + "Criticality": "Shall", + "PolicyId": "MS.DEFENDER.8.1v1", + "ReportDetails": "No policy found that applies to all domains: alexwilber.myo365.site, y2zj1.onmicrosoft.com", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-SafeLinksPolicy", + "Get-SafeLinksRule" + ], + "Criticality": "Shall", + "PolicyId": "MS.DEFENDER.7.2v1", + "ReportDetails": "Requirement not met", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-SafeLinksPolicy", + "Get-SafeLinksRule" + ], + "Criticality": "Shall", + "PolicyId": "MS.DEFENDER.7.3v1", + "ReportDetails": "Requirement not met", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-SafeLinksPolicy", + "Get-SafeLinksRule" + ], + "Criticality": "Shall", + "PolicyId": "MS.DEFENDER.7.4v1", + "ReportDetails": "Requirement not met", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-SafeLinksPolicy", + "Get-SafeLinksRule" + ], + "Criticality": "Shall", + "PolicyId": "MS.DEFENDER.7.5v1", + "ReportDetails": "Requirement not met", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-SafeLinksPolicy", + "Get-SafeLinksRule" + ], + "Criticality": "Shall", + "PolicyId": "MS.DEFENDER.7.6v1", + "ReportDetails": "Requirement not met", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-SafeLinksPolicy", + "Get-SafeLinksRule" + ], + "Criticality": "Shall", + "PolicyId": "MS.DEFENDER.7.7v1", + "ReportDetails": "Requirement not met", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-SafeLinksPolicy", + "Get-SafeLinksRule" + ], + "Criticality": "Shall", + "PolicyId": "MS.DEFENDER.7.8v1", + "ReportDetails": "Requirement not met", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-SafeLinksPolicy", + "Get-SafeLinksRule" + ], + "Criticality": "Shall", + "PolicyId": "MS.DEFENDER.7.9v1", + "ReportDetails": "Requirement not met", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-SafeLinksRule", + "Get-AcceptedDomain" + ], + "Criticality": "Shall", + "PolicyId": "MS.DEFENDER.7.1v1", + "ReportDetails": "No policy found that applies to all domains: alexwilber.myo365.site, y2zj1.onmicrosoft.com", + "RequirementMet": false + }, + { + "ActualValue": [ + "A potentially malicious URL click was detected", + "Malware campaign detected after delivery", + "Messages have been delayed", + "Suspicious Email Forwarding Activity", + "Suspicious connector activity", + "Suspicious email sending patterns detected", + "Tenant restricted from sending unprovisioned email", + "Unusual increase in email reported as phish", + "User restricted from sending email" + ], + "Commandlet": [ + "Get-ProtectionAlert" + ], + "Criticality": "Shall", + "PolicyId": "MS.DEFENDER.9.1v1", + "ReportDetails": "9 disabled required alert(s) found: A potentially malicious URL click was detected, Malware campaign detected after delivery, Messages have been delayed, Suspicious Email Forwarding Activity, Suspicious connector activity, Suspicious email sending patterns detected, Tenant restricted from sending unprovisioned email, Unusual increase in email reported as phish, User restricted from sending email", + "RequirementMet": false + }, + { + "ActualValue": [ + "Default" + ], + "Commandlet": [ + "Get-MalwareFilterPolicy" + ], + "Control": "Defender 2.3", + "Criticality": "Should", + "ReportDetails": "Requirement met", + "Requirement": "Disallowed file types SHALL be determined and set. At a minimum, click-to-run files SHOULD be blocked: cmd files", + "RequirementMet": true + }, + { + "ActualValue": [ + "Default" + ], + "Commandlet": [ + "Get-MalwareFilterPolicy" + ], + "Control": "Defender 2.3", + "Criticality": "Should", + "ReportDetails": "Requirement met", + "Requirement": "Disallowed file types SHALL be determined and set. At a minimum, click-to-run files SHOULD be blocked: vbe files", + "RequirementMet": true + }, + { + "ActualValue": [ + "Default" + ], + "Commandlet": [ + "Get-MalwareFilterPolicy" + ], + "Criticality": "Should", + "PolicyId": "MS.DEFENDER.3.2v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [ + { + "EnableATPForSPOTeamsODB": true, + "Identity": "Default" + } + ], + "Commandlet": [ + "Get-AtpPolicyForO365" + ], + "Criticality": "Should", + "PolicyId": "MS.DEFENDER.8.4v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [ + { + "Identity": "Admin Audit Log Settings", + "UnifiedAuditLogIngestionEnabled": true + } + ], + "Commandlet": [ + "Get-AdminAuditLogConfig" + ], + "Criticality": "Shall", + "PolicyId": "MS.DEFENDER.10.1v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Shall/3rd Party", + "PolicyId": "MS.EXO.10.1v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Shall/3rd Party", + "PolicyId": "MS.EXO.10.2v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Shall/3rd Party", + "PolicyId": "MS.EXO.14.1v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Shall/3rd Party", + "PolicyId": "MS.EXO.14.2v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Shall/3rd Party", + "PolicyId": "MS.EXO.14.3v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Shall/3rd Party", + "PolicyId": "MS.EXO.16.1v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Shall/3rd Party", + "PolicyId": "MS.EXO.17.1v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Shall/3rd Party", + "PolicyId": "MS.EXO.17.2v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Shall/3rd Party", + "PolicyId": "MS.EXO.17.3v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Shall/3rd Party", + "PolicyId": "MS.EXO.8.1v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Shall/3rd Party", + "PolicyId": "MS.EXO.8.2v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Shall/3rd Party", + "PolicyId": "MS.EXO.9.1v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Shall/3rd Party", + "PolicyId": "MS.EXO.9.3v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Shall/Not-Implemented", + "PolicyId": "MS.EXO.2.1v1", + "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Should/3rd Party", + "PolicyId": "MS.EXO.10.3v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Should/3rd Party", + "PolicyId": "MS.EXO.11.1v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Should/3rd Party", + "PolicyId": "MS.EXO.11.2v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Should/3rd Party", + "PolicyId": "MS.EXO.11.3v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Should/3rd Party", + "PolicyId": "MS.EXO.15.1v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Should/3rd Party", + "PolicyId": "MS.EXO.15.2v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Should/3rd Party", + "PolicyId": "MS.EXO.15.3v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Should/3rd Party", + "PolicyId": "MS.EXO.16.2v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Should/3rd Party", + "PolicyId": "MS.EXO.9.2v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-ScubaDmarcRecords", + "Get-AcceptedDomain" + ], + "Criticality": "Shall", + "PolicyId": "MS.EXO.4.1v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-ScubaDmarcRecords", + "Get-AcceptedDomain" + ], + "Criticality": "Shall", + "PolicyId": "MS.EXO.4.2v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-ScubaDmarcRecords", + "Get-AcceptedDomain" + ], + "Criticality": "Shall", + "PolicyId": "MS.EXO.4.3v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-ScubaDmarcRecords", + "Get-AcceptedDomain" + ], + "Criticality": "Should", + "PolicyId": "MS.EXO.4.4v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-TransportRule" + ], + "Criticality": "Shall", + "PolicyId": "MS.EXO.7.1v1", + "ReportDetails": "No transport rule found that applies warnings to emails received from outside the organization", + "RequirementMet": false + }, + { + "ActualValue": [ + [], + [ + null + ] + ], + "Commandlet": [ + "Get-DkimSigningConfig", + "Get-ScubaDkimRecords", + "Get-AcceptedDomain" + ], + "Criticality": "Should", + "PolicyId": "MS.EXO.3.1v1", + "ReportDetails": "1 of 1 agency domain(s) found in violation: alexwilber.myo365.site", + "RequirementMet": false + }, + { + "ActualValue": [ + { + "AddressBookPolicyRoutingEnabled": false, + "AdminDisplayName": "", + "AgentGeneratedMessageLoopDetectionInSmtpEnabled": true, + "AgentGeneratedMessageLoopDetectionInSubmissionEnabled": true, + "AllowLegacyTLSClients": false, + "AnonymousSenderToRecipientRatePerHour": 1800, + "AttributionRejectBeforeMServRequest": false, + "AttributionRejectConsumerMessages": false, + "ClearCategories": true, + "ConvertDisclaimerWrapperToEml": false, + "ConvertReportToMessage": false, + "CurrentTransportSystemState": "Green", + "DSNConversionMode": "PreserveDSNBody", + "DiagnosticsAggregationServicePort": 9710, + "DistinguishedName": "CN=Transport Settings,CN=Configuration,CN=y2zj1.onmicrosoft.com,CN=ConfigurationUnits,DC=NAMPR10A008,DC=PROD,DC=OUTLOOK,DC=COM", + "EnableExternalHTTPMailDelivery": false, + "ExchangeObjectId": "b4f29764-fa61-4718-ac8d-29e1ad3007b9", + "ExchangeVersion": "0.1 (8.0.535.0)", + "ExternalDelayDsnEnabled": true, + "ExternalDsnDefaultLanguage": null, + "ExternalDsnLanguageDetectionEnabled": true, + "ExternalDsnMaxMessageAttachSize": "10 MB (10,485,760 bytes)", + "ExternalDsnReportingAuthority": null, + "ExternalDsnSendHtml": true, + "ExternalPostmasterAddress": null, + "GenerateCopyOfDSNFor": [], + "Guid": "b4f29764-fa61-4718-ac8d-29e1ad3007b9", + "HeaderPromotionModeSetting": "NoCreate", + "HygieneSuite": "Premium", + "Id": "Transport Settings", + "Identity": "Transport Settings", + "InternalDelayDsnEnabled": true, + "InternalDsnDefaultLanguage": null, + "InternalDsnLanguageDetectionEnabled": true, + "InternalDsnMaxMessageAttachSize": "10 MB (10,485,760 bytes)", + "InternalDsnReportingAuthority": null, + "InternalDsnSendHtml": true, + "InternalSMTPServers": [], + "IsValid": true, + "JournalArchivingEnabled": false, + "JournalMessageExpirationDays": 0, + "JournalReportDLMemberSubstitutionEnabled": false, + "JournalingReportNdrTo": "u003cu003e", + "LegacyArchiveJournalingEnabled": false, + "LegacyArchiveLiveJournalingEnabled": false, + "LegacyJournalingMigrationEnabled": false, + "MaxAllowedAgentGeneratedMessageDepth": 3, + "MaxAllowedAgentGeneratedMessageDepthPerAgent": 2, + "MaxDumpsterSizePerDatabase": "18 MB (18,874,368 bytes)", + "MaxDumpsterTime": "7.00:00:00", + "MaxReceiveSize": "Unlimited", + "MaxRecipientEnvelopeLimit": "Unlimited", + "MaxSendSize": "Unlimited", + "MessageExpiration": "1.00:00:00", + "MigrationEnabled": true, + "Name": "Transport Settings", + "ObjectCategory": "NAMPR10A008.PROD.OUTLOOK.COM/Configuration/Schema/ms-Exch-Transport-Settings", + "ObjectClass": [ + "top", + "container", + "msExchTransportSettings" + ], + "ObjectState": "Unchanged", + "OpenDomainRoutingEnabled": false, + "OrganizationFederatedMailbox": "FederatedEmail.4c1f4d8b-8179-4148-93bf-00a95fa1e042@y2zj1.onmicrosoft.com", + "OrganizationId": "NAMPR10A008.PROD.OUTLOOK.COM/Microsoft Exchange Hosted Organizations/y2zj1.onmicrosoft.com - NAMPR10A008.PROD.OUTLOOK.COM/ConfigurationUnits/y2zj1.onmicrosoft.com/Configuration", + "OrganizationalUnitRoot": "y2zj1.onmicrosoft.com", + "OriginatingServer": "DM5PR10A08DC002.NAMPR10A008.PROD.OUTLOOK.COM", + "OtherWellKnownObjects": [], + "PreserveReportBodypart": true, + "QueueDiagnosticsAggregationInterval": "00:01:00", + "RedirectDLMessagesForLegacyArchiveJournaling": false, + "RedirectUnprovisionedUserMessagesForLegacyArchiveJournaling": false, + "ReplyAllStormBlockDurationHours": 6, + "ReplyAllStormDetectionMinimumRecipients": 2500, + "ReplyAllStormDetectionMinimumReplies": 10, + "ReplyAllStormProtectionEnabled": true, + "Rfc2231EncodingEnabled": false, + "SafetyNetHoldTime": "7.00:00:00", + "SmtpClientAuthenticationDisabled": true, + "SupervisionTags": [ + "Reject", + "Allow" + ], + "TLSReceiveDomainSecureList": [], + "TLSSendDomainSecureList": [], + "TransportRuleAttachmentTextScanLimit": "1 MB (1,048,576 bytes)", + "TransportRuleCollectionAddedRecipientsLimit": 100, + "TransportRuleCollectionRegexCharsLimit": "20 KB (20,480 bytes)", + "TransportRuleConfig": [ + "TransportRuleMinProductVersion:14.0.0.0", + "TransportRuleRegexValidationTimeout:00:00:00.3000000", + "TransportRuleAttachmentTextScanLimit:1 MB (1,048,576 bytes)", + "TransportRuleSizeLimit:8 KB (8,192 bytes)", + "TransportRuleCollectionRegexCharsLimit:20 KB (20,480 bytes)", + "TransportRuleLimit:300", + "TransportRuleCollectionAddedRecipientsLimit:100" + ], + "TransportRuleLimit": 300, + "TransportRuleMinProductVersion": { + "Build": 0, + "Major": 14, + "MajorRevision": 0, + "Minor": 0, + "MinorRevision": 0, + "Revision": 0 + }, + "TransportRuleRegexValidationTimeout": "00:00:00.3000000", + "TransportRuleSizeLimit": "8 KB (8,192 bytes)", + "TransportSystemState": "", + "VerifySecureSubmitEnabled": false, + "VoicemailJournalingEnabled": true, + "WhenChanged": "/Date(1643184486000)/", + "WhenChangedUTC": "/Date(1643184486000)/", + "WhenCreated": "/Date(1643059670000)/", + "WhenCreatedUTC": "/Date(1643059670000)/", + "Xexch50Enabled": true + } + ], + "Commandlet": [ + "Get-TransportConfig" + ], + "Criticality": "Shall", + "PolicyId": "MS.EXO.5.1v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [ + { + "AdminDisplayName": "", + "Default": true, + "DistinguishedName": "CN=Default Sharing Policy,CN=Federation,CN=Configuration,CN=y2zj1.onmicrosoft.com,CN=ConfigurationUnits,DC=NAMPR10A008,DC=PROD,DC=OUTLOOK,DC=COM", + "Domains": [ + "Anonymous:CalendarSharingFreeBusyReviewer", + "*:CalendarSharingFreeBusySimple" + ], + "Enabled": true, + "ExchangeObjectId": "2f1ca8cf-5ba5-45e3-b73a-1405ff552a2e", + "ExchangeVersion": "0.10 (14.0.100.0)", + "Guid": "2f1ca8cf-5ba5-45e3-b73a-1405ff552a2e", + "Id": "Default Sharing Policy", + "Identity": "Default Sharing Policy", + "IsValid": true, + "Name": "Default Sharing Policy", + "ObjectCategory": "NAMPR10A008.PROD.OUTLOOK.COM/Configuration/Schema/ms-Exch-Sharing-Policy", + "ObjectClass": [ + "top", + "msExchSharingPolicy" + ], + "ObjectState": "Changed", + "OrganizationId": "NAMPR10A008.PROD.OUTLOOK.COM/Microsoft Exchange Hosted Organizations/y2zj1.onmicrosoft.com - NAMPR10A008.PROD.OUTLOOK.COM/ConfigurationUnits/y2zj1.onmicrosoft.com/Configuration", + "OrganizationalUnitRoot": "y2zj1.onmicrosoft.com", + "OriginatingServer": "DM5PR10A08DC002.NAMPR10A008.PROD.OUTLOOK.COM", + "WhenChanged": "/Date(1645650761000)/", + "WhenChangedUTC": "/Date(1645650761000)/", + "WhenCreated": "/Date(1645650752000)/", + "WhenCreatedUTC": "/Date(1645650752000)/" + } + ], + "Commandlet": [ + "Get-SharingPolicy" + ], + "Criticality": "Shall", + "PolicyId": "MS.EXO.6.1v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [ + { + "AdminDisplayName": "", + "Default": true, + "DistinguishedName": "CN=Default Sharing Policy,CN=Federation,CN=Configuration,CN=y2zj1.onmicrosoft.com,CN=ConfigurationUnits,DC=NAMPR10A008,DC=PROD,DC=OUTLOOK,DC=COM", + "Domains": [ + "Anonymous:CalendarSharingFreeBusyReviewer", + "*:CalendarSharingFreeBusySimple" + ], + "Enabled": true, + "ExchangeObjectId": "2f1ca8cf-5ba5-45e3-b73a-1405ff552a2e", + "ExchangeVersion": "0.10 (14.0.100.0)", + "Guid": "2f1ca8cf-5ba5-45e3-b73a-1405ff552a2e", + "Id": "Default Sharing Policy", + "Identity": "Default Sharing Policy", + "IsValid": true, + "Name": "Default Sharing Policy", + "ObjectCategory": "NAMPR10A008.PROD.OUTLOOK.COM/Configuration/Schema/ms-Exch-Sharing-Policy", + "ObjectClass": [ + "top", + "msExchSharingPolicy" + ], + "ObjectState": "Changed", + "OrganizationId": "NAMPR10A008.PROD.OUTLOOK.COM/Microsoft Exchange Hosted Organizations/y2zj1.onmicrosoft.com - NAMPR10A008.PROD.OUTLOOK.COM/ConfigurationUnits/y2zj1.onmicrosoft.com/Configuration", + "OrganizationalUnitRoot": "y2zj1.onmicrosoft.com", + "OriginatingServer": "DM5PR10A08DC002.NAMPR10A008.PROD.OUTLOOK.COM", + "WhenChanged": "/Date(1645650761000)/", + "WhenChangedUTC": "/Date(1645650761000)/", + "WhenCreated": "/Date(1645650752000)/", + "WhenCreatedUTC": "/Date(1645650752000)/" + } + ], + "Commandlet": [ + "Get-SharingPolicy" + ], + "Criticality": "Shall", + "PolicyId": "MS.EXO.6.2v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [ + { + "AdminDisplayName": "", + "DirectoryBasedEdgeBlockMode": "Default", + "DistinguishedName": "CN=Default,CN=Hosted Connection Filter,CN=Transport Settings,CN=Configuration,CN=y2zj1.onmicrosoft.com,CN=ConfigurationUnits,DC=NAMPR10A008,DC=PROD,DC=OUTLOOK,DC=COM", + "EnableSafeList": false, + "ExchangeObjectId": "3843aef3-f3bd-49c1-a674-4d6741ac11b6", + "ExchangeVersion": "0.20 (15.0.0.0)", + "Guid": "3843aef3-f3bd-49c1-a674-4d6741ac11b6", + "IPAllowList": [], + "IPBlockList": [], + "Id": "Default", + "Identity": "Default", + "IsDefault": true, + "IsValid": true, + "Name": "Default", + "ObjectCategory": "NAMPR10A008.PROD.OUTLOOK.COM/Configuration/Schema/ms-Exch-Hosted-Connection-Filter-Policy", + "ObjectClass": [ + "top", + "msExchHostedConnectionFilterPolicy" + ], + "ObjectState": "Unchanged", + "OrganizationId": "NAMPR10A008.PROD.OUTLOOK.COM/Microsoft Exchange Hosted Organizations/y2zj1.onmicrosoft.com - NAMPR10A008.PROD.OUTLOOK.COM/ConfigurationUnits/y2zj1.onmicrosoft.com/Configuration", + "OrganizationalUnitRoot": "y2zj1.onmicrosoft.com", + "OriginatingServer": "DM5PR10A08DC002.NAMPR10A008.PROD.OUTLOOK.COM", + "WhenChanged": "/Date(1645650833000)/", + "WhenChangedUTC": "/Date(1645650833000)/", + "WhenCreated": "/Date(1645650828000)/", + "WhenCreatedUTC": "/Date(1645650828000)/" + } + ], + "Commandlet": [ + "Get-HostedConnectionFilterPolicy" + ], + "Criticality": "Should", + "PolicyId": "MS.EXO.12.1v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [ + { + "AdminDisplayName": "", + "DirectoryBasedEdgeBlockMode": "Default", + "DistinguishedName": "CN=Default,CN=Hosted Connection Filter,CN=Transport Settings,CN=Configuration,CN=y2zj1.onmicrosoft.com,CN=ConfigurationUnits,DC=NAMPR10A008,DC=PROD,DC=OUTLOOK,DC=COM", + "EnableSafeList": false, + "ExchangeObjectId": "3843aef3-f3bd-49c1-a674-4d6741ac11b6", + "ExchangeVersion": "0.20 (15.0.0.0)", + "Guid": "3843aef3-f3bd-49c1-a674-4d6741ac11b6", + "IPAllowList": [], + "IPBlockList": [], + "Id": "Default", + "Identity": "Default", + "IsDefault": true, + "IsValid": true, + "Name": "Default", + "ObjectCategory": "NAMPR10A008.PROD.OUTLOOK.COM/Configuration/Schema/ms-Exch-Hosted-Connection-Filter-Policy", + "ObjectClass": [ + "top", + "msExchHostedConnectionFilterPolicy" + ], + "ObjectState": "Unchanged", + "OrganizationId": "NAMPR10A008.PROD.OUTLOOK.COM/Microsoft Exchange Hosted Organizations/y2zj1.onmicrosoft.com - NAMPR10A008.PROD.OUTLOOK.COM/ConfigurationUnits/y2zj1.onmicrosoft.com/Configuration", + "OrganizationalUnitRoot": "y2zj1.onmicrosoft.com", + "OriginatingServer": "DM5PR10A08DC002.NAMPR10A008.PROD.OUTLOOK.COM", + "WhenChanged": "/Date(1645650833000)/", + "WhenChangedUTC": "/Date(1645650833000)/", + "WhenCreated": "/Date(1645650828000)/", + "WhenCreatedUTC": "/Date(1645650828000)/" + } + ], + "Commandlet": [ + "Get-HostedConnectionFilterPolicy" + ], + "Criticality": "Should", + "PolicyId": "MS.EXO.12.2v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [ + { + "AuditDisabled": false, + "DisplayName": "y2zj1", + "Name": "y2zj1.onmicrosoft.com" + } + ], + "Commandlet": [ + "Get-OrganizationConfig" + ], + "Criticality": "Shall", + "PolicyId": "MS.EXO.13.1v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-ScubaSpfRecords", + "Get-AcceptedDomain" + ], + "Criticality": "Shall", + "PolicyId": "MS.EXO.2.2v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [ + "*" + ], + "Commandlet": [ + "Get-RemoteDomain" + ], + "Criticality": "Shall", + "PolicyId": "MS.EXO.1.1v1", + "ReportDetails": "1 remote domain(s) that allows automatic forwarding: *", + "RequirementMet": false + }, + { + "ActualValue": "PowerShell Error", + "Commandlet": [ + "Get-DlpPolicy" + ], + "Criticality": "Should", + "PolicyId": "MS.POWERPLATFORM.2.2v1", + "ReportDetails": "PowerShell Error", + "RequirementMet": false + }, + { + "ActualValue": "PowerShell Error", + "Commandlet": [ + "Get-PowerAppTenantIsolationPolicy" + ], + "Criticality": "Shall", + "PolicyId": "MS.POWERPLATFORM.3.1v1", + "ReportDetails": "PowerShell Error", + "RequirementMet": false + }, + { + "ActualValue": "PowerShell Error", + "Commandlet": [ + "Get-TenantSettings" + ], + "Control": "Power Platform 2.1", + "Criticality": "Shall", + "ReportDetails": "PowerShell Error", + "Requirement": "The ability to create trial environments SHALL be restricted to admins", + "RequirementMet": false + }, + { + "ActualValue": "PowerShell Error", + "Commandlet": [ + "Get-TenantSettings" + ], + "Criticality": "Shall", + "PolicyId": "MS.POWERPLATFORM.1.1v1", + "ReportDetails": "PowerShell Error", + "RequirementMet": false + }, + { + "ActualValue": "PowerShell error", + "Commandlet": [ + "Get-DlpPolicy" + ], + "Criticality": "Should", + "PolicyId": "MS.POWERPLATFORM.2.3v1", + "ReportDetails": "PowerShell error", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Shall/Not-Implemented", + "PolicyId": "MS.POWERPLATFORM.4.1v1", + "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Should/Not-Implemented", + "PolicyId": "MS.POWERPLATFORM.3.2v1", + "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Should/Not-Implemented", + "PolicyId": "MS.POWERPLATFORM.3.3v1", + "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-DlpPolicy" + ], + "Criticality": "Shall", + "PolicyId": "MS.POWERPLATFORM.2.1v1", + "ReportDetails": "No policy found that applies to default environment", + "RequirementMet": false + }, + { + "ActualValue": 1, + "Commandlet": [ + "Get-SPOTenant", + "Get-PnPTenant" + ], + "Criticality": "Should", + "PolicyId": "MS.SHAREPOINT.1.3v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": 2, + "Commandlet": [ + "Get-SPOSite", + "Get-PnPTenantSite" + ], + "Control": "Sharepoint 2.5", + "Criticality": "Shall", + "ReportDetails": "Requirement met", + "Requirement": "Users SHALL be prevented from running custom scripts on self-service created sites", + "RequirementMet": true + }, + { + "ActualValue": 2, + "Commandlet": [ + "Get-SPOTenant", + "Get-PnPTenant" + ], + "Criticality": "Shall", + "PolicyId": "MS.SHAREPOINT.1.1v1", + "ReportDetails": "Requirement not met", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Control": "Sharepoint 2.5", + "Criticality": "Shall/Not-Implemented", + "PolicyId": "MS.SHAREPOINT.TBD", + "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", + "Requirement": "Users SHALL be prevented from running custom scripts on personal sites (OneDrive)", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Shall/Not-Implemented", + "PolicyId": "MS.SHAREPOINT.1.2v1", + "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Should/Not-Implemented", + "PolicyId": "MS.SHAREPOINT.2.1v1", + "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", + "RequirementMet": false + }, + { + "ActualValue": [ + 1, + true, + 29 + ], + "Commandlet": [ + "Get-SPOTenant", + "Get-PnPTenant" + ], + "Control": "Sharepoint 2.4", + "Criticality": "Should", + "ReportDetails": "Requirement not met: Expiration timer for 'People who use a verification code' NOT set to 30 days", + "Requirement": "Expiration timer for 'People who use a verification code' should be set to 30 days", + "RequirementMet": false + }, + { + "ActualValue": [ + 1, + true, + 31 + ], + "Commandlet": [ + "Get-SPOTenant", + "Get-PnPTenant" + ], + "Criticality": "Should", + "PolicyId": "MS.SHAREPOINT.3.1v1", + "ReportDetails": "Requirement not met: Expiration timer for 'Guest access to a site or OneDrive' NOT set to 30 days", + "RequirementMet": false + }, + { + "ActualValue": true, + "Commandlet": [ + "Get-CsTeamsMeetingPolicy" + ], + "Criticality": "Should", + "PolicyId": "MS.TEAMS.9.1v1", + "ReportDetails": "Requirement not met", + "RequirementMet": false + }, + { + "ActualValue": "AlwaysEnabled", + "Commandlet": [ + "Get-CsTeamsMeetingBroadcastPolicy" + ], + "Criticality": "Should", + "PolicyId": "MS.TEAMS.10.1v1", + "ReportDetails": "Requirement not met", + "RequirementMet": false + }, + { + "ActualValue": "EveryoneInCompany", + "Commandlet": [ + "Get-CsTeamsMeetingPolicy" + ], + "Criticality": "Should", + "PolicyId": "MS.TEAMS.3.2v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Shall/3rd Party", + "PolicyId": "MS.TEAMS.11.1v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Shall/3rd Party", + "PolicyId": "MS.TEAMS.11.4v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Shall/3rd Party", + "PolicyId": "MS.TEAMS.8.3v1", + "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Should/3rd Party", + "PolicyId": "MS.TEAMS.11.2v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Should/3rd Party", + "PolicyId": "MS.TEAMS.12.1v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Should/3rd Party", + "PolicyId": "MS.TEAMS.12.2v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Should/3rd Party", + "PolicyId": "MS.TEAMS.13.1v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Should/3rd Party", + "PolicyId": "MS.TEAMS.13.2v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [], + "Commandlet": [], + "Criticality": "Should/3rd Party", + "PolicyId": "MS.TEAMS.13.3v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [ + "EveryoneInCompany", + false + ], + "Commandlet": [ + "Get-CsTeamsMeetingPolicy" + ], + "Criticality": "Should", + "PolicyId": "MS.TEAMS.3.1v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [ + [], + "MicrosoftCommunicationsOnline/NOAM-ED6-A7" + ], + "Commandlet": [ + "Get-CsTeamsClientConfiguration" + ], + "Criticality": "Shall", + "PolicyId": "MS.TEAMS.7.1v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-CsTeamsAppPermissionPolicy" + ], + "Criticality": "Should", + "PolicyId": "MS.TEAMS.8.1v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-CsTeamsMeetingPolicy" + ], + "Control": "Teams 2.4", + "Criticality": "Should", + "ReportDetails": "Requirement met", + "Requirement": "Anonymous users SHOULD be enabled to join meetings", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-CsTeamsMeetingPolicy" + ], + "Criticality": "Shall", + "PolicyId": "MS.TEAMS.2.1v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-CsTeamsMeetingPolicy" + ], + "Criticality": "Should", + "PolicyId": "MS.TEAMS.1.1v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-CsTeamsMeetingPolicy" + ], + "Criticality": "Should", + "PolicyId": "MS.TEAMS.9.3v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-CsTenantFederationConfiguration" + ], + "Criticality": "Shall", + "PolicyId": "MS.TEAMS.4.1v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [], + "Commandlet": [ + "Get-CsTenantFederationConfiguration" + ], + "Criticality": "Shall", + "PolicyId": "MS.TEAMS.6.1v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [ + "Global" + ], + "Commandlet": [ + "Get-CsTeamsAppPermissionPolicy" + ], + "Criticality": "Should", + "PolicyId": "MS.TEAMS.8.2av1", + "ReportDetails": "1 meeting policy(ies) found that allow custom apps by default: Global", + "RequirementMet": false + }, + { + "ActualValue": [ + "Global" + ], + "Commandlet": [ + "Get-CsTeamsAppPermissionPolicy" + ], + "Criticality": "Should", + "PolicyId": "MS.TEAMS.8.2v1", + "ReportDetails": "1 meeting policy(ies) found that allow third-party apps by default: Global", + "RequirementMet": false + }, + { + "ActualValue": [ + "Global" + ], + "Commandlet": [ + "Get-CsTenantFederationConfiguration" + ], + "Criticality": "Shall", + "PolicyId": "MS.TEAMS.5.1v1", + "ReportDetails": "1 Configuration allowed unmanaged users to initiate contact with internal user across domains: Global", + "RequirementMet": false + }, + { + "ActualValue": [ + "Global" + ], + "Commandlet": [ + "Get-CsTenantFederationConfiguration" + ], + "Criticality": "Should", + "PolicyId": "MS.TEAMS.5.2v1", + "ReportDetails": "1 Internal users are enabled to initiate contact with unmanaged users across domains: Global", + "RequirementMet": false + } ] \ No newline at end of file diff --git a/Testing/Unit/PowerShell/CreateReport/Import-SecureBaseline.Tests.ps1 b/Testing/Unit/PowerShell/CreateReport/Import-SecureBaseline.Tests.ps1 index 73414e4ce7..d425047ab1 100644 --- a/Testing/Unit/PowerShell/CreateReport/Import-SecureBaseline.Tests.ps1 +++ b/Testing/Unit/PowerShell/CreateReport/Import-SecureBaseline.Tests.ps1 @@ -39,7 +39,7 @@ InModuleScope CreateReport { @{Product = "onedrive"; GroupCount = 7; PolicyCount = 8} @{Product = "powerbi"; GroupCount = 10; PolicyCount = 12} @{Product = "powerplatform"; GroupCount = 4; PolicyCount = 8} - @{Product = "sharepoint"; GroupCount = 5; PolicyCount = 6} + @{Product = "sharepoint"; GroupCount = 5; PolicyCount = 10} @{Product = "teams"; GroupCount = 13; PolicyCount = 28} ){ {$Baselines.$Product} | Should -Not -Throw diff --git a/Testing/Unit/PowerShell/CreateReport/New-Report.Tests.ps1 b/Testing/Unit/PowerShell/CreateReport/New-Report.Tests.ps1 index b39fd24f98..64758d5a28 100644 --- a/Testing/Unit/PowerShell/CreateReport/New-Report.Tests.ps1 +++ b/Testing/Unit/PowerShell/CreateReport/New-Report.Tests.ps1 @@ -46,7 +46,7 @@ InModuleScope CreateReport { @{Product = 'exo'; ErrorCount = 2}, @{Product = 'onedrive'; ErrorCount = 8}, @{Product = 'powerplatform'; ErrorCount = 0}, - @{Product = 'sharepoint'; ErrorCount = 3}, + @{Product = 'sharepoint'; ErrorCount = 5}, @{Product = 'teams'; ErrorCount = 5} ){ $CreateReportParams += @{ diff --git a/Testing/Unit/Rego/Sharepoint/SharepointConfig_01_test.rego b/Testing/Unit/Rego/Sharepoint/SharepointConfig_01_test.rego index ba1b014859..41fca58d22 100644 --- a/Testing/Unit/Rego/Sharepoint/SharepointConfig_01_test.rego +++ b/Testing/Unit/Rego/Sharepoint/SharepointConfig_01_test.rego @@ -1,17 +1,18 @@ package sharepoint import future.keywords +import data.report.utils.NotCheckedDetails # -# Policy 1 +# MS.SHAREPOINT.1.1v1 #-- -test_DefaultSharingLinkType_Correct if { +test_SharingCapability_Correct_V1 if { PolicyId := "MS.SHAREPOINT.1.1v1" Output := tests with input as { "SPO_tenant": [ { - "DefaultSharingLinkType" : 1 + "SharingCapability" : 0 } ] } @@ -23,13 +24,145 @@ test_DefaultSharingLinkType_Correct if { RuleOutput[0].ReportDetails == "Requirement met" } -test_DefaultSharingLinkType_Incorrect if { +test_SharingCapability_Correct_V2 if { PolicyId := "MS.SHAREPOINT.1.1v1" Output := tests with input as { "SPO_tenant": [ { - "DefaultSharingLinkType" : 2 + "SharingCapability" : 3 + } + ] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "Requirement met" +} + +test_SharingCapability_Incorrect_V1 if { + PolicyId := "MS.SHAREPOINT.1.1v1" + + Output := tests with input as { + "SPO_tenant": [ + { + "SharingCapability" : 1 + } + ] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "Requirement not met" +} + +test_SharingCapability_Incorrect_V2 if { + PolicyId := "MS.SHAREPOINT.1.1v1" + + Output := tests with input as { + "SPO_tenant": [ + { + "SharingCapability" : 2 + } + ] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "Requirement not met" +} +#-- + +# +# MS.SHAREPOINT.1.2v1 +#-- +test_SharingDomainRestrictionMode_Correct if { + PolicyId := "MS.SHAREPOINT.1.2v1" + + Output := tests with input as { + "SPO_tenant": [ + { + "SharingDomainRestrictionMode" : 1 + } + ] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "Requirement met" +} + +test_SharingDomainRestrictionMode_Incorrect if { + PolicyId := "MS.SHAREPOINT.1.2v1" + + Output := tests with input as { + "SPO_tenant": [ + { + "SharingDomainRestrictionMode" : 0 + } + ] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "Requirement not met" +} +#-- + +# +# MS.SHAREPOINT.1.3v1 +#-- +test_NotImplemented_Correct if { + PolicyId := "MS.SHAREPOINT.1.3v1" + + Output := tests with input as { } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == NotCheckedDetails(PolicyId) +} +#-- + +# +# MS.SHAREPOINT.1.4v1 +#-- +test_RequireAcceptingAccountMatchInvitedAccount_Correct if { + PolicyId := "MS.SHAREPOINT.1.4v1" + + Output := tests with input as { + "SPO_tenant": [ + { + "RequireAcceptingAccountMatchInvitedAccount" : true + } + ] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "Requirement met" +} + +test_RequireAcceptingAccountMatchInvitedAccount_Incorrect if { + PolicyId := "MS.SHAREPOINT.1.4v1" + + Output := tests with input as { + "SPO_tenant": [ + { + "RequireAcceptingAccountMatchInvitedAccount" : false } ] } @@ -40,3 +173,4 @@ test_DefaultSharingLinkType_Incorrect if { not RuleOutput[0].RequirementMet RuleOutput[0].ReportDetails == "Requirement not met" } +#-- \ No newline at end of file diff --git a/Testing/Unit/Rego/Sharepoint/SharepointConfig_02_test.rego b/Testing/Unit/Rego/Sharepoint/SharepointConfig_02_test.rego index 1953086f7d..2529ee0a43 100644 --- a/Testing/Unit/Rego/Sharepoint/SharepointConfig_02_test.rego +++ b/Testing/Unit/Rego/Sharepoint/SharepointConfig_02_test.rego @@ -3,33 +3,15 @@ import future.keywords # -# Policy 1 +# MS.SHAREPOINT.2.1v1 #-- -test_SharingCapability_Correct_V1 if { - PolicyId := "MS.SHAREPOINT.1.3v1" - - Output := tests with input as { - "SPO_tenant": [ - { - "SharingCapability" : 1 - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_SharingCapability_Correct_V2 if { - PolicyId := "MS.SHAREPOINT.1.3v1" +test_DefaultSharingLinkType_Correct if { + PolicyId := "MS.SHAREPOINT.2.1v1" Output := tests with input as { "SPO_tenant": [ { - "SharingCapability" : 0 + "DefaultSharingLinkType" : 1 } ] } @@ -41,13 +23,13 @@ test_SharingCapability_Correct_V2 if { RuleOutput[0].ReportDetails == "Requirement met" } -test_SharingCapability_Incorrect if { - PolicyId := "MS.SHAREPOINT.1.3v1" +test_DefaultSharingLinkType_Incorrect if { + PolicyId := "MS.SHAREPOINT.2.1v1" Output := tests with input as { "SPO_tenant": [ { - "SharingCapability" : 2 + "DefaultSharingLinkType" : 2 } ] } @@ -57,4 +39,5 @@ test_SharingCapability_Incorrect if { count(RuleOutput) == 1 not RuleOutput[0].RequirementMet RuleOutput[0].ReportDetails == "Requirement not met" -} \ No newline at end of file +} +#-- \ No newline at end of file diff --git a/Testing/Unit/Rego/Sharepoint/SharepointConfig_03_test.rego b/Testing/Unit/Rego/Sharepoint/SharepointConfig_03_test.rego index c63204f413..04820f45cb 100644 --- a/Testing/Unit/Rego/Sharepoint/SharepointConfig_03_test.rego +++ b/Testing/Unit/Rego/Sharepoint/SharepointConfig_03_test.rego @@ -2,12 +2,13 @@ package sharepoint import future.keywords import data.report.utils.NotCheckedDetails + # -# Policy 1 +# MS.SHAREPOINT.3.1v1 #-- test_NotImplemented_Correct if { - PolicyId := "MS.SHAREPOINT.2.1v1" - + PolicyId := "MS.SHAREPOINT.3.1v1" + Output := tests with input as { } RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] @@ -15,4 +16,5 @@ test_NotImplemented_Correct if { count(RuleOutput) == 1 not RuleOutput[0].RequirementMet RuleOutput[0].ReportDetails == NotCheckedDetails(PolicyId) -} \ No newline at end of file +} +#-- \ No newline at end of file diff --git a/Testing/Unit/Rego/Sharepoint/SharepointConfig_04_test.rego b/Testing/Unit/Rego/Sharepoint/SharepointConfig_04_test.rego index 89406e7263..2c83c359b6 100644 --- a/Testing/Unit/Rego/Sharepoint/SharepointConfig_04_test.rego +++ b/Testing/Unit/Rego/Sharepoint/SharepointConfig_04_test.rego @@ -3,17 +3,17 @@ import future.keywords # -# Policy 1 +# MS.SHAREPOINT.4.1v1 #-- test_SharingCapability_Correct_V1 if { - PolicyId := "MS.SHAREPOINT.3.1v1" + PolicyId := "MS.SHAREPOINT.4.1v1" Output := tests with input as { "SPO_tenant": [ { "SharingCapability" : 0, "ExternalUserExpirationRequired" : true, - "ExternalUserExpireInDays" : 30 + "ExternalUserExpireInDays": 30 } ] } @@ -26,74 +26,14 @@ test_SharingCapability_Correct_V1 if { } test_SharingCapability_Correct_V2 if { - PolicyId := "MS.SHAREPOINT.3.1v1" + PolicyId := "MS.SHAREPOINT.4.1v1" Output := tests with input as { "SPO_tenant": [ { - "SharingCapability" : 0, - "ExternalUserExpirationRequired" : false, - "ExternalUserExpireInDays" : 30 - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_SharingCapability_Correct_V3 if { - PolicyId := "MS.SHAREPOINT.3.1v1" - - Output := tests with input as { - "SPO_tenant": [ - { - "SharingCapability" : 0, - "ExternalUserExpirationRequired" : true, - "ExternalUserExpireInDays" : 29 - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_SharingCapability_Correct_V4 if { - PolicyId := "MS.SHAREPOINT.3.1v1" - - Output := tests with input as { - "SPO_tenant": [ - { - "SharingCapability" : 0, + "SharingCapability" : 1, "ExternalUserExpirationRequired" : true, - "ExternalUserExpireInDays" : 31 - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_SharingCapability_Correct_V5 if { - PolicyId := "MS.SHAREPOINT.3.1v1" - - Output := tests with input as { - "SPO_tenant": [ - { - "SharingCapability" : 0, - "ExternalUserExpirationRequired" : false, - "ExternalUserExpireInDays" : 29 + "ExternalUserExpireInDays": 30 } ] } @@ -105,35 +45,15 @@ test_SharingCapability_Correct_V5 if { RuleOutput[0].ReportDetails == "Requirement met" } -test_SharingCapability_Correct_V6 if { - PolicyId := "MS.SHAREPOINT.3.1v1" - - Output := tests with input as { - "SPO_tenant": [ - { - "SharingCapability" : 0, - "ExternalUserExpirationRequired" : false, - "ExternalUserExpireInDays" : 31 - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_Multi_Correct if { - PolicyId := "MS.SHAREPOINT.3.1v1" +test_ExternalUserExpireInDays_Correct if { + PolicyId := "MS.SHAREPOINT.4.1v1" Output := tests with input as { "SPO_tenant": [ { "SharingCapability" : 1, "ExternalUserExpirationRequired" : true, - "ExternalUserExpireInDays" : 30 + "ExternalUserExpireInDays": 29 } ] } @@ -145,15 +65,15 @@ test_Multi_Correct if { RuleOutput[0].ReportDetails == "Requirement met" } -test_ExternalUserExpirationRequired_Incorrect if { - PolicyId := "MS.SHAREPOINT.3.1v1" +test_Multi_Incorrect_V1 if { + PolicyId := "MS.SHAREPOINT.4.1v1" Output := tests with input as { "SPO_tenant": [ { "SharingCapability" : 1, "ExternalUserExpirationRequired" : false, - "ExternalUserExpireInDays" : 30 + "ExternalUserExpireInDays": 31 } ] } @@ -162,58 +82,18 @@ test_ExternalUserExpirationRequired_Incorrect if { count(RuleOutput) == 1 not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement not met: Expiration timer for 'Guest access to a site or OneDrive' NOT enabled" + RuleOutput[0].ReportDetails == "Requirement not met: Expiration timer for 'Guest access to a site or OneDrive' NOT enabled and set to greater 30 days" } -test_ExternalUserExpireInDays_Incorrect_V1 if { - PolicyId := "MS.SHAREPOINT.3.1v1" - - Output := tests with input as { - "SPO_tenant": [ - { - "SharingCapability" : 1, - "ExternalUserExpirationRequired" : true, - "ExternalUserExpireInDays" : 29 - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement not met: Expiration timer for 'Guest access to a site or OneDrive' NOT set to 30 days" -} - -test_ExternalUserExpireInDays_Incorrect_V2 if { - PolicyId := "MS.SHAREPOINT.3.1v1" - - Output := tests with input as { - "SPO_tenant": [ - { - "SharingCapability" : 1, - "ExternalUserExpirationRequired" : true, - "ExternalUserExpireInDays" : 31 - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement not met: Expiration timer for 'Guest access to a site or OneDrive' NOT set to 30 days" -} - -test_Multi_Incorrect_V1 if { - PolicyId := "MS.SHAREPOINT.3.1v1" +test_ExternalUserExpirationRequired_Incorrect_V2 if { + PolicyId := "MS.SHAREPOINT.4.1v1" Output := tests with input as { "SPO_tenant": [ { "SharingCapability" : 1, "ExternalUserExpirationRequired" : false, - "ExternalUserExpireInDays" : 29 + "ExternalUserExpireInDays": 29 } ] } @@ -222,18 +102,18 @@ test_Multi_Incorrect_V1 if { count(RuleOutput) == 1 not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement not met" + RuleOutput[0].ReportDetails == "Requirement not met: Expiration timer for 'Guest access to a site or OneDrive' NOT enabled" } -test_Multi_Incorrect_V2 if { - PolicyId := "MS.SHAREPOINT.3.1v1" +test_ExternalUserExpireInDays_Incorrect_V3 if { + PolicyId := "MS.SHAREPOINT.4.1v1" Output := tests with input as { "SPO_tenant": [ { "SharingCapability" : 1, - "ExternalUserExpirationRequired" : false, - "ExternalUserExpireInDays" : 31 + "ExternalUserExpirationRequired" : true, + "ExternalUserExpireInDays": 31 } ] } @@ -242,69 +122,27 @@ test_Multi_Incorrect_V2 if { count(RuleOutput) == 1 not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement not met" + RuleOutput[0].ReportDetails == "Requirement not met: Expiration timer for 'Guest access to a site or OneDrive' NOT set to 30 days or less" } +#-- # -# Policy 2 +# MS.SHAREPOINT.4.2v1 #-- -test_SharingCapability_Correct_V1 if { - ControlNumber := "Sharepoint 2.4" - Requirement := "Expiration timer for 'People who use a verification code' should be set to 30 days" - - Output := tests with input as { - "SPO_tenant": [ - { - "SharingCapability" : 0, - "EmailAttestationRequired" : true, - "EmailAttestationReAuthDays" : 30 - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_SharingCapability_Correct_V2 if { - ControlNumber := "Sharepoint 2.4" - Requirement := "Expiration timer for 'People who use a verification code' should be set to 30 days" - - Output := tests with input as { - "SPO_tenant": [ - { - "SharingCapability" : 0, - "EmailAttestationRequired" : false, - "EmailAttestationReAuthDays" : 30 - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - test_SharingCapability_Correct_V3 if { - ControlNumber := "Sharepoint 2.4" - Requirement := "Expiration timer for 'People who use a verification code' should be set to 30 days" + PolicyId := "MS.SHAREPOINT.4.2v1" Output := tests with input as { "SPO_tenant": [ { "SharingCapability" : 0, "EmailAttestationRequired" : true, - "EmailAttestationReAuthDays" : 29 + "EmailAttestationReAuthDays": 30 } ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -312,190 +150,102 @@ test_SharingCapability_Correct_V3 if { } test_SharingCapability_Correct_V4 if { - ControlNumber := "Sharepoint 2.4" - Requirement := "Expiration timer for 'People who use a verification code' should be set to 30 days" + PolicyId := "MS.SHAREPOINT.4.2v1" Output := tests with input as { "SPO_tenant": [ { - "SharingCapability" : 0, + "SharingCapability" : 1, "EmailAttestationRequired" : true, - "EmailAttestationReAuthDays" : 31 - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_SharingCapability_Correct_V5 if { - ControlNumber := "Sharepoint 2.4" - Requirement := "Expiration timer for 'People who use a verification code' should be set to 30 days" - - Output := tests with input as { - "SPO_tenant": [ - { - "SharingCapability" : 0, - "EmailAttestationRequired" : false, - "EmailAttestationReAuthDays" : 29 - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_SharingCapability_Correct_V6 if { - ControlNumber := "Sharepoint 2.4" - Requirement := "Expiration timer for 'People who use a verification code' should be set to 30 days" - - Output := tests with input as { - "SPO_tenant": [ - { - "SharingCapability" : 0, - "EmailAttestationRequired" : false, - "EmailAttestationReAuthDays" : 31 + "EmailAttestationReAuthDays": 30 } ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet RuleOutput[0].ReportDetails == "Requirement met" } -test_Multi_Correct if { - ControlNumber := "Sharepoint 2.4" - Requirement := "Expiration timer for 'People who use a verification code' should be set to 30 days" +test_EmailAttestationReAuthDays_Correct if { + PolicyId := "MS.SHAREPOINT.4.2v1" Output := tests with input as { "SPO_tenant": [ { "SharingCapability" : 1, "EmailAttestationRequired" : true, - "EmailAttestationReAuthDays" : 30 + "EmailAttestationReAuthDays": 29 } ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet RuleOutput[0].ReportDetails == "Requirement met" } -test_EmailAttestationRequired_Incorrect if { - ControlNumber := "Sharepoint 2.4" - Requirement := "Expiration timer for 'People who use a verification code' should be set to 30 days" +test_Multi_Incorrect_V1 if { + PolicyId := "MS.SHAREPOINT.4.2v1" Output := tests with input as { "SPO_tenant": [ { "SharingCapability" : 1, "EmailAttestationRequired" : false, - "EmailAttestationReAuthDays" : 30 + "EmailAttestationReAuthDays": 31 } ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement not met: Expiration timer for 'People who use a verification code' NOT enabled" + RuleOutput[0].ReportDetails == "Requirement not met: Expiration timer for 'People who use a verification code' NOT enabled and set to greater 30 days" } -test_EmailAttestationReAuthDays_Incorrect_V1 if { - ControlNumber := "Sharepoint 2.4" - Requirement := "Expiration timer for 'People who use a verification code' should be set to 30 days" +test_EmailAttestationRequired_Incorrect_V2 if { + PolicyId := "MS.SHAREPOINT.4.2v1" Output := tests with input as { "SPO_tenant": [ { "SharingCapability" : 1, - "EmailAttestationRequired" : true, - "EmailAttestationReAuthDays" : 29 + "EmailAttestationRequired" : false, + "EmailAttestationReAuthDays": 29 } ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement not met: Expiration timer for 'People who use a verification code' NOT set to 30 days" + RuleOutput[0].ReportDetails == "Requirement not met: Expiration timer for 'People who use a verification code' NOT enabled" } -test_EmailAttestationReAuthDays_Incorrect_V2 if { - ControlNumber := "Sharepoint 2.4" - Requirement := "Expiration timer for 'People who use a verification code' should be set to 30 days" +test_EmailAttestationReAuthDays_Incorrect_V3 if { + PolicyId := "MS.SHAREPOINT.4.2v1" Output := tests with input as { "SPO_tenant": [ { "SharingCapability" : 1, "EmailAttestationRequired" : true, - "EmailAttestationReAuthDays" : 31 + "EmailAttestationReAuthDays": 31 } ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet RuleOutput[0].ReportDetails == "Requirement not met: Expiration timer for 'People who use a verification code' NOT set to 30 days" } - -test_Multi_Incorrect_V1 if { - ControlNumber := "Sharepoint 2.4" - Requirement := "Expiration timer for 'People who use a verification code' should be set to 30 days" - - Output := tests with input as { - "SPO_tenant": [ - { - "SharingCapability" : 1, - "EmailAttestationRequired" : false, - "EmailAttestationReAuthDays" : 29 - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement not met" -} - -test_Multi_Incorrect_V2 if { - ControlNumber := "Sharepoint 2.4" - Requirement := "Expiration timer for 'People who use a verification code' should be set to 30 days" - - Output := tests with input as { - "SPO_tenant": [ - { - "SharingCapability" : 1, - "EmailAttestationRequired" : false, - "EmailAttestationReAuthDays" : 31 - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement not met" -} \ No newline at end of file +#-- \ No newline at end of file diff --git a/Testing/Unit/Rego/Sharepoint/SharepointConfig_05_test.rego b/Testing/Unit/Rego/Sharepoint/SharepointConfig_05_test.rego index 450c50cdf9..1b0fa9e478 100644 --- a/Testing/Unit/Rego/Sharepoint/SharepointConfig_05_test.rego +++ b/Testing/Unit/Rego/Sharepoint/SharepointConfig_05_test.rego @@ -2,39 +2,38 @@ package sharepoint import future.keywords import data.report.utils.NotCheckedDetails + # -# Policy 1 +# MS.SHAREPOINT.5.1v1 #-- test_NotImplemented_Correct if { - ControlNumber := "Sharepoint 2.5" - PolicyId := "MS.SHAREPOINT.TBD" - Requirement := "Users SHALL be prevented from running custom scripts on personal sites (OneDrive)" + PolicyId := "MS.SHAREPOINT.5.1v1" Output := tests with input as { } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet RuleOutput[0].ReportDetails == NotCheckedDetails(PolicyId) } +#-- # -# Policy 2 +# MS.SHAREPOINT.5.2v1 #-- test_DenyAddAndCustomizePages_Correct if { - ControlNumber := "Sharepoint 2.5" - Requirement := "Users SHALL be prevented from running custom scripts on self-service created sites" + PolicyId := "MS.SHAREPOINT.5.2v1" Output := tests with input as { "SPO_site": [ { "DenyAddAndCustomizePages" : 2 } - ] + ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 RuleOutput[0].RequirementMet @@ -42,8 +41,7 @@ test_DenyAddAndCustomizePages_Correct if { } test_DenyAddAndCustomizePages_Incorrect if { - ControlNumber := "Sharepoint 2.5" - Requirement := "Users SHALL be prevented from running custom scripts on self-service created sites" + PolicyId := "MS.SHAREPOINT.5.2v1" Output := tests with input as { "SPO_site": [ @@ -53,9 +51,10 @@ test_DenyAddAndCustomizePages_Incorrect if { ] } - RuleOutput := [Result | Result = Output[_]; Result.Control == ControlNumber; Result.Requirement == Requirement] + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet RuleOutput[0].ReportDetails == "Requirement not met" } +#-- \ No newline at end of file diff --git a/baselines/sharepoint.md b/baselines/sharepoint.md index b153f02bc2..aebd9431ab 100644 --- a/baselines/sharepoint.md +++ b/baselines/sharepoint.md @@ -66,39 +66,7 @@ listed. # Baselines -## 1. File and Folder Links Default Sharing Settings - -This policy ensures that when sharing files in SharePoint, there are -several possible scopes, including agency-wide or “anyone with the -link.” - -### Policies - -#### MS.SHAREPOINT.1.1v1 -File and folder links default sharing setting SHALL be set to Specific People (Only the People the User Specifies). -- _Rationale:_ TODO -- _Last modified:_ June 2023 - -### Resources - -- [File and folder links \| Microsoft - Documents](https://docs.microsoft.com/en-us/sharepoint/turn-external-sharing-on-or-off#file-and-folder-links) - -### License Requirements - -- N/A - -### Implementation - -In the **SharePoint admin** **center**: - -1. In the left-hand navigation bar, click **Policies** -\> **Sharing** - to display sharing settings. - -2. Under **File and folder links**, ensure that the default link type - is set to **Specific people (only the people the user specifies)**. - -## 2. External Sharing +## 1. External Sharing SharePoint allows sharing with users who are outside the agency, which is convenient but may pose a data loss or other information security @@ -109,7 +77,7 @@ groups per interagency collaboration needs. for OneDrive and Teams to the same, selected level. OneDrive and Teams can be less permissive (not more permissive) than SharePoint Online. -Adding approved domains and/or security groups will also be reflected in +Adding approved domains and security groups will also be reflected in OneDrive external sharing settings. External access may be granted on a per-domain basis. This may be @@ -119,8 +87,24 @@ Program](https://community.max.gov/display/Egov/Interagency+Collaboration+Progra OMB Max Site for a list of .gov domains for sharing). ### Policies -#### MS.SHAREPOINT.2.1v1 -External sharing SHOULD be limited to approved domains and security groups per interagency collaboration needs. +#### MS.SHAREPOINT.1.1v1 +External sharing SHOULD be limited to Existing Guests or the more restrictive setting, Only People in your Organization. +- _Rationale:_ TODO +- _Last modified:_ June 2023 +- _Note:_ Same implementation in MS.ONEDRIVE.1.1v1 + +#### MS.SHAREPOINT.1.2v1 +External sharing SHOULD be limited to approved domains per interagency collaboration needs. +- _Rationale:_ TODO +- _Last modified:_ June 2023 + +#### MS.SHAREPOINT.1.3v1 +External sharing SHOULD be limited to approved security groups per interagency collaboration needs. +- _Rationale:_ TODO +- _Last modified:_ June 2023 + +#### MS.SHAREPOINT.1.4v1 +Guest access SHOULD be limited to the email the invitation was sent. - _Rationale:_ TODO - _Last modified:_ June 2023 @@ -133,39 +117,96 @@ External sharing SHOULD be limited to approved domains and security groups per i - N/A -### Implementation +### Implementation + +MS.SHAREPOINT.1.1v1, in the **SharePoint admin center**: + +1. Select **Policies** -\> **Sharing** + +2. Adjust external sharing slider to **Existing Guests** or **Only people in your organization** + +3. Select **Save** + +MS.SHAREPOINT.1.2v1, in the **SharePoint admin center**: + +1. Select **Policies** -\> **Sharing** + +2. Expand **More external sharing settings** + +3. Select **Limit external sharing by domain** + +4. Select **Add domains** + +5. Add approved external domains + +6. Select **Save** -To adjust sharing settings, in the **SharePoint admin center**: +MS.SHAREPOINT.1.3v1, in the **SharePoint admin center**: -1. Select **Policies** -\> **Sharing**. +1. Select **Policies** -\> **Sharing** -2. Adjust external sharing slider to **New and Existing Guests.** +2. Expand **More external sharing settings** -3. Expand **More external sharing settings.** +3. Select **Allow only users in specific security groups to share + externally** -4. Select **Limit external sharing by domain**. +4. Select **Manage security groups** -5. Select **Add domains.** +5. Add approved security groups -6. Add domains. +6. Select **Save** -7. Select **Save.** +MS.SHAREPOINT.1.4v1, in the **SharePoint admin center**: -8. Select **Allow only users in specific security groups to share - externally**. +1. Select **Policies** -\> **Sharing** -9. Select **Manage security groups.** +2. Expand **More external sharing settings** -10. Add security groups. +3. Select **Guests must sign in using the same account to which sharing invitations are sent** -11. Select **Save.** +4. Select **Save** -## 3. Sensitivity Levels +## 2. File and Folder Links Default Sharing Settings + +This policy ensures that when sharing files in SharePoint, there are +several possible scopes, including agency-wide or “anyone with the +link.” + +### Policies + +#### MS.SHAREPOINT.2.1v1 +File and folder links default sharing setting SHALL be set to Specific People (only the people the user specifies). +- _Rationale:_ TODO +- _Last modified:_ June 2023 +_Note:_ Similar implementation in MS.ONEDRIVE.3.1v1 + +### Resources + +- [File and folder links \| Microsoft + Documents](https://docs.microsoft.com/en-us/sharepoint/turn-external-sharing-on-or-off#file-and-folder-links) + +### License Requirements + +- N/A + +### Implementation + +MS.SHAREPOINT.2.1v1, in the **SharePoint admin center**: + +1. In the left-hand navigation bar, click **Policies** -\> **Sharing** + to display sharing settings + +2. Under **File and folder links**, ensure that the default link type + is set to **Specific people (only the people the user specifies)** + +3. Select **Save** + +## 3. Sensitivity Levels SharePoint allows sharing with users who are outside the agency, which is convenient but may pose a data loss or other information security -risk. This working group recommends outside of the default -organizational settings agencies should evaluate each created site and +risk. This baseline policy recommends, outside of the default +organizational settings, agencies evaluate each created site and adjust sharing settings best aligned to their respective sensitivity level. @@ -184,26 +225,24 @@ Sharing settings for specific SharePoint sites SHOULD align to their sensitivity - N/A -### Implementation - -To limit external sharing by domain, in the **SharePoint admin center**: +### Implementation -1. Select **Sites.** +MS.SHAREPOINT.3.1v1, in the **SharePoint admin center**: -2. Select **Active sites.** +1. Select **Sites** -3. Select **Site name.** +2. Select **Active sites** -4. Select **Add domains.** +3. Select **Site name** -5. Select **Policies.** +4. Select **Settings** -6. Under **external sharing**, select **Edit**. +5. Select **More sharing settings** -7. Select permissions aligning to the risk posture associated with the - sensitivity of the SharePoint site. +6. Select permissions aligning to the risk posture associated with the + sensitivity of the SharePoint site -8. Select **Save.** +7. Select **Save** ## 4. Guest Access to a Site or OneDrive @@ -217,12 +256,12 @@ for OneDrive and Teams to the same, specified expiration times. ### Policies #### MS.SHAREPOINT.4.1v1 -Expiration timers for guest access to a site or OneDrive and people who use a verification code SHOULD be set. +Expiration timers for guest access to a site or OneDrive SHOULD be set to 30 days or less. - _Rationale:_ TODO - _Last modified:_ June 2023 #### MS.SHAREPOINT.4.2v1 -Expiration timers SHOULD be set to 30 days. +Expiration timers for people who use a verification code SHOULD be set to 30 days or less. - _Rationale:_ TODO - _Last modified:_ June 2023 @@ -234,34 +273,53 @@ Expiration timers SHOULD be set to 30 days. - [Managing SharePoint Online Security: A Team Effort \| Microsoft Build](https://docs.microsoft.com/en-us/microsoft-365/community/sharepoint-security-a-team-effort) +- [Secure external sharing recipient experience \| Microsoft + Build](https://learn.microsoft.com/en-us/sharepoint/what-s-new-in-sharing-in-targeted-release) -### Implementation +### Implementation -To limit external sharing by domain, in the **SharePoint admin center**: +MS.SHAREPOINT.4.1v1, in the **SharePoint admin center**: -1. Select **Policies** -\> **Sharing**. +1. Select **Policies** -\> **Sharing** -2. Expand **More external sharing settings.** +2. Expand **More external sharing settings** 3. Select **Guest access to a site or OneDrive will expire - automatically after this many days.** + automatically after this many days** -4. Enter “30” days. +4. Enter “30” days or less -5. Select **People who use a verification code must reauthenticate - after this many days**. +5. Select **Save** -6. Enter “30 days”. +MS.SHAREPOINT.4.2v1, in the **SharePoint admin center**: + +1. Select **Policies** -\> **Sharing** + +2. Expand **More external sharing settings** + +3. Select **People who use a verification code must reauthenticate + after this many days** + +4. Enter “30 days” or less + +5. Select **Save** ## 5. Custom Scripts Allowing users to run custom scripts can potentially allow malicious -scripts to run in a trusted environment. For this reason, running custom -scripts should not be allowed. +scripts to run in a trusted environment. Microsoft provides settings to +mitigate this risk by preventing users from running custom scripts. ### Policy #### MS.SHAREPOINT.5.1v1 -Users SHALL be prevented from running custom scripts. +Users SHALL be prevented from running custom scripts on personal sites. +- _Rationale:_ TODO +- _Last modified:_ June 2023 + +#### MS.SHAREPOINT.5.2v1 +Users SHALL be prevented from running custom scripts on self-service created sites. +- _Rationale:_ TODO +- _Last modified:_ June 2023 ### Resources @@ -274,15 +332,30 @@ Users SHALL be prevented from running custom scripts. ### Implementation -In the **SharePoint Classic admin center**: +MS.SHAREPOINT.5.1v1, in the **SharePoint admin center**: + +1. Select **Settings** + +2. Scroll down to select **classic settings page** + +3. Scroll to the **Custom Script** setting + +4. Select **Prevent users from running custom script on personal sites** + +5. Select **Ok** + +MS.SHAREPOINT.5.1v1, in the **SharePoint admin center**: + +1. Select **Settings** + +2. Scroll down to select **classic settings page** -1. Scroll to the **Custom Script** setting and select both of the - following: +3. Scroll to the **Custom Script** setting -2. **Prevent users from running custom script on personal sites.** +4. Select **Prevent users from running custom script on self-service created + sites** -3. **Prevent users from running custom script on self-service created - sites.** +5. Select **Ok** # Acknowledgements @@ -333,4 +406,4 @@ Matthew Snitchler (Sandia), Darryl Purdy (USCB), Brandon Frankens Dr. Mukesh Rohatgi (MITRE), Lee Szilagyi (MITRE), Nanda Katikaneni (MITRE), Ted Kolovos (MITRE), Thomas Comeau (MITRE), Karen Caraway (MITRE), Jackie Whieldon (MITRE), Jeanne Firey (MITRE), Kenneth Myers -(General Services Administration). +(General Services Administration). \ No newline at end of file From f7a6e75e8f43034a015a49c1acd982643c408b59 Mon Sep 17 00:00:00 2001 From: Addam Schroll <108814318+schrolla@users.noreply.github.com> Date: Thu, 8 Jun 2023 10:36:43 -0500 Subject: [PATCH 06/33] Fix test location file path (#367) --- .github/workflows/run_markdown_check.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/run_markdown_check.yaml b/.github/workflows/run_markdown_check.yaml index 2870b90b11..f18cf5d5ec 100644 --- a/.github/workflows/run_markdown_check.yaml +++ b/.github/workflows/run_markdown_check.yaml @@ -29,4 +29,4 @@ jobs: - name: Execute markdown checks run: | $PSVersionTable - Invoke-Pester Testing\Unit\Pester\CreateReport -Output Detailed \ No newline at end of file + Invoke-Pester Testing\Unit\PowerShell\CreateReport -Output Detailed \ No newline at end of file From 5ad473bab79cd034fc9e450d9b7dfed0688d2146 Mon Sep 17 00:00:00 2001 From: Richard Crutchfield Date: Tue, 13 Jun 2023 15:31:15 -0400 Subject: [PATCH 07/33] Enhanced smoke test - check for missing results (#356) * Structural baseline updates (cleaned up) (#334) * Update aad.md all updates * Update defender.md all updates * Update exchange.md all updates * Rename exchange.md to exo.md * Update onedrive.md * Update powerbi.md all updates * Update powerplatform.md all updates * Update sharepoint.md all updates * Update teams.md all updates * Update baselines/defender.md good catch! Co-authored-by: Addam Schroll <108814318+schrolla@users.noreply.github.com> * Update baselines/powerbi.md Co-authored-by: Addam Schroll <108814318+schrolla@users.noreply.github.com> * Update baselines/powerbi.md Co-authored-by: Addam Schroll <108814318+schrolla@users.noreply.github.com> * Update baselines/aad.md Co-authored-by: Addam Schroll <108814318+schrolla@users.noreply.github.com> * Update aad.md referenced old policy number * Update powerbi.md --------- Co-authored-by: Addam Schroll <108814318+schrolla@users.noreply.github.com> * Initial drop of secure baseline automation (#336) * initial teams drop * Add markdown check * Fix spelling * Check action * Test Action * Check version * Fix Markdown test * Add path *.md * Update anchor func * Update AAD * WIP * WIP * WIP * WIP * WIP * Structural baseline updates (cleaned up) (#334) * Update aad.md all updates * Update defender.md all updates * Update exchange.md all updates * Rename exchange.md to exo.md * Update onedrive.md * Update powerbi.md all updates * Update powerplatform.md all updates * Update sharepoint.md all updates * Update teams.md all updates * Update baselines/defender.md good catch! Co-authored-by: Addam Schroll <108814318+schrolla@users.noreply.github.com> * Update baselines/powerbi.md Co-authored-by: Addam Schroll <108814318+schrolla@users.noreply.github.com> * Update baselines/powerbi.md Co-authored-by: Addam Schroll <108814318+schrolla@users.noreply.github.com> * Update baselines/aad.md Co-authored-by: Addam Schroll <108814318+schrolla@users.noreply.github.com> * Update aad.md referenced old policy number * Update powerbi.md --------- Co-authored-by: Addam Schroll <108814318+schrolla@users.noreply.github.com> * WIP * Structural baseline updates (cleaned up) (#334) * Update aad.md all updates * Update defender.md all updates * Update exchange.md all updates * Rename exchange.md to exo.md * Update onedrive.md * Update powerbi.md all updates * Update powerplatform.md all updates * Update sharepoint.md all updates * Update teams.md all updates * Update baselines/defender.md good catch! Co-authored-by: Addam Schroll <108814318+schrolla@users.noreply.github.com> * Update baselines/powerbi.md Co-authored-by: Addam Schroll <108814318+schrolla@users.noreply.github.com> * Update baselines/powerbi.md Co-authored-by: Addam Schroll <108814318+schrolla@users.noreply.github.com> * Update baselines/aad.md Co-authored-by: Addam Schroll <108814318+schrolla@users.noreply.github.com> * Update aad.md referenced old policy number * Update powerbi.md --------- Co-authored-by: Addam Schroll <108814318+schrolla@users.noreply.github.com> * initial teams drop * Update AAD * WIP * WIP * WIP * WIP * WIP * Structural baseline updates (cleaned up) (#334) * Update aad.md all updates * Update defender.md all updates * Update exchange.md all updates * Rename exchange.md to exo.md * Update onedrive.md * Update powerbi.md all updates * Update powerplatform.md all updates * Update sharepoint.md all updates * Update teams.md all updates * Update baselines/defender.md good catch! Co-authored-by: Addam Schroll <108814318+schrolla@users.noreply.github.com> * Update baselines/powerbi.md Co-authored-by: Addam Schroll <108814318+schrolla@users.noreply.github.com> * Update baselines/powerbi.md Co-authored-by: Addam Schroll <108814318+schrolla@users.noreply.github.com> * Update baselines/aad.md Co-authored-by: Addam Schroll <108814318+schrolla@users.noreply.github.com> * Update aad.md referenced old policy number * Update powerbi.md --------- Co-authored-by: Addam Schroll <108814318+schrolla@users.noreply.github.com> * initial teams drop * Update AAD * WIP * Structural baseline updates (cleaned up) (#334) * Update aad.md all updates * Update defender.md all updates * Update exchange.md all updates * Rename exchange.md to exo.md * Update onedrive.md * Update powerbi.md all updates * Update powerplatform.md all updates * Update sharepoint.md all updates * Update teams.md all updates * Update baselines/defender.md good catch! Co-authored-by: Addam Schroll <108814318+schrolla@users.noreply.github.com> * Update baselines/powerbi.md Co-authored-by: Addam Schroll <108814318+schrolla@users.noreply.github.com> * Update baselines/powerbi.md Co-authored-by: Addam Schroll <108814318+schrolla@users.noreply.github.com> * Update baselines/aad.md Co-authored-by: Addam Schroll <108814318+schrolla@users.noreply.github.com> * Update aad.md referenced old policy number * Update powerbi.md --------- Co-authored-by: Addam Schroll <108814318+schrolla@users.noreply.github.com> * Fix UT errors * Default baseline for testing * Updates based on review comments * Call Import-SecureBaseline once * Update for review comments * Review updates * Add help comment * remove unused import * Fix OPA check issues * fix opa tests action * Update action to test * Action update * Sum PS/Bug as Errors * Update darkmode colors * Fix UT after Rebase * Fix UT * Fix error log * Update UT for NewReport * Update link color --------- Co-authored-by: Andrew Huynh <113476170+ahuynhMITRE@users.noreply.github.com> Co-authored-by: Addam Schroll <108814318+schrolla@users.noreply.github.com> Co-authored-by: Sloane4 * Check if missing reported * Change missing to warning * Fix UT for warning * Update Testing/Unit/PowerShell/CreateReport/New-Report.Tests.ps1 * Update Testing/Unit/PowerShell/CreateReport/New-Report.Tests.ps1 * Align with updated defender.md * Update to match defender --------- Co-authored-by: Andrew Huynh <113476170+ahuynhMITRE@users.noreply.github.com> Co-authored-by: Addam Schroll <108814318+schrolla@users.noreply.github.com> Co-authored-by: Sloane4 --- .../Modules/CreateReport/CreateReport.psm1 | 4 +- .../SmokeTest/SmokeTest001.Tests.ps1 | 6 ++- .../SmokeTest/SmokeTest002.Tests.ps1 | 42 +++++++++++++++---- .../Import-SecureBaseline.Tests.ps1 | 2 +- .../CreateReport/New-Report.Tests.ps1 | 19 +++++---- 5 files changed, 50 insertions(+), 23 deletions(-) diff --git a/PowerShell/ScubaGear/Modules/CreateReport/CreateReport.psm1 b/PowerShell/ScubaGear/Modules/CreateReport/CreateReport.psm1 index d65b4dd815..8b11beabf8 100644 --- a/PowerShell/ScubaGear/Modules/CreateReport/CreateReport.psm1 +++ b/PowerShell/ScubaGear/Modules/CreateReport/CreateReport.psm1 @@ -76,7 +76,7 @@ function New-Report { } $MetaDataTable = $MetaData | ConvertTo-HTML -Fragment - $MetaDataTable = $MetaDataTable -replace '^(.*?)','
' + $MetaDataTable = $MetaDataTable -replace '^(.*?)
','
' $Fragments += $MetaDataTable $ReportSummary = @{ "Warnings" = 0; @@ -144,7 +144,7 @@ function New-Report { "Criticality"= "-" "Details"= "Report issue on GitHub" } - Write-Error("ERROR: No test results found for Control Id $($Control.Id)") + Write-Warning -Message "WARNING: No test results found for Control Id $($Control.Id)" } } diff --git a/Testing/Functional/SmokeTest/SmokeTest001.Tests.ps1 b/Testing/Functional/SmokeTest/SmokeTest001.Tests.ps1 index a52e4e422c..03eddc002f 100644 --- a/Testing/Functional/SmokeTest/SmokeTest001.Tests.ps1 +++ b/Testing/Functional/SmokeTest/SmokeTest001.Tests.ps1 @@ -51,10 +51,12 @@ Describe "Smoke Test: Generate Output" { Context "Invoke Scuba for $Organization" { BeforeAll { if ($PSCmdlet.ParameterSetName -eq 'Manual'){ - Invoke-SCuBA -ProductNames "*" -M365Environment $M365Environment + { Invoke-SCuBA -ProductNames "*" -M365Environment $M365Environment } | + Should -Not -Throw } else { - Invoke-SCuBA -CertificateThumbprint $Thumbprint -AppID $AppId -Organization $Organization -ProductNames "*" -M365Environment $M365Environment + { Invoke-SCuBA -CertificateThumbprint $Thumbprint -AppID $AppId -Organization $Organization -ProductNames "*" -M365Environment $M365Environment } | + Should -Not -Throw } $ReportFolders = Get-ChildItem . -directory -Filter "M365BaselineConformance*" | Sort-Object -Property LastWriteTime -Descending [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', 'OutputFolder', diff --git a/Testing/Functional/SmokeTest/SmokeTest002.Tests.ps1 b/Testing/Functional/SmokeTest/SmokeTest002.Tests.ps1 index d2ff29c8eb..16b8bd42d0 100644 --- a/Testing/Functional/SmokeTest/SmokeTest002.Tests.ps1 +++ b/Testing/Functional/SmokeTest/SmokeTest002.Tests.ps1 @@ -30,7 +30,7 @@ param ( Import-Module Selenium Describe -Tag "UI","Chrome" -Name "Test Report with for $OrganizationName" -ForEach @( - @{ Browser = "Chrome"; Driver = Start-SeChrome -Arguments @('start-maximized') 2>$null } + @{ Browser = "Chrome"; Driver = Start-SeChrome -Headless -Arguments @('start-maximized') 2>$null } ){ BeforeAll { $ReportFolders = Get-ChildItem . -directory -Filter "M365BaselineConformance*" | Sort-Object -Property LastWriteTime -Descending @@ -95,20 +95,44 @@ Describe -Tag "UI","Chrome" -Name "Test Report with for $OrganizationN $DetailLink | Should -Not -BeNullOrEmpty Invoke-SeClick -Element $DetailLink + # For better performance turn off implict wait + $Driver.Manage().Timeouts().ImplicitWait = New-TimeSpan -Seconds 0 + $Tables = Get-SeElement -Driver $Driver -By TagName 'table' $Tables.Count | Should -BeGreaterThan 1 ForEach ($Table in $Tables){ - $Row = Get-SeElement -Element $Table -By TagName 'tr' - $Row.Count | Should -BeGreaterThan 0 - - ForEach ($Row in $Rows){ - $RowHeaders = Get-SeElement -Element $Row -By TagName 'th' - $RowHeaders.Count | Should -BeExactly 1 - $RowData = Get-SeElement -Element $Row -By TagName 'td' - $RowData.Count | Should -BeGreaterThan 0 + $Rows = Get-SeElement -Element $Table -By TagName 'tr' + $Rows.Count | Should -BeGreaterThan 0 + + if ($Table.GetProperty("id") -eq "tenant-data"){ + $Rows.Count | Should -BeExactly 2 + $TenantDataColumns = Get-SeElement -Target $Rows[1] -By TagName "td" + $Tenant = $TenantDataColumns[0].Text + $Tenant | Should -Be $OrganizationName -Because "Tenant is $Tenant" + } else { + # Control report tables + ForEach ($Row in $Rows){ + $RowHeaders = Get-SeElement -Element $Row -By TagName 'th' + $RowData = Get-SeElement -Element $Row -By TagName 'td' + + ($RowHeaders.Count -eq 0 ) -xor ($RowData.Count -eq 0) | Should -BeTrue -Because "Any given row should be homogenious" + + if ($RowHeaders.Count -gt 0){ + $RowHeaders.Count | Should -BeExactly 5 + $RowHeaders[0].text | Should -BeLikeExactly "Control ID" + } + + if ($RowData.Count -gt 0){ + $RowData.Count | Should -BeExactly 5 + $RowData[2].text | Should -Not -BeLikeExactly "Error - Test results missing" -Because "All policies should have implementations: $($RowData[0].text)" + } + } } } + + # Turn implict wait back on + $Driver.Manage().Timeouts().ImplicitWait = New-TimeSpan -Seconds 10 } } diff --git a/Testing/Unit/PowerShell/CreateReport/Import-SecureBaseline.Tests.ps1 b/Testing/Unit/PowerShell/CreateReport/Import-SecureBaseline.Tests.ps1 index d425047ab1..d1f1b8e80d 100644 --- a/Testing/Unit/PowerShell/CreateReport/Import-SecureBaseline.Tests.ps1 +++ b/Testing/Unit/PowerShell/CreateReport/Import-SecureBaseline.Tests.ps1 @@ -34,7 +34,7 @@ InModuleScope CreateReport { } It "Validate markdown group count for " -ForEach @( @{Product = "aad"; GroupCount = 18; PolicyCount = 33} - @{Product = "defender"; GroupCount = 10; PolicyCount = 46} + @{Product = "defender"; GroupCount = 6; PolicyCount = 22} @{Product = "exo"; GroupCount = 17; PolicyCount = 39} @{Product = "onedrive"; GroupCount = 7; PolicyCount = 8} @{Product = "powerbi"; GroupCount = 10; PolicyCount = 12} diff --git a/Testing/Unit/PowerShell/CreateReport/New-Report.Tests.ps1 b/Testing/Unit/PowerShell/CreateReport/New-Report.Tests.ps1 index 64758d5a28..79b7a8cffc 100644 --- a/Testing/Unit/PowerShell/CreateReport/New-Report.Tests.ps1 +++ b/Testing/Unit/PowerShell/CreateReport/New-Report.Tests.ps1 @@ -3,7 +3,8 @@ Import-Module (Join-Path -Path $PSScriptRoot -ChildPath '../../../../PowerShell/ InModuleScope CreateReport { Describe -Tag CreateReport -Name 'New-Report' { BeforeAll { - Mock -CommandName Write-Error {} + Mock -CommandName Write-Warning {} + New-Item -Path (Join-Path -Path "TestDrive:" -ChildPath "CreateReportStubs") -Name "CreateReportUnitFolder" -ItemType Directory New-Item -Path (Join-Path -Path "TestDrive:" -ChildPath "CreateReportStubs/CreateReportUnitFolder") -Name "IndividualReports" -ItemType Directory $TestOutPath = (Join-Path -Path "TestDrive:" -ChildPath "CreateReportStubs") @@ -41,13 +42,13 @@ InModuleScope CreateReport { } } It 'Creates a report for ' -ForEach @( - @{Product = 'aad'; ErrorCount = 1}, - @{Product = 'defender'; ErrorCount = 3}, - @{Product = 'exo'; ErrorCount = 2}, - @{Product = 'onedrive'; ErrorCount = 8}, - @{Product = 'powerplatform'; ErrorCount = 0}, - @{Product = 'sharepoint'; ErrorCount = 5}, - @{Product = 'teams'; ErrorCount = 5} + @{Product = 'aad'; WarningCount = 1}, + @{Product = 'defender'; WarningCount = 10}, + @{Product = 'exo'; WarningCount = 2}, + @{Product = 'onedrive'; WarningCount = 8}, + @{Product = 'powerplatform'; WarningCount = 0}, + @{Product = 'sharepoint'; WarningCount = 5}, + @{Product = 'teams'; WarningCount = 5} ){ $CreateReportParams += @{ 'BaselineName' = $ArgToProd[$Product]; @@ -55,8 +56,8 @@ InModuleScope CreateReport { } { New-Report @CreateReportParams } | Should -Not -Throw + Should -Invoke -CommandName Write-Warning -Exactly -Times $WarningCount - Should -Invoke -CommandName Write-Error -Exactly -Times $ErrorCount Test-Path -Path "$($IndividualReportPath)/$($ArgToProd[$Product])Report.html" -PathType leaf | Should -Be $true } } From d4231165a3426acea5194028d5330b36d6fcdaa5 Mon Sep 17 00:00:00 2001 From: Dylan Gao <107067015+Dylan-MITRE@users.noreply.github.com> Date: Fri, 16 Jun 2023 11:04:01 -0400 Subject: [PATCH 08/33] One drive baseline (#370) * update onedrive baseline * remove should shall language * remove Configuring On-Premises Devices session at the end of the doc * Update wording for policy1 Co-authored-by: Addam Schroll <108814318+schrolla@users.noreply.github.com> * Update policy 2 to keep consistency Co-authored-by: Addam Schroll <108814318+schrolla@users.noreply.github.com> * Update wording for note Co-authored-by: Addam Schroll <108814318+schrolla@users.noreply.github.com> * Spelling error fix Co-authored-by: Addam Schroll <108814318+schrolla@users.noreply.github.com> * spelling fix Co-authored-by: Addam Schroll <108814318+schrolla@users.noreply.github.com> * change name to match with sharepoint * Update onedrive.md remove MS.ONEDRIVE.3.1v1 because it is actually duplicate of policy MS.ONEDRIVE.1.1v1 @Sloane4 Might want to remove the reference in MS.SHAREPOINT.2.1v1 * Update onedrive.md revert changes --------- Co-authored-by: Addam Schroll <108814318+schrolla@users.noreply.github.com> --- baselines/onedrive.md | 246 ++++++++---------------------------------- 1 file changed, 42 insertions(+), 204 deletions(-) diff --git a/baselines/onedrive.md b/baselines/onedrive.md index 170eea0baf..3840ce3fd0 100644 --- a/baselines/onedrive.md +++ b/baselines/onedrive.md @@ -43,7 +43,7 @@ strengthen the security of widely used cloud-based software services. # Baseline -## 1. Anyone Links +## 1. External Sharing Unauthenticated sharing (Anyone links) is used to share data without authentication and users are free to pass it on to others outside the @@ -54,20 +54,21 @@ in SharePoint, Groups, or Teams. ### Policies #### MS.ONEDRIVE.1.1v1 -Anyone links SHOULD be disabled. +External sharing SHOULD be limited to Existing Guests or the more restrictive setting, Only People in your Organization. - _Rationale:_ TODO -- _Last modified:_ June 2023 +- _Last Modified:_ June 2023 +- _Note:_ Same Implementation in MS.SHAREPOINT.1.1V1 ### Resources - [Limit accidental exposure \| Microsoft - Docs](https://docs.microsoft.com/en-us/microsoft-365/solutions/share-limit-accidental-exposure?view=o365-worldwide) + Docs](https://learn.microsoft.com/en-us/microsoft-365/solutions/share-limit-accidental-exposure?view=o365-worldwide) -### License Requirements +### License Requirements - N/A -### Implementation +### Implementation **Note**: OneDrive settings can be more restrictive than the SharePoint setting, but not more permissive. @@ -79,22 +80,21 @@ To turn off Anyone links for the agency: 2. In the left-hand navigation pane, expand **Policies,** then select [**Sharing**](https://go.microsoft.com/fwlink/?linkid=2185222). -3. Set the SharePoint external sharing settings to **New and existing - guests**, then set OneDrive to **New and existing guests**. +3. Set the SharePoint external sharing settings to either **Existing guests** or **Only people in your organization**, then set OneDrive to either **Existing guests** or **Only people in your organization**. 4. Click **Save**. -To turn off Anyone links for a site: - +To turn off Anyone links for a site: (**Default is set to organization-level settings**) + 1. In the **SharePoint admin center** left navigation pane, expand **Sites,** and select [**Active sites**](https://go.microsoft.com/fwlink/?linkid=2185220). 2. Select the site to configure. -3. In the ribbon, select **Sharing**. +3. In the ribbon, under **Settings**, select **More sharing settings**. -4. Ensure that **Sharing** is set to **New and existing guests**. +4. Ensure that **External Sharing** is set to either **Existing guests** or **Only people in your organization**. 5. Click **Save**. @@ -104,34 +104,28 @@ Files that are stored in SharePoint sites, Groups, and Teams for months and years could lead to unexpected modifications to files if shared with unauthenticated people. Configuring expiration times for Anyone links can help avoid unwanted changes. If Anyone links are enabled, the -expiration date SHOULD be set to thirty days or as determined by mission -needs or agency policy. +expiration date of thirty days or less is necessary. ### Policies #### MS.ONEDRIVE.2.1v1 -Expiration Date SHOULD Be Set for Anyone Links. -- _Rationale:_ TODO -- _Last modified:_ June 2023 - -#### MS.ONEDRIVE.2.2v1 -Expiration date SHOULD be set to thirty days. +Expiration Date SHOULD Be Set for Anyone Links for 30 days or less. - _Rationale:_ TODO - _Last modified:_ June 2023 -### Resources +### Resources - [Best practices for unauthenticated sharing \| Microsoft - Docs](https://docs.microsoft.com/en-us/microsoft-365/solutions/best-practices-anonymous-sharing?view=o365-worldwide) + Docs](https://learn.microsoft.com/en-us/microsoft-365/solutions/best-practices-anonymous-sharing?view=o365-worldwide) -### License Requirements +### License Requirements - N/A -### Implementation +### Implementation To set an expiration date for Anyone links across the agency (**Note**: -Anyone links must be enabled). +Only necessary when MS.ONEDRIVE.1.1v1 is not being implemented and OneDrive external sharing is set to Anyone). 1. Open the **SharePoint admin center.** @@ -139,30 +133,13 @@ Anyone links must be enabled). select [**Sharing**](https://go.microsoft.com/fwlink/?linkid=2185222). -3. Under **Choose expiration and permissions options for Anyone - links**, select the **These links must expire within this many - days** check box. - -4. Enter the number of days in the box, and then click **Save**. - -To set an expiration date for Anyone links on a specific site: - -1. Open the **SharePoint admin center**, expand **Sites**, and then - select [**Active - sites**](https://go.microsoft.com/fwlink/?linkid=2185220). - -2. Select the site to change, and then select **Sharing**. - -3. Under **Advanced settings for Anyone links**, under **Expiration of - Anyone links**, clear the **Same as organization-level setting** +3. Under **Choose expiration and permissions options for Anyone links**, + select the **These links must expire within this many days** check box. -4. Select the **These links must expire within this many days** option - and enter a number of days in the box. - -5. Click **Save**. +4. Enter the number of days in the box, and then click **Save**. -## 3. Link Permissions +## 3. File and Folder Links Default Sharing Settings The Anyone links default to allow people to edit files, as well as edit and view files and upload new files to folders. To allow unauthenticated @@ -172,46 +149,20 @@ content, consider setting the file and folder permissions to **View**. ### Policies #### MS.ONEDRIVE.3.1v1 -Link Permissions SHOULD Be Set to Enabled Anyone Links to View. +Default Link Sharing Type SHOULD NOT Be Set to Anyone - _Rationale:_ TODO - _Last modified:_ June 2023 +_Note:_ Similar Implementation in MS.SHAREPOINT.2.1V1 -### Resources - -- [Set link permissions \| Microsoft - Docs](https://docs.microsoft.com/en-us/microsoft-365/solutions/best-practices-anonymous-sharing?view=o365-worldwide#set-link-permissions) - -### License Requirements - -- N/A - -### Implementation - -1. Open the **SharePoint admin center**. - -2. In the left-hand navigation pane, expand **Policies**, then select - **Sharing**. - -3. Under **Advanced settings for Anyone links**, set the file and - folder permissions to **View**. - -## 4. OneDrive Client - -Configuring OneDrive to sync only to agency-defined domains ensures that -users can only sync to agency-managed computers. - -### Policies - -#### MS.ONEDRIVE.4.1v1 -OneDrive Client SHALL Be Restricted to Windows for Agency-Defined Domain(s). +#### MS.ONEDRIVE.3.2v1 +Anyone Link Permissions SHOULD Be Set to View Only - _Rationale:_ TODO - _Last modified:_ June 2023 ### Resources -- [Allow syncing only on computers joined to specific domains – OneDrive - \| Microsoft - Docs](https://docs.microsoft.com/en-us/onedrive/allow-syncing-only-on-specific-domains) +- [Set link permissions \| Microsoft + Docs](https://learn.microsoft.com/en-us/microsoft-365/solutions/best-practices-anonymous-sharing?view=o365-worldwide#set-link-permissions) ### License Requirements @@ -219,52 +170,31 @@ OneDrive Client SHALL Be Restricted to Windows for Agency-Defined Domain(s). ### Implementation -1. Open the **SharePoint admin center.** - -2. In the left-hand navigation pane, select **Settings** and sign in - with an account that has [admin - permissions](https://docs.microsoft.com/en-us/sharepoint/sharepoint-admin-role) - for the agency. - -3. Select **Sync**. - -4. Select the **Allow syncing only on computers joined to specific - domains** check box. - -5. Add the [Globally Unique Identifier (GUID) of each - domain](https://docs.microsoft.com/en-us/powershell/module/activedirectory/get-addomain?view=windowsserver2022-ps) for - the member computers that the agency wants to be able to sync. +To set the default file and folder sharing link for the organization: -**Note:** Add the domain GUID of the computer domain membership. If -users are in a separate domain, only the domain GUID that the computer -account is joined to is required. +1. Open the **SharePoint admin center**. -**Important:** This setting is only applicable to Active Directory -domains. It does not apply to Azure Active Directory (AAD) domains. If -agency devices are only Azure AD joined, consider using a [Conditional -Access Policy](https://docs.microsoft.com/en-us/azure/active-directory/conditional-access/overview) -instead. +2. In the left-hand navigation pane, expand **Policies**, then select + **Sharing**. -6. Click **Save**. +3. Under **File and folder links**, for **Choose the type of link that's selected by default when users share files and folders in SharePoint and OneDrive** + select **Only people in your organization** or **Specific people (only the people the user specifies)**. -## 5. Sync with Mac for Agency-Defined Devices +The set Link permission to View Only -Set restrictions on whether users can sync items to non-domain joined -machines, control the list of allowed domains, and manage whether Mac -clients (which do not support domain join) can sync. +1. Open the **SharePoint admin center**. -### Policies +2. In the left-hand navigation pane, expand **Policies**, then select + **Sharing**. -#### MS.ONEDRIVE.5.1v1 -OneDrive Client SHALL Be Restricted to Sync with Mac for Agency-Defined Devices. -- _Rationale:_ TODO -- _Last modified:_ June 2023 +3. Under **File and folder links**, for **Choose the permission that's selected by default for sharing links** + select **View**. ### Resources - [Set-SPOTenantSyncClientRestriction (SharePointOnlinePowerShell) \| Microsoft - Docs](https://docs.microsoft.com/en-us/powershell/module/sharepoint-online/set-spotenantsyncclientrestriction?view=sharepoint-ps#:~:text=In%20order%20to%20explicitly%20block%20Microsoft%20OneDrive%20client,cmdlet%20with%20the%20BlockMacSync%20parameter%20set%20to%20true.?msclkid=f80f95c5c4c611ecac7de0980370f33c) + Docs](https://learn.microsoft.com/en-us/powershell/module/sharepoint-online/set-spotenantsyncclientrestriction?view=sharepoint-ps) ### License Requirements @@ -282,83 +212,6 @@ reflected within five minutes. "786548DD-877B-4760-A749-6B1EFBC1190A; 877564FF-877B-4760-A749-6B1EFBC1190A" -BlockMacSync:$false` -## 6. Local Domain Sync - -Configuring OneDrive to sync only to agency-defined domains ensures that -users can only sync to agency-managed computers. - -### Policies - -#### MS.ONEDRIVE.6.1v1 -OneDrive Client Sync SHALL Only Be Allowed Within the Local Domain. -- _Rationale:_ TODO -- _Last modified:_ June 2023 - -### Resources - -- [Allow syncing only on computers joined to specific domains \| - Microsoft - Documents](https://docs.microsoft.com/en-us/onedrive/allow-syncing-only-on-specific-domains) - -### License Requirements - -- N/A - -### Implementation - -1. Open the **SharePoint admin center**. - -2. In the left-hand navigation pane, select **Settings**. - -3. Next to **OneDrive**, click **Sync** to display synchronization - settings. - -4. On the **Sync settings** page, confirm that **Allow syncing only on - computers joined to specific domains** is checked, and that a domain - GUID displays in the box below it. - -## 7. Legacy Authentication - -Modern authentication, based on Active Directory Authentication Library -(ADAL) and Open Authorization 2 (OAuth2), is a critical component of -security in Office 365. It provides the device authentication and -authorization capability of Office 365, which is a foundational security -component. If modern authentication is not required, this creates a -loophole that could allow unauthorized devices to connect to OneDrive -and download/exfiltrate enterprise data. For this reason, it is -important to make sure that only apps that support modern authentication -are allowed to connect, assuring that only authorized devices are -allowed to access enterprise data. - -### Policies - -#### MS.ONEDRIVE.7.1v1 -Legacy Authentication SHALL Be Blocked. -- _Rationale:_ TODO -- _Last modified:_ June 2023 - -### Resources - -- [Control access from unmanaged devices \| Microsoft - Documents](https://docs.microsoft.com/en-us/sharepoint/control-access-from-unmanaged-devices) - -### License Requirements - -- N/A - -### Implementation - -1. Open the **SharePoint admin center**. - -2. In the left-hand navigation pane, click **Policies** \> **Access - Control** \> **Device access**. - -3. Click **Apps that don’t use modern authentication** to display the - device access settings. - -4. On the **Apps that don’t use modern authentication** page, select - the **Block access** option. - # Acknowledgements In addition to acknowledging the important contributions of a diverse @@ -409,18 +262,3 @@ Dr. Mukesh Rohatgi (MITRE), Lee Szilagyi (MITRE), Nanda Katikaneni (MITRE), Ted Kolovos (MITRE), Thomas Comeau (MITRE), Karen Caraway (MITRE), Jackie Whieldon (MITRE), Jeanne Firey (MITRE), Kenneth Myers (General Services Administration). - -# Configuring On-Premises Devices - -##### Limit Syncing to Agency-defined Equipment within the Agency (Tenants) - -OneDrive includes a sync client that allows users to synchronize their -files from the OneDrive cloud service to their desktop/laptop computer. -This allows them to interact with a local copy of the files in a way -that is very similar to working with regular local files on their -computer. - -**Resources** - -[Use OneDrive policies to control sync settings - OneDrive \| Microsoft -Docs](https://docs.microsoft.com/en-us/onedrive/use-group-policy#allow-syncing-onedrive-accounts-for-only-specific-organizations) From 99081e7464738b78c76c15255fd21961232632fa Mon Sep 17 00:00:00 2001 From: Addam Schroll <108814318+schrolla@users.noreply.github.com> Date: Mon, 26 Jun 2023 11:46:23 -0500 Subject: [PATCH 09/33] DLP policy group additions and updates (#381) --- baselines/defender.md | 253 +++++++++++++++++++++++++++++++++--------- 1 file changed, 200 insertions(+), 53 deletions(-) diff --git a/baselines/defender.md b/baselines/defender.md index 781a6e80a1..3c066910d8 100644 --- a/baselines/defender.md +++ b/baselines/defender.md @@ -204,40 +204,69 @@ Docs](https://docs.microsoft.com/en-us/microsoft-365/security/office-365-securit ## 4. Data Loss Prevention -There are multiple, different ways to secure sensitive information, such +There are several approaches to secure sensitive information, such as warning users, encryption, or blocking attempts to share. The agency’s data loss prevention (DLP) policy will dictate what agency -information is sensitive and how that information is handled. +information is sensitive and how that information is handled. Defender +can detect sensitive information and associates a default confidence +level with this detection based on the sensitive information type +matched. Confidence levels are used to reduce false positives in +detecting access to sensitive information. Agencies may choose to use +the default confidence levels or adjust the levels in custom DLP policies +to fit their environment and needs. ### Policies #### MS.DEFENDER.4.1v1 -A custom policy SHALL be configured to protect PII and sensitive information, as defined by the agency. At a minimum, credit card numbers, Taxpayer Identification Numbers (TIN), and Social Security Numbers (SSN) SHALL be blocked. - - _Rationale:_ TODO +A custom policy SHALL be configured to protect PII and sensitive information, +as defined by the agency. At a minimum, credit card numbers, Taxpayer +Identification Numbers (TIN), and Social Security Numbers (SSN) SHALL be +blocked. + - _Rationale:_ Users may inadvertently share sensitive information with + others who should not have access to it. Data loss prevention policies provide a way for agencies to detect + and prevent unauthorized disclosures. - _Last modified:_ June 2023 #### MS.DEFENDER.4.2v1 -The custom policy SHOULD be applied in Exchange, OneDrive, Teams Chat, and Microsoft Defender. -- _Rationale:_ TODO +The custom policy SHOULD be applied in Exchange, OneDrive, Teams Chat, +and Devices. +- _Rationale:_ Unauthorized disclosures may happen through Microsoft 365 + services or endpoint devices. Data loss prevention + policies should cover all affected locations to be + effective. - _Last modified:_ June 2023 #### MS.DEFENDER.4.3v1 The action for the DLP policy SHOULD be set to block sharing sensitive information with everyone when DLP conditions are met. -- _Rationale:_ TODO +- _Rationale:_ Access to sensitive information should be prohibited unless + explicitly allowed. Specific exemptions can be made based + on agency policies and valid business justifications. - _Last modified:_ June 2023 #### MS.DEFENDER.4.4v1 Notifications to inform users and help educate them on the proper use of sensitive information SHOULD be enabled. -- _Rationale:_ TODO +- _Rationale:_ Some users may not be aware of agency policies on the + proper use of sensitive information. Enabling + notifications provides positive feedback to users when + accessing sensitive information. - _Last modified:_ June 2023 #### MS.DEFENDER.4.5v1 -A list of apps that are not allowed to access files protected by DLP policy SHOULD be defined. -- _Rationale:_ TODO +A list of apps that are restricted when accessing files protected by DLP policy SHOULD be defined. +- _Rationale:_ Some applications may inappropriately share accessed files + or not conform to agency policies for access to sensitive + information. Defining a list of those apps makes it + possible to use DLP policies to restrict those apps access + to sensitive information on endpoints using Defender. - _Last modified:_ June 2023 #### MS.DEFENDER.4.6v1 -A list of browsers that are not allowed to access files protected by DLP policy SHOULD be defined. -- _Rationale:_ TODO +The custom policy SHOULD include an action to block access to sensitive +information by restricted apps and unwanted bluetooth applications. +- _Rationale:_ Some applications may inappropriately share accessed files + or not conform to agency policies for access to sensitive + information. Defining a DLP policy with an action to block + access from restricted apps and unwanted bluetooth applications prevents unauthorized disclosure by those + programs. - _Last modified:_ June 2023 ### Resources @@ -269,55 +298,54 @@ A list of browsers that are not allowed to access files protected by DLP policy ### Implementation -1. Sign in to the [Microsoft 365 - compliance](https://compliance.microsoft.com) admin center. +MS.DEFENDER.4.1v1 implementation: -2. Under **Solutions**, select **Data loss prevention**. +1. Sign in to the [Microsoft 365 + compliance](https://compliance.microsoft.com) admin center. -3. Select **Policies** from the top of the page. +2. Under **Solutions**, select **Data loss prevention**. -4. Select **Default Office 365 DLP policy**. +3. Select **Policies** from the top of the page. -5. Select **Edit policy**. +4. Select **Default Office 365 DLP policy**. -6. Edit the name and description of the policy if desired, then click - **Next**. +5. Select **Copy policy**. -7. Under **Locations to apply the policy**, set **Status** to **On** - for all products except Power BI (preview). +6. Edit the name and description of the policy if desired, then click + **Next**. -8. Click **Create rule**. Assign the rule an appropriate name and - description. +7. Under **Assign admin units**, select **Full directory**, then click + **Next**. -9. Click **Add condition**, then **Content contains**. +8. Under **Choose Locations to apply the policy**, set **Status** to **On** + for all products except Power BI and Microsoft Defender for Cloud + Apps. -10. Click **Add**, then **Sensitive info types**. +9. Click **Create rule**. Assign the rule an appropriate name and + description. -11. Create policies that protect information that is sensitive to the - agency. At a minimum, the agency should protect: +10. Click **Add condition**, then **Content contains**. - - Credit card numbers +11. Click **Add**, then **Sensitive info types**. - - U.S. Individual Taxpayer Identification Numbers (TIN) - - - U.S. Social Security Numbers (SSN) - - - All agency defined PII and sensitive information +12. Add info types that protect information that is sensitive to the + agency. At a minimum, the agency should protect: -12. Click **Add**. + - Credit card numbers + - U.S. Individual Taxpayer Identification Numbers (TIN) + - U.S. Social Security Numbers (SSN) + - All agency defined PII and sensitive information -13. Under **Actions**, click **Add an action**. +13. Click **Add**. -14. Click **Restrict access of encrypt the content in Microsoft 365 - locations**. +14. Under **Actions**, click **Add an action**. 15. Check **Restrict Access or encrypt the content in Microsoft 365 locations**. 16. Select **Block Everyone**. -17. Turn on **Use notifications to inform your users and help educate - them on the proper use of sensitive info**. +17. Turn on **Use notifications to inform your users and help educate them on the proper use of sensitive info**. 18. Click **Save**, then **Next**. @@ -325,27 +353,146 @@ A list of browsers that are not allowed to access files protected by DLP policy 20. Click **Submit**. -21. Go to **Endpoint DLP Settings.** +MS.DEFENDER.4.2v1 implementation: + +1. Sign in to the [Microsoft 365 + compliance](https://compliance.microsoft.com) admin center. + +2. Under **Solutions**, select **Data loss prevention**. + +3. Select **Policies** from the top of the page. + +4. Find the relevant DLP policy in the list and click the Policy name to select. + Select **Edit Policy**. + +5. Click **Next** on each page in the policy wizard until you reach the + Locations page. + +6. Under **Choose locations to apply the policy**, ensure **Status** is set + to **On** for at least the Exchange email, OneDrive accounts, Teams chat + and channel messages, and Devices. + +7. Click **Next** on each page until reaching the + **Review your policy and create it** page. + +8. Review the policy locations listed and click **Submit**. + +MS.DEFENDER.4.3v1 implementation: + +1. Sign in to the [Microsoft 365 + compliance](https://compliance.microsoft.com) admin center. + +2. Under **Solutions**, select **Data loss prevention**. + +3. Select **Policies** from the top of the page. + +4. Select the relevant custom policy and select **Edit policy**. + +5. Click **Next** on each page in the policy wizard until you reach the + Advanced DLP rules page. + +6. Select the relevant rule and click the pencil icon to edit it. + +7. Under **Actions**, click **Add an action**. + +8. Select **Restrict Access or encrypt the content in Microsoft 365 + locations**. + +9. Select **Block Everyone**. + +10. Click **Save** to save the changes. + +11. Click **Next** on each page until reaching the + **Review your policy and create it** page. + +12. Review the policy and click **Submit** to complete the policy changes. + +MS.DEFENDER.4.4v1 implementation: + +1. Sign in to the [Microsoft 365 + compliance](https://compliance.microsoft.com) admin center. + +2. Under **Solutions**, select **Data loss prevention**. + +3. Select **Policies** from the top of the page. + +4. Select the relevant custom policy and select **Edit policy**. + +5. Click **Next** on each page in the policy wizard until you reach the + Advanced DLP rules page. + +6. Select the relevant rule and click the pencil icon to edit it. + +7. Under **User notifications**, toggle **Turn on Use notifications to inform + your users and help educate them on the proper use of sensitive info.** + to **On**. + +8. Click **Save** to save the changes. + +9. Click **Next** on each page until reaching the + **Review your policy and create it** page. + +10. Review the policy and click **Submit** to complete the policy changes. + +MS.DEFENDER.4.5v1 implementation: + +1. Sign in to the [Microsoft 365 + compliance](https://compliance.microsoft.com) admin center. + +2. Under **Solutions**, select **Data loss prevention**. + +3. Go to **Endpoint DLP Settings**. + +4. Go to **Restricted apps and app groups**. + +5. Click **Add or edit Restricted Apps**. + +6. Enter an app and executable name to disallow said app from + accessing protected files and to log the incident. + +7. Return and click **Unallowed Bluetooth apps**. + +8. Click **Add or edit unallowed Bluetooth apps**. + +9. Enter an app and executable name to disallow said app from + accessing protected files and to log the incident. + +MS.DEFENDER.4.6v1 implementation: + +1. Sign in to the [Microsoft 365 + compliance](https://compliance.microsoft.com) admin center. + +2. Under **Solutions**, select **Data loss prevention**. + +3. Select **Policies** from the top of the page. + +4. Find the relevant DLP policy in the list and click the Policy name to select. + Select **Edit Policy**. + +5. Click **Next** on each page in the policy wizard until you reach the + Advanced DLP rules page. + +6. Select the relevant rule and click the pencil icon to edit it. - 1. Go to **Unallowed Apps.** +7. Under **Actions**, click **Add an action**. - 2. Click **Add** or **Edit Unallowed Apps.** +8. Choose **Audit or restrict activities on device** - 3. Enter an app and executable name to disallow said app from accessing - protected files and to log the incident. +9. Under **File activities for all apps**, select + **Apply restrictions to specific activity**. - 4. Return and click **Unallowed Bluetooth Apps**. +10. Check the box next to **Copy or move using unallowed Bluetooth app** + and set its action to **Block**. - 5. Enter an app and executable name to disallow said app from accessing - protected files and to log the incident. +11. Under **Restricted app activities** , check the **Access by restricted apps** box + and set the action drop-down to **Block**. - 6. Return and click **Browser and domain restrictions to sensitive - data**. +12. Click **Save** to save the changes. - 7. Under **Unallowed Browsers**, enter and select needed browsers to - prevent that browser from accessing protected files. +13. Click **Next** on each page until reaching the + **Review your policy and create it** page. - 8. Switch **Always audit file activity for devices** to **ON**. +14. Review the policy and click **Submit** to complete the policy changes. ## 5. Alerts From b023ecb60148e6db27ee70ed018f5230bd344627 Mon Sep 17 00:00:00 2001 From: Shanti Satyapal <78565245+ssatyapal123@users.noreply.github.com> Date: Thu, 29 Jun 2023 10:50:47 -0400 Subject: [PATCH 10/33] Adjudicate Substantive AAD Baseline Comments (#379) * Updated to reflect phishing-resistant preferences * Updated to reflect phishing resistant pref'starting * Updates to AAD Policy 2.4 * Updates to aad policies * Updates to aad markdown * aad updates * aad baseline updates * aad baseline update (2.10) * aad baseline updates (removed 2.9) * updates to aad baseline (16.2) * aad 4.1 implementation updates * updates to aad 4 baseline policy implementations * Updates to aad policy 14 * updates to aad baseline * updates to aad.4.7v1 implementation * updates to aad.4.7v1 * Consolidated highly privileged user policies * fixes to aad.11.x * updates to policy 7 * Update to AAD 11 policy front matter (intro text) * updates to aad baseline * testing write to GitHub * backup of revisions 062223 * backup 062323 6:47 * backup 062623 --------- Co-authored-by: Ted Kolovos --- baselines/aad.md | 1437 +++++++++++++------------------------------- images/aad-mfa.png | Bin 42482 -> 46669 bytes 2 files changed, 425 insertions(+), 1012 deletions(-) diff --git a/baselines/aad.md b/baselines/aad.md index a6ead4a6cb..aa45480f86 100644 --- a/baselines/aad.md +++ b/baselines/aad.md @@ -1,95 +1,70 @@ -# Introduction +# CISA M365 Security Configuration Baseline for Azure Active Directory -## Key Terminology +Azure Active Directory (AAD) is a cloud-based identity and access control service that provides security and functional capabilities to Microsoft 365. This security baseline provides policies to help secure AAD. -The following are key terms and descriptions used in this document. +## License Compliance and Copyright -**Hybrid Azure Active Directory (AD)** – This term denotes the scenario -when an organization has an on-premises AD domain that contains the -master user directory but federates access to the cloud Microsoft 365 -(M365) Azure AD tenant. - -**Resource Tenant** – In scenarios where external users are involved -(e.g., guest users), the [resource tenant](https://docs.microsoft.com/en-us/azure/active-directory/external-identities/authentication-conditional-access) -hosts the M365 resources being used. - -**Home Tenant** – In scenarios where external users are involved, the -[home tenant](https://docs.microsoft.com/en-us/azure/active-directory/external-identities/authentication-conditional-access) -is the one that owns the external user’s (e.g., guest) account. +Portions of this document are adapted from documents in Microsoft’s +[Microsoft 365](https://github.com/MicrosoftDocs/microsoft-365-docs/blob/public/LICENSE) +and +[Azure](https://github.com/MicrosoftDocs/azure-docs/blob/main/LICENSE) +GitHub repositories. The respective documents are subject to copyright +and are adapted under the terms of the Creative Commons Attribution 4.0 +International license. Source documents are linked throughout this +document. The United States government has adpted selections of these +documents to develop innovative and scalable configuration standards to +strengthen the security of widely used cloud-based software services. ## Assumptions -The agency has created emergency access accounts in Azure AD and -implemented strong security measures to protect the credentials of those -accounts. Once created, those accounts should be placed into a group -named “Emergency Users” or a similar name. Throughout Microsoft’s -instructions, this entity is referred to as “emergency access or -break-glass accounts.” Use the following Microsoft guidance to create -and manage emergency access accounts. - -[Manage emergency access accounts in Azure AD](https://docs.microsoft.com/en-us/azure/active-directory/roles/security-emergency-access) - The **License Requirements** sections of this document assume the organization is using an [M365 E3](https://www.microsoft.com/en-us/microsoft-365/compare-microsoft-365-enterprise-plans) or [G3](https://www.microsoft.com/en-us/microsoft-365/government) license level. Therefore, only licenses not included in E3/G3 are listed. -## Common guidance +Some of the policies in this baseline may link to Microsoft instruction pages which assume that an agency has created emergency access accounts in AAD and [implemented strong security measures](https://docs.microsoft.com/en-us/azure/active-directory/roles/security-emergency-access) to protect the credentials of those accounts. + +## Key Terminology + +The following are key terms and descriptions used in this document. -### Conditional Access Policies +**Hybrid Azure Active Directory (AD)** – This term denotes the scenario +when an organization has an on-premises AD domain that contains the +master user directory but federates access to the cloud Microsoft 365 +(M365) Azure AD tenant. -This section provides common guidance that should be applied when -implementing baseline instructions related to Azure AD Conditional -Access policies. +**Resource Tenant & Home Tenant** – In scenarios where [guest users are involved](https://docs.microsoft.com/en-us/azure/active-directory/external-identities/authentication-conditional-access) the resource tenant hosts the M365 target resources that the guest user is accessing. The home tenant is the one that hosts the guest user's identity. -As described in Microsoft’s instructions and examples related to -conditional access policies, CISA recommends setting a policy to -**Report-only** when it is created and then performing thorough hands-on -testing to ensure that there are no unintended consequences before -toggling the policy from **Report-only** to **On**. One tool that can -assist with running test simulations is the [What If tool](https://docs.microsoft.com/en-us/azure/active-directory/conditional-access/what-if-tool). -Microsoft also describes [Conditional Access insights and reporting features](https://docs.microsoft.com/en-us/azure/active-directory/conditional-access/howto-conditional-access-insights-reporting) -that can assist with testing. +**Home Tenant** – In scenarios where guest users are involved, the +[home tenant](https://docs.microsoft.com/en-us/azure/active-directory/external-identities/authentication-conditional-access) is the one that hosts the guest user’s identity. -### Azure AD Privileged Identity Management +## Highly Privileged Roles -Some of the guidance in this baseline document leverages specific -features of the Azure AD Privileged Identity Management (PIM) service to -demonstrate how to improve the security of highly privileged Azure AD -roles. The PIM service provides what is referred to as “Privileged -Access Management (PAM)” capabilities in industry. As an alternative to -Azure AD PIM, there are third-party vendors that provide products or -services with privileged access management capabilities that can be -leveraged if an agency chooses to do so. +This section provides a list of what CISA considers highly privileged [built-in roles in Azure Active Directory](https://learn.microsoft.com/en-us/azure/active-directory/roles/permissions-reference). This list is referenced in numerous baseline policies throughout this document. Agencies should consider this reference as a minimum list and can apply the respective baseline policies to additional AAD roles as necessary. -## Resources +- Global Administrator, Privileged Role Administrator, User Administrator, SharePoint Administrator, Exchange Administrator, Hybrid Identity Administrator, Application Administrator, Cloud Application Administrator. -License Compliance and Copyright +## Conditional Access Policies -Portions of this document are adapted from documents in Microsoft’s -[Microsoft 365](https://github.com/MicrosoftDocs/microsoft-365-docs/blob/public/LICENSE) -and -[Azure](https://github.com/MicrosoftDocs/azure-docs/blob/main/LICENSE) -GitHub repositories. The respective documents are subject to copyright -and are adapted under the terms of the Creative Commons Attribution 4.0 -International license. Source documents are linked throughout this -document. The United States government has adpted selections of these -documents to develop innovative and scalable configuration standards to -strengthen the security of widely used cloud-based software services. +Numerous policies in this baseline rely on AAD Conditional Access. This section provides guidance and tools when implementing baseline policies which rely on AAD Conditional Access. -# Baseline +As described in Microsoft’s literature related to conditional access policies, CISA recommends initially setting a policy to +**Report-only** when it is created and then performing thorough hands-on +testing to ensure that there are no unintended consequences before +toggling the policy from **Report-only** to **On**. The policy will only be enforced when it is set to **On**. One tool that can assist with running test simulations is the [What If tool](https://docs.microsoft.com/en-us/azure/active-directory/conditional-access/what-if-tool). Microsoft also describes [Conditional Access insights and reporting features](https://docs.microsoft.com/en-us/azure/active-directory/conditional-access/howto-conditional-access-insights-reporting) that can assist with testing. + +# Baseline Policies ## 1. Legacy Authentication -Block legacy authentication protocols using a conditional access policy. -Legacy authentication does not support multifactor authentication (MFA), -which is required to minimize the impact of user credential theft. +This section provides policies that help reduce security risks related to legacy authentication protocols that do not support MFA. ### Policies #### MS.AAD.1.1v1 Legacy authentication SHALL be blocked. -- _Rationale:_ TODO + +- _Rationale:_ The security risk of allowing legacy authentication protocols is that they do not support MFA. By blocking legacy protocols the impact of user credential theft is minimized. - _Last modified:_ June 2023 ### Resources @@ -104,636 +79,344 @@ Legacy authentication SHALL be blocked. ### Implementation +#### MS.AAD.1.1v1, instructions: + 1. Before blocking legacy authentication across the entire application - base, follow [these instructions](https://docs.microsoft.com/en-us/azure/active-directory/conditional-access/block-legacy-authentication#identify-legacy-authentication-use) - to determine if any of the agency’s existing applications are - presently using legacy authentication. This helps develop a plan to - address policy impacts. - -2. Follow [the instructions on this page](https://docs.microsoft.com/en-us/azure/active-directory/conditional-access/howto-conditional-access-policy-block-legacy) - to block legacy authentication. **Note:** The instructions suggest - using Report-only mode which will not block legacy authentication. - -## 2. High Risk Users - -Azure AD Identity Protection uses various signals to detect the risk -level for each user and determine if an account has likely been -compromised. Users who are determined to be high risk are to be blocked -from accessing the system via Conditional Access until an administrator -remediates their account. Once a respective conditional access policy -with a block is implemented, if a high-risk user attempts to login, the -user will receive an error message with instructions to contact the -administrator to re-enable their access. +base, follow [these instructions](https://docs.microsoft.com/en-us/azure/active-directory/conditional-access/block-legacy-authentication#identify-legacy-authentication-use) to determine if any of the agency’s existing applications are presently using legacy authentication. + +2. Follow [the instructions on this page](https://docs.microsoft.com/en-us/azure/active-directory/conditional-access/howto-conditional-access-policy-block-legacy) to create a conditional access policy that blocks legacy authentication. + +## 2. Risk Based Policies + +This section provides policies that help reduce security risks related to user accounts that may have been compromised. These policies use a combination of AAD Identity Protection and AAD Conditional Access. AAD Identity Protection uses numerous signals to detect the risk level for each user or sign-in to determine if an account may have been compromised. + +- _Additional mitigations to secure Workload Identities:_ Although not covered in this baseline due to the need for an additional non-standard license, Microsoft also provides support for mitigating risks related to workload identities (AAD applications or service principals). Agencies should strongly consider implementing this feature because workload identities present many of the same risks as interactive user access and are commonly used in modern systems. Follow [these instructions](https://learn.microsoft.com/en-us/azure/active-directory/conditional-access/workload-identity) to apply conditional access policies to workload identities. + +- _Note:_ The term "high risk" in the context of this section denotes the risk level applied by the AAD Identity Protection service to a user account or sign-in event. See the Resources section for a link to a detailed description of AAD Identity Protection risk and the factors that comprise it. ### Policies #### MS.AAD.2.1v1 Users detected as high risk SHALL be blocked. -- _Rationale:_ TODO + +- _Rationale:_ By blocking users determined as high risk, this prevents accounts that are likely compromised from accessing the tenant. - _Last modified:_ June 2023 +- _Note:_ Users who are determined to be high risk by AAD Identity Protection can be blocked from accessing the system via an AAD Conditional Access policy. A high risk user will be blocked until an administrator remediates their account. #### MS.AAD.2.2v1 A notification SHOULD be sent to the administrator when high-risk users are detected. -- _Rationale:_ TODO +- _Rationale:_ By alerting an administrator when high risk detections are made, the admin can respond to monitor the event and remediate the risk. This helps the organization proactively respond to cyber intrusions in action. - _Last modified:_ June 2023 -### Resources +#### MS.AAD.2.3v1 +Sign-ins detected as high risk SHALL be blocked. +- _Rationale:_ By blocking sign-ins determined as high risk, this prevents accounts that are likely compromised from accessing the tenant. +- _Last modified:_ June 2023 -- [Conditional Access: User risk-based Conditional Access](https://docs.microsoft.com/en-us/azure/active-directory/conditional-access/howto-conditional-access-policy-risk-user) +### Resources -- [User-linked detections](https://docs.microsoft.com/en-us/azure/active-directory/identity-protection/concept-identity-protection-risks#user-linked-detections) +- [What is risk?](https://docs.microsoft.com/en-us/azure/active-directory/identity-protection/concept-identity-protection-risks) - [Simulating risk detections in Identity Protection](https://docs.microsoft.com/en-us/azure/active-directory/identity-protection/howto-identity-protection-simulate-risk) - [User experiences with Azure AD Identity Protection](https://docs.microsoft.com/en-us/azure/active-directory/identity-protection/concept-identity-protection-user-experience) (Examples of how these policies are applied in practice) -- [Five steps to securing your identity infrastructure](https://docs.microsoft.com/en-us/azure/security/fundamentals/steps-secure-identity) - ### License Requirements - Requires an AAD P2 license ### Implementation -**Policy MS.AAD.2.1v1:** +#### MS.AAD.2.1v1, instructions: -1. To create the conditional access policy that implements the block - for users at the risk level of High, follow the instructions in the - [Enable with Conditional Access policy](https://docs.microsoft.com/en-us/azure/active-directory/conditional-access/howto-conditional-access-policy-risk-user#enable-with-conditional-access-policy) - section, but set the policy to block access as follows: +1. Create a conditional access policy that blocks users determined to be high risk by the Identity Protection service. -2. Under **Access Controls** -\> **Grant**, select **Block access**. +Follow the conditional access policy template below: -**Policy MS.AAD.2.2v1**: + Users > Include > All users -1. Follow the instructions in the [Configure users at risk detected alerts](https://docs.microsoft.com/en-us/azure/active-directory/identity-protection/howto-identity-protection-configure-notifications#configure-users-at-risk-detected-alerts) - section to configure Azure AD Identity Protection to email the - security operations team/administrator when a user account is - determined to be high risk so that they can review and respond to - threats. + Target resources > Cloud apps > All cloud apps -## 3. High Risk Sign-ins + Conditions > User risk > High + + Access controls > Grant > Block Access -Azure AD Identity Protection uses various signals to detect the risk -level for each user sign-in. Sign-ins detected as high risk are to be -blocked via Conditional Access. +#### MS.AAD.2.2v1, instructions: -### Policies -#### MS.AAD.3.1v1 -Sign-ins detected as high risk SHALL be blocked. -- _Rationale:_ TODO -- _Last modified:_ June 2023 +1. Follow the instructions in the [Configure users at risk detected alerts](https://docs.microsoft.com/en-us/azure/active-directory/identity-protection/howto-identity-protection-configure-notifications#configure-users-at-risk-detected-alerts) section to configure Azure AD Identity Protection to email a regularly monitored security mailbox when a user account is determined to be high risk. -### Resources +#### MS.AAD.2.3v1, instructions: -- [Conditional Access: Sign-in risk-based Conditional - Access](https://docs.microsoft.com/en-us/azure/active-directory/conditional-access/howto-conditional-access-policy-risk) +1. Create a conditional access policy that blocks sign-ins determined to be high risk by the Identity Protection service. -- [Sign-in - risk](https://docs.microsoft.com/en-us/azure/active-directory/identity-protection/concept-identity-protection-risks#sign-in-risk) +Follow the conditional access policy template below: -- [Simulating risk detections in Identity - Protection](https://docs.microsoft.com/en-us/azure/active-directory/identity-protection/howto-identity-protection-simulate-risk) + Users > Include > All users -- [User experiences with Azure AD Identity - Protection](https://docs.microsoft.com/en-us/azure/active-directory/identity-protection/concept-identity-protection-user-experience) - (Examples of how these policies are applied in practice) + Target resources > Cloud apps > All cloud apps -### License Requirements + Conditions > Sign-in risk > High + + Access controls > Grant > Block Access -- Requires an AAD P2 license +## 3. Strong Authentication and a Secure Registration Process -### Implementation +This section provides policies that help reduce security risks related to user authentication and registration. -To create the conditional access policy that implements the block for -sign-ins at the risk level of **High**, follow the instructions in the -[Enable with Conditional Access -policy](https://docs.microsoft.com/en-us/azure/active-directory/conditional-access/howto-conditional-access-policy-risk#enable-with-conditional-access-policy) -section, but set the risk level to **High** and block access. - -1. Under **Select the sign-in risk level this policy will apply to**, - select **High.** - -2. Under **Access Controls** -\> **Grant**, select **Block access.** - -**Note**: If after implementing this, it is observed that numerous -legitimate user sign-ins are consistently being blocked due to their -location being interpreted as suspicious and this creates an operational -burden on the agency, then [a Trusted Location can be -configured](https://docs.microsoft.com/en-us/azure/active-directory/conditional-access/location-condition#ip-address-ranges) -in the Conditional Access blade for each of the legitimate sign-in -locations. Azure AD Identity Protection considers the Trusted Location -data when it calculates sign-in risk, and this may help to prevent users -signing in from legitimate locations from being flagged as high risk. - -## 4. Phishing-Resistant Multifactor Authentication - -Phishing-resistant multifactor authentication protects against -sophisticated phishing attacks. Recognizing the significant risk these -attack present, the Office of Management and Budget (OMB), requires -federal agencies to [implement phishing-resistant -authentication](https://www.whitehouse.gov/wp-content/uploads/2022/01/M-22-09.pdf). - -However, phishing-resistant MFA may not always be immediately available, -especially on mobile devices. Where phishing-resistant MFA is not yet -available, organization should adopt an MFA method from the list below. -Organizations must upgrade to a phishing-resistant MFA method as soon as -possible to become compliant with this policy and address the critical -security threat posed by modern phishing attacks. - -**Note**: Figure adapted from [MS Build -Page](https://docs.microsoft.com/en-us/azure/active-directory/authentication/concept-authentication-methods) -article (12/29/2021). - -Weak MFA (SMS/Voice) Stronger MFA (Push Notifications, Software OTP, Hardware Token OTP) Strongest MFA (FIDO2, PIV, Windows Hello) -Figure 1: Options for Weak MFA, Stronger MFA Options, and Strongest MFA +Figure 1: Depiction of MFA methods from weakest to strongest. _Adapted from [MS Build Page](https://docs.microsoft.com/en-us/azure/active-directory/authentication/concept-authentication-methods)_ ### Policies -#### MS.AAD.4.1v1 -MFA SHALL be required for all users. -- _Rationale:_ TODO -- _Last modified:_ June 2023 - -#### MS.AAD.4.2v1 -Phishing-resistant MFA SHALL be used for all users. +#### MS.AAD.3.1v1 +Phishing-resistant MFA SHALL be enforced for all users. - - Phishing-resistant methods: +**Preferred phishing-resistant methods** - - Federal PIV card (Azure AD Certificate-Based authentication - \[CBA\]) +The methods **AAD Certificate-Based Authentication (CBA)**, **FIDO2 Security Key** and **Windows Hello for Business** are the recommended options since they offer forms of MFA with the least potential weaknesses. AAD CBA supports Federal PIV cards when they authenticate directly to Azure AD and is likely the most appropriate option for agencies to authenticate their users. - - FIDO2 Security Key +**Non-preferred phishing-resistant methods** - - Windows Hello for Business +The option **Federal PIV card (federated from agency on-premises Active Directory Federation Services or other identity provider)**, although technically phishing-resistant presents significant risks if the on-premises authentication infrastructure (e.g. ADFS) is compromised. Therefore federated PIV is not a preferred option and agencies should migrate to the options listed in the preferred section above. If an agency does use an on-premises PIV authentication and federate to AAD, reference the [guidance at this link](https://playbooks.idmanagement.gov/piv/network/group/) to enforce PIV logon via AD group policy. - - Federal Personal Identity Verification (PIV) card (Federated from - agency Active Directory or other identity provider) -- _Rationale:_ TODO +- _Rationale:_ The security risk of allowing weaker forms of MFA is that they do not protect against sophisticated phishing attacks. By enforcing methods which are resistant to phishing those risks are minimized. - _Last modified:_ June 2023 -#### MS.AAD.4.3v1 -If phishing-resistant MFA cannot be used, an MFA method from the list - below SHALL be used in the interim: - - - Microsoft Authenticator (Push Notifications) - - - Microsoft Authenticator (Phone Sign-in) (Also referred to as - Passwordless Sign-in) - - - When using Microsoft Authenticator: - - - Number Matching SHALL be enabled. - - - Additional Context SHALL be enabled. - - - Software Tokens One-Time Password (OTP) – This option is commonly implemented using mobile phone authenticator apps +#### MS.AAD.3.2v1 +If Phishing-resistant MFA has not been enforced yet, then an alternative MFA method SHALL be enforced for all users. - - Hardware tokens OTP -- _Rationale:_ TODO +- _Rationale:_ This is a backup security policy to help protect the tenant in the event that phishing-resistant MFA has not been enforced yet. This policy requires that MFA is enforced and thus reduces the risks of single form authentication. - _Last modified:_ June 2023 +- _Note:_ If a conditional access policy has been created that enforces phishing-resistant MFA, then this policy is not necessary. This policy does not dictate the specific MFA method. -#### MS.AAD.4.4v1 -SMS or Voice as the MFA method SHALL NOT be used. -- _Rationale:_ TODO -- _Last modified:_ June 2023 - -### Resources - -- [What authentication and verification methods are available in Azure - Active - Directory?](https://docs.microsoft.com/en-us/azure/active-directory/authentication/concept-authentication-methods) - -- [Use number matching in multifactor authentication (MFA) notifications - (Preview) - Azure Active Directory - Microsoft Entra \| Microsoft - Docs](https://docs.microsoft.com/en-us/azure/active-directory/authentication/how-to-mfa-number-match#enable-number-matching-in-the-portal) +#### MS.AAD.3.3v1 +If Phishing-resistant MFA has not been enforced yet and Microsoft Authenticator is enabled, it SHALL be configured to show login context information. -- [Use additional context in Microsoft Authenticator notifications - (Preview) - Azure Active Directory - Microsoft Entra \| Microsoft - Docs](https://docs.microsoft.com/en-us/azure/active-directory/authentication/how-to-mfa-additional-context#enable-additional-context-in-the-portal) - -- [M-22-09 Federal Zero Trust - Strategy](https://www.whitehouse.gov/wp-content/uploads/2022/01/M-22-09.pdf) - -### License Requirements +- _Rationale:_ This is a backup security policy to help protect the tenant in the event that phishing-resistant MFA has not been enforced yet and Microsoft Authenticator is being used. This policy helps improve the security of Microsoft Authenticator by showing the user context information which helps reduce MFA phishing compromises. +- _Last modified:_ June 2023 -- N/A +#### MS.AAD.3.4v1 +The Authentication Methods Manage Migration feature SHALL be set to Migration Complete. -### Implementation +- _Rationale:_ By configuring the Manage Migration feature to Migration Complete, we ensure that the tenant has disabled the legacy authentication methods screen. The MFA and SSPR authentication methods are both managed from a central admin page thereby reducing administrative complexity and +reducing the chances of security misconfigurations. +- _Last modified:_ June 2023 -**Policy \#1:** - -1. Follow [these - instructions](https://docs.microsoft.com/en-us/azure/active-directory/conditional-access/howto-conditional-access-policy-all-users-mfa) - to create a conditional access policy that requires all users to - authenticate with MFA. - -**Policy \#2:** - -Use the following instructions to configure a phishing-resistant MFA -method for users with highly privileged roles. If the agency is -configuring a phishing-resistant MFA method for all users, then the -instructions in this section also apply, but set the **Target** to **All -Users** instead of a specific group in the respective configuration -screens. - -CISA recommends placing highly privileged users into an Azure AD group -named “Highly Privileged Admins” or an equivalent and then referencing -the group in the MFA configuration. Newly created, highly privileged -users should be added to the group so they can register a -phishing-resistant method. CISA does not recommend assigning MFA methods -directly to individual users. - -Select one of the following phishing-resistant MFA methods to configure: - -**FIDO2 Security Key** - -1. Follow the instructions at [this - link](https://docs.microsoft.com/en-us/azure/active-directory/authentication/howto-authentication-passwordless-security-key#enable-fido2-security-key-method) - to configure FIDO2. -2. For **Enable**, select **Yes.** -3. For **Target**, select the **Highly Privileged Admins** group or an - equivalent. - -**Certificate Based Authentication (CBA)** - - -1. Follow the instructions at [this - link](https://docs.microsoft.com/en-us/azure/active-directory/authentication/how-to-certificate-based-authentication#steps-to-configure-and-test-azure-ad-cba) - to configure CBA. -2. On the tenant, in the instructions section named [**Enable CBA on - the - tenant**](https://docs.microsoft.com/en-us/azure/active-directory/authentication/how-to-certificate-based-authentication#step-4-enable-cba-on-the-tenant) - , under **Target**, select the **Highly Privileged Admins** group or - an equivalent. - -**Windows Hello for Business** - -1. Follow the instructions at [this - link](https://docs.microsoft.com/en-us/windows/security/identity-protection/hello-for-business/hello-deployment-guide) - to configure Windows Hello for Business. - -**Policy \#3:** - -If the agency is implementing a phishing-resistant MFA method for all -users, follow the instructions in the previous section. Otherwise use -the following instructions to configure a non-phishing resistant MFA -method for users that are not in highly privileged roles. - -**Microsoft Authenticator (Phone Sign-in) (Also referred to as -Passwordless Sign-in) or Microsoft Authenticator (Push Notifications)** - -1. In the Azure Portal navigate to **Azure Active Directory.** -2. Select **Security.** -3. Select **Manage** -\> **MFA.** -4. Under **Configure,** select **Additional cloud-based MFA settings.** -5. Under **verification options**, select **Notification through mobile - app.** -6. If desired, to enforce Microsoft Authenticator app usage and disable - third party authenticator apps usage, make sure that **Verification - code from mobile app** or **hardware token** is not selected. -7. Click **Save.** -8. Go back to the **Azure Active Directory** home tab and select - **Security**. -9. Select **Authentication Methods**. -10. In the **Policies** window, select **Microsoft Authenticator**. -11. For **Enable**, select **Yes**. -12. For **Target**, select **All users**. -13. In the row for the **All users**, click the … -\> **Configure**. -14. If configuring Phone Sign-in (aka Passwordless Sign-in), for - **Authentication mode**, select **Passwordless**. If configuring - Push Notifications, for **Authentication mode**, select **Push**. If - configuring the usage of both, for **Authentication mode**, select - **Any**. -15. For **Require number matching**, select **Enabled**. -16. For **Show additional context in notifications**, select - **Enabled**. -17. Select **Done**. -18. Click **Save**. - -**Software Tokens OTP or Hardware Tokens OTP** - -1. In the **Azure Portal**, navigate to **Azure Active Directory**. -2. Select **Security**. -3. Select **Manage** -\> **MFA**. -4. Under **Configure**, select **Additional cloud-based MFA settings**. -5. Under **verification options**, select **Verification code from - mobile app** or **hardware token**. -6. If configuring Hardware Tokens OTP, follow the additional steps at - [this link](https://docs.microsoft.com/en-us/azure/active-directory/authentication/concept-authentication-oath-tokens#oath-hardware-tokens-preview) - when provisioning a user. - -**Policy \#4:** - -1. In the **Azure Portal,** navigate to **Azure Active Directory**. -2. Select **Security**. -3. Select **Manage** -\> **MFA**. -4. Under **Configure**, select **Additional cloud-based MFA settings**. -5. Under **verification options**, make sure that **Text message to - phone** and **Call to phone** are **disabled**. - -## 5. Azure AD logs - -Configure Azure AD to send critical logs to the agency’s centralized -SIEM and to CISA’s central analysis system so that they can be audited -and queried. Configure Azure AD to send logs to a storage account and -retain them for when incident response is needed. +#### MS.AAD.3.5v1 +The authentication methods SMS, Voice Call and Email OTP SHALL be disabled. -### Policies -#### MS.AAD.5.1v1 -The following critical logs SHALL be sent at a minimum: AuditLogs, SignInLogs, RiskyUsers, UserRiskEvents, NonInteractiveUserSignInLogs, ServicePrincipalSignInLogs, ADFSSignInLogs, RiskyServicePrincipals, ServicePrincipalRiskEvents. -- _Rationale:_ TODO +- _Rationale:_ This policy helps reduce the possibility for users to register and authenticate with the weakest authenticators. Thus users are forced to use stronger MFA methods. - _Last modified:_ June 2023 +- _Note:_ This policy is only applicable if the tenant has their Manage Migration feature set to Migration Complete because that is required to manage the respective configuration options from the combined MFA / SSPR authentication methods page. - +#### MS.AAD.3.6v1 +Phishing-resistant MFA SHALL be required for Highly Privileged Roles. -#### MS.AAD.5.2v1 -If managed identities are used for Azure resources, logs SHALL include the ManagedIdentitySignInLogs log type. -- _Rationale:_ TODO +- _Rationale:_ This is a backup security policy to help protect privileged access to the tenant in the event that the conditional access policy which requires MFA for all users is disabled or misconfigured. - _Last modified:_ June 2023 +- _Note:_ Refer to the Highly Privileged Roles section at the top of this document for a reference list of roles considered highly privileged. -#### MS.AAD.5.3v1 -If the Azure AD Provisioning Service is used to provision users to SaaS apps or other systems, also include the ProvisioningLogs log type. -- _Rationale:_ TODO +#### MS.AAD.3.7v1 +Managed devices SHOULD be required for authentication. + +- _Rationale:_ The security risk of an adversary authenticating to the tenant from their own device is reduced by requiring a managed device to authenticate. Managed devices are under the provisioning and control of the agency. OMB-22-09 specifically states "When authorizing users to access resources, agencies must consider at least one device-level signal alongside identity information about the authenticated user". - _Last modified:_ June 2023 - +#### MS.AAD.3.8v1 +Managed Devices SHOULD be required to register MFA. -#### MS.AAD.5.4v1 -The logs SHALL be sent to the agency's SOC for monitoring. -- _Rationale:_ TODO +- _Rationale:_ The security risk of an adversary using stolen user credentials and then registering their own MFA devices to access the tenant is reduced by requiring a managed device to perform registration actions. Thus the adversary cannot perform the registration from their own unmanaged device. Managed devices are under the provisioning and control of the agency. - _Last modified:_ June 2023 ### Resources -- [Everything you wanted to know about Security and Audit Logging in - Office - 365](https://thecloudtechnologist.com/2021/10/15/everything-you-wanted-to-know-about-security-and-audit-logging-in-office-365/) - -- [Sign-in logs in Azure Active Directory - - preview](https://docs.microsoft.com/en-us/azure/active-directory/reports-monitoring/concept-all-sign-ins) - -- [National Cybersecurity Protection System-Cloud Interface Reference - Architecture Volume - 1](https://www.cisa.gov/sites/default/files/publications/NCPS%20Cloud%20Interface%20RA%20Volume%20One%20%282021-05-14%29.pdf) +- [What authentication and verification methods are available in Azure Active Directory?](https://docs.microsoft.com/en-us/azure/active-directory/authentication/concept-authentication-methods) -- [National Cybersecurity Protection System - Cloud Interface Reference - Architecture Volume - 2](https://www.cisa.gov/sites/default/files/publications/NCPS%20Cloud%20Interface%20RA%20Volume%20Two%202021-06-11%20%28508%20COMPLIANT%29.pdf) - -### License Requirements - -- N/A +- [How to use additional context in Microsoft Authenticator notifications Authentication methods policy](https://docs.microsoft.com/en-us/azure/active-directory/authentication/how-to-mfa-additional-context#enable-additional-context-in-the-portal) -### Implementation - -[Follow these instructions](https://docs.microsoft.com/en-us/azure/active-directory/reports-monitoring/quickstart-azure-monitor-route-logs-to-storage-account) -to configure sending the logs to a storage account: - -1. From the **Diagnostic settings** page, click **Add diagnostic** - setting. - -2. Select the specific logs mentioned in the previous policy section. - -3. Under **Destination Details,** select the **Archive to a storage - account** check box and select the storage account that was - specifically created to host security logs. - -4. In the **Retention** field enter “365” days. - -## 6. Register Third-Party Applications - -Ensure that only administrators can register third-party applications -that can access the tenant. +- [M-22-09 Federal Zero Trust Strategy](https://www.whitehouse.gov/wp-content/uploads/2022/01/M-22-09.pdf) -### Policies -#### MS.AAD.6.1v1 -Only administrators SHALL be allowed to register third-party applications. -- _Rationale:_ TODO -- _Last modified:_ June 2023 +- [Configure hybrid Azure AD join](https://docs.microsoft.com/en-us/azure/active-directory/devices/howto-hybrid-azure-ad-join) -### Resources +- [Azure AD joined devices](https://docs.microsoft.com/en-us/azure/active-directory/devices/concept-azure-ad-join) -- [Restrict Application Registration for Non-Privileged - Users](https://www.trendmicro.com/cloudoneconformity/knowledge-base/azure/ActiveDirectory/users-can-register-applications.html) +- [Set up enrollment for Windows devices (for Intune)](https://docs.microsoft.com/en-us/mem/intune/enrollment/windows-enroll) ### License Requirements -- N/A +- Microsoft Intune (if implementing the authentication policies for the device to be managed). ### Implementation -1. In the **Azure Portal**, navigate to **Azure Active Directory.** +#### MS.AAD.3.1v1, instructions: - +1. Create a conditional access policy that enforces phishing-resistant MFA for all users. -2. Under **Manage**, select **Users**. +Follow the conditional access policy template below: -3. Select **User settings**. + Users > Include > All users -4. Under **App Registrations** -\> **Users can register applications**, - select **No.** + Target resources > Cloud apps > All cloud apps + + Access controls > Grant > Grant Access > Require authentication strength > Phishing-resistant MFA -5. Click **Save**. +#### MS.AAD.3.2v1, instructions: -## 7. Consenting to Third-Party Applications +1. If Phishing-resistant MFA has not been enforced for all users yet, create a conditional access policy that enforces MFA but does not dictate the MFA method. -Ensure that only administrators can consent to third-party applications -and only administrators can control which permissions are granted. An -admin consent workflow can be configured in Azure AD, otherwise users -will be blocked when they try to access an application that requires -permissions to access organizational data. Develop a process for -approving and managing third-party applications. +Follow the conditional access policy template below. -### Policies -#### MS.AAD.7.1v1 -Only administrators SHALL be allowed to consent to third-party - applications. -- _Rationale:_ TODO -- _Last modified:_ June 2023 + Users > Include > All users -#### MS.AAD.7.2v1 -An admin consent workflow SHALL be configured. -- _Rationale:_ TODO -- _Last modified:_ June 2023 + Target resources > Cloud apps > All cloud apps + + Access controls > Grant > Grant Access > Require multifactor authentication -#### MS.AAD.7.3v1 -Group owners SHALL NOT be allowed to consent to third-party applications. -- _Rationale:_ TODO -- _Last modified:_ June 2023 +#### MS.AAD.3.3v1, instructions: +If Phishing-resistant MFA has not been deployed yet and Microsoft Authenticator is in use, configure Authenticator to display context information to users when they login. -### Resources +1. In **Azure Active Directory**, click **Security > Authentication methods > Microsoft Authenticator**. +2. Click the **Configure** tab. +3. For **Allow use of Microsoft Authenticator OTP** select *No*. +4. Under **Show application name in push and passwordless notifications** select **Status > Enabled** and **Target > Include > All users**. +5. Under **Show geographic location in push and passwordless notifications** select **Status > Enabled** and **Target > Include > All users**. +6. Select **Save** -- [Enforce Administrators to Provide Consent for Apps Before - Use](https://www.trendmicro.com/cloudoneconformity/knowledge-base/azure/ActiveDirectory/users-can-consent-to-apps-accessing-company-data-on-their-behalf.html) -- [Configure the admin consent - workflow](https://docs.microsoft.com/en-us/azure/active-directory/manage-apps/configure-admin-consent-workflow) +#### MS.AAD.3.4v1, instructions: +1. Go through the process of migrating from the legacy AAD MFA and Self-Service Password Reset (SSPR) administration pages to the new unified Authentication Methods policy page. Follow [these instructions ](https://learn.microsoft.com/en-us/azure/active-directory/authentication/how-to-authentication-methods-manage). +2. Once ready to finish the migration, follow [these instructions ](https://learn.microsoft.com/en-us/azure/active-directory/authentication/how-to-authentication-methods-manage#finish-the-migration) and set the **Manage Migration** option to **Migration Complete**. -### License Requirements +#### MS.AAD.3.5v1, instructions: +1. In **Azure Active Directory**, click **Security > Authentication methods** +2. Click on the **SMS**, **Voice Call**, and **Email OTP** authentication methods and disable each of them. Their statuses should be **Enabled > No** on the **Authentication methods > Policies** page. -- N/A +#### MS.AAD.3.6v1, instructions: -### Implementation +1. Create a conditional access policy that enforces phishing-resistant MFA for highly privileged roles. -1. In the **Azure Portal**, navigate to **Azure Active Directory.** +Follow the conditional access policy template below: - + Users > Include > Select users and groups > Directory roles > select each of the roles listed in the Highly Privileged Roles section at the top of this document -2. Create a new Azure AD Group that contains admin users responsible - for reviewing and adjudicating app requests. + Target resources > Cloud apps > All cloud apps + + Access controls > Grant > Grant Access > Require authentication strength > Phishing-resistant MFA -3. Under **Manage**, select **Enterprise Applications.** +#### MS.AAD.3.7v1, instructions: -4. Under **Security**, select **Consent and permissions.** +1. Create a conditional access policy that requires a user's device to be +either hybrid Azure AD joined or compliant during authentication. -5. Under **User consent for applications**, select **Do not allow user - consent.** +Follow the conditional access policy template below. -6. Under **Group owner consent for apps accessing data**, select **Do - not allow group owner consent.** + Users > Include > All users -7. In the menu, navigate back to **Enterprise Applications**. + Target resources > Cloud apps > All cloud apps + + Access controls > Grant > Grant Access > "Require device to be marked as compliant" and "Require Hybrid Azure AD joined device" > Require one of the selected controls -8. Under **Manage**, select **User Settings**. +#### MS.AAD.3.8v1, instructions: -9. Under **Admin consent requests** -\> **Users can request admin - consent to apps they are unable to consent to**, select **Yes.** +1. Create a conditional access policy that requires a user to be on a managed device when registering for MFA. -10. Under **Who can review admin consent requests**, select the group - created in step two that is responsible for reviewing and - adjudicating app requests. +Follow the conditional access policy template below. -11. Click **Save** + Users > Include > All users -## 8. Passwords + Target resources > User actions > Register security information + + Access controls > Grant > Grant Access > "Require device to be marked as compliant" and "Require Hybrid Azure AD joined device" > Require one of the selected controls -Ensure that user passwords do not expire. Both the National Institute of -Standards and Technology (NIST) and Microsoft emphasize MFA because they -indicate that mandated password changes make user accounts less secure. +## 4. Centralized Log Collection + +This section provides policies that help reduce security risks related to the lack of security logs which hampers security visibility. ### Policies -#### MS.AAD.8.1v1 -User passwords SHALL NOT expire. -- _Rationale:_ TODO +#### MS.AAD.4.1v1 +Security logs SHALL be sent to the agency's Security Operations Center for monitoring. + +- _Rationale:_ The security risk of not having visibility into cyber attacks is reduced by collecting the logs into the agency's centralized security detection infrastructure. Thus security events can be audited, queried and available for incident response. - _Last modified:_ June 2023 +- _Scope:_ The following logs (configured in Azure AD diagnostic settings), are required: AuditLogs, SignInLogs, RiskyUsers, UserRiskEvents, NonInteractiveUserSignInLogs, ServicePrincipalSignInLogs, ADFSSignInLogs, RiskyServicePrincipals, ServicePrincipalRiskEvents, EnrichedOffice365AuditLogs, MicrosoftGraphActivityLogs. If managed identities are used for Azure resources, also send the ManagedIdentitySignInLogs log type. If the Azure AD Provisioning Service is used to provision users to SaaS apps or other systems, also send the ProvisioningLogs log type. +- _Federal Agencies:_ It is also recommended to send the logs to the CISA CLAW system so that agencies can benefit from the security detection capabilities offered there. Contact CISA to request integration instructions. ### Resources -- [Password policy recommendations - Microsoft 365 admin \| Microsoft - Docs](https://docs.microsoft.com/en-us/microsoft-365/admin/misc/password-policy-recommendations?view=o365-worldwide#password-expiration-requirements-for-users) +- [Everything you wanted to know about Security and Audit Logging in + Office 365](https://thecloudtechnologist.com/2021/10/15/everything-you-wanted-to-know-about-security-and-audit-logging-in-office-365/) -- [Eliminate bad passwords using Azure Active Directory Password - Protection](https://docs.microsoft.com/en-us/azure/active-directory/authentication/concept-password-ban-bad) +- [Sign-in logs in Azure Active Directory - + preview](https://docs.microsoft.com/en-us/azure/active-directory/reports-monitoring/concept-all-sign-ins) -- [NIST Special Publication 800-63B - Digital Identity - Guidelines](https://pages.nist.gov/800-63-3/sp800-63b.html) +- [National Cybersecurity Protection System-Cloud Interface Reference + Architecture Volume + 1](https://www.cisa.gov/sites/default/files/publications/NCPS%20Cloud%20Interface%20RA%20Volume%20One%20%282021-05-14%29.pdf) ### License Requirements -- N/A +- An Azure subscription is required to send the logs to an external system such as the agency's SIEM. ### Implementation -[Follow the instructions at this -link](https://docs.microsoft.com/en-us/microsoft-365/admin/manage/set-password-expiration-policy?view=o365-worldwide#set-password-expiration-policy) -to configure the password expiration policy. - -## 9. Session Length - -To reduce the risk of credential theft during user sessions, configure -the sign-in frequency to a limited period of time. - -### Policies -#### MS.AAD.9.1v1 -Sign-in frequency SHALL be configured to 12 hours. -- _Rationale:_ TODO -- _Last modified:_ June 2023 - -### Resources - -- [Configure authentication session management with Conditional - Access](https://docs.microsoft.com/en-us/azure/active-directory/conditional-access/howto-conditional-access-session-lifetime) - -- [NIST Special Publication 800-63B - Digital Identity - Guidelines](https://pages.nist.gov/800-63-3/sp800-63b.html) - -### License Requirements - -- N/A +#### MS.AAD.4.1v1, instructions: -### Implementation +[Follow these instructions](https://docs.microsoft.com/en-us/azure/active-directory/reports-monitoring/quickstart-azure-monitor-route-logs-to-storage-account) +to configure sending the logs to a storage account: -[Follow the instructions at this -link](https://docs.microsoft.com/en-us/azure/active-directory/conditional-access/howto-conditional-access-session-lifetime#policy-1-sign-in-frequency-control) -to implement the conditional access policy that configures the sign-in -frequency, +1. From the **Diagnostic settings** page, click **Add diagnostic** + setting. -1. Set the **Users** or **workload identities** to include **All - users.** +2. Select the specific logs mentioned in the previous policy section. -2. Set the **Cloud apps or actions** to include **All cloud apps.** +3. Under **Destination Details,** select the **Archive to a storage + account** check box and select the storage account that was + specifically created to host security logs. -3. Set the **Access Controls** -\> **Session** -\> **Sign-in - frequency** to a value of “12 hours”. +4. In the **Retention** field enter “365” days. -## 10. Browser Sessions +## 5. Application Registration and Consent -To reduce the risk of credential theft during user sessions, disallow -persistent browser sessions. +This section provides policies that help reduce security risks related to non privileged users adding malicious applications or service principals to the tenant. Malicious applications can perform many of the same operations as interactive users and can access data "on behalf of" compromised users. These policies apply to custom-developed applications and applications published by third-party vendors. ### Policies -#### MS.AAD.10.1v1 -Browser sessions SHALL not be persistent. -- _Rationale:_ TODO -- _Last modified:_ June 2023 - -### Resources - -- [Configure authentication session management with Conditional Access](https://docs.microsoft.com/en-us/azure/active-directory/conditional-access/howto-conditional-access-session-lifetime) - -- [NIST Special Publication 800-63B - Digital Identity Guidelines](https://pages.nist.gov/800-63-3/sp800-63b.html) - -### License Requirements - -- N/A - -### Implementation +#### MS.AAD.5.1v1 +Only administrators SHALL be allowed to register applications. -[Follow the instructions at this link](https://docs.microsoft.com/en-us/azure/active-directory/conditional-access/howto-conditional-access-session-lifetime#policy-2-persistent-browser-session) -to implement the conditional access policy that prevents persistent -browser sessions. +- _Rationale:_ Application access to the tenant presents a hightened security risk compared to interactive user access because applications are typically not subject to critical security protections such as MFA policies and others. Ensuring that only specific privileged users can register applications reduces the risks of unauthorized users installing malicious applications into the tenant. +- _Last modified:_ June 2023 -1. Set the **Users or workload identities** to **include All users.** +#### MS.AAD.5.2v1 +Only administrators SHALL be allowed to consent to applications. -2. Set the **Cloud apps or actions** to include **All cloud apps.** +- _Rationale:_ Ensuring that only specific privileged users can consent to applications reduces the risks of users giving insecure applications access to their data via [consent grant attacks](https://learn.microsoft.com/en-us/microsoft-365/security/office-365-security/detect-and-remediate-illicit-consent-grants?view=o365-worldwide). +- _Last modified:_ June 2023 -3. Set the **Access Controls -**\> **Session** -\> **Persistent browser - session** to **Never persistent.** +#### MS.AAD.5.3v1 +An admin consent workflow SHALL be configured for applications. -## 11. Global Administrators +- _Rationale:_ Configuring an admin consent workflow helps support the risk reduction of the previous policy by setting up a process for users to securely request access to applications necessary for business purposes. Administrators get the opportunity to review the permissions requested by new applications and approve or deny access based on a risk assessment. +- _Last modified:_ June 2023 -Global Administrator is the highest privileged role in Azure AD because -it provides unfettered access to the tenant. Therefore, if a user’s -credential with these permissions were to be compromised, it would -present grave risks to the security of the tenant. Limit the number of -users that are assigned the role of Global Administrator. Assign users -to finer-grained administrative roles that they need to perform their -duties instead of being assigned the Global Administrator role. +#### MS.AAD.5.4v1 +Group owners SHALL NOT be allowed to consent to applications. -### Policies -#### MS.AAD.11.1v1 -A minimum of two users and a maximum of four users SHALL be provisioned with the Global Administrator role. -- _Rationale:_ TODO +- _Rationale:_ In M365 group and team owners can consent to applications accessing data in the tenant, thus by preventing this and requiring consent requests to go through an approval consent workflow, the risks of exposure to malicious applications is reduced. - _Last modified:_ June 2023 ### Resources -- [Best practices for Azure AD roles (Limit number of Global - Administrators to less than 5)](https://docs.microsoft.com/en-us/azure/active-directory/roles/best-practices#5-limit-the-number-of-global-administrators-to-less-than-5) +- [Restrict Application Registration for Non-Privileged + Users](https://www.trendmicro.com/cloudoneconformity/knowledge-base/azure/ActiveDirectory/users-can-register-applications.html) -- [About admin roles](https://docs.microsoft.com/en-us/microsoft-365/admin/add-users/about-admin-roles?view=o365-worldwide) +- [Enforce Administrators to Provide Consent for Apps Before + Use](https://www.trendmicro.com/cloudoneconformity/knowledge-base/azure/ActiveDirectory/users-can-consent-to-apps-accessing-company-data-on-their-behalf.html) + +- [Configure the admin consent + workflow](https://docs.microsoft.com/en-us/azure/active-directory/manage-apps/configure-admin-consent-workflow) ### License Requirements @@ -741,132 +424,72 @@ A minimum of two users and a maximum of four users SHALL be provisioned with the ### Implementation -**Policy bullet \#1:** - -1. In the **Azure Portal**, navigate to **Azure Active Directory.** +#### MS.AAD.5.1v1, instructions: - +1. In **Azure Active Directory**, under **Manage**, select **Users**. -2. Select **Roles and administrators.** +2. Select **User settings**. -3. Select the **Global administrator role.** +3. For **Users can register applications**, select **No.** -4. Under **Manage**, select **Assignments.** +4. Click **Save**. -5. Validate that between two to four users are listed. +#### MS.AAD.5.2v1, instructions: - +1. In **Azure Active Directory** under **Manage**, select **Enterprise Applications.** -6. For those who have Azure AD PIM, they will need to check both the - **Eligible assignments** and **Active assignments** tabs. There - should be a total of two to four users across both of these tabs - (not individually). +2. Under **Security**, select **Consent and permissions.** -7. If any groups are listed, need to check how many users are members - of each group and include that in the total count. +3. Under **User consent for applications**, select **Do not allow user consent.** -**Policy bullet \#2:** +4. Click **Save**. -1. In the **Azure Portal**, navigate to **Azure Active Directory.** +#### MS.AAD.5.3v1, instructions: - +1. In **Azure Active Directory** create a new Azure AD Group that contains admin users responsible for reviewing and adjudicating application consent requests. Users in this group will be notified when users request consent for new applications. -2. Select **Security.** +2. Then in **Azure Active Directory** under **Manage**, select **Enterprise Applications.** -3. Under **Manage**, select **Identity Secure Score.** +3. Select **Admin consent settings**. -4. Click the **Columns** button and ensure that all the available - columns are selected to display and click **Apply.** +4. Under **Admin consent requests** > **Users can request admin consent to apps they are unable to consent to**, select **Yes**. -5. Review the score for the action named **Use limited administrative - roles.** +5. Under **Who can review admin consent requests**, select the group created in step 1 that is responsible for reviewing and adjudicating app requests. -6. Ensure that the maximum score was achieved, and that the status is - **Completed.** +6. Click **Save**. -7. If the maximum score was not achieved, click the improvement action - and Microsoft provides a pop-up page with detailed instructions on - how to address the weakness. In short, to address the weakness, - assign users to finer grained roles (e.g., SharePoint Administrator, - Exchange Administrator) instead of Global Administrator. Only the - minimum number of users necessary should be assigned to Global - Administrator. Once the roles are reassigned according to the - guidance, check the score again after 48 hours to ensure compliance. - -## 12. Highly Privileged User Accounts - -Assign users that need to perform highly privileged tasks to cloud-only -Azure AD accounts to minimize the collateral damage of an on-premises -identity compromise.[^1] - -### Policies -#### MS.AAD.12.1v1 -Users that need to be assigned to highly privileged Azure AD roles SHALL be provisioned cloud-only accounts that are separate from the on-premises directory or other federated identity providers. -- _Rationale:_ TODO -- _Last modified:_ June 2023 +#### MS.AAD.5.4v1, instructions: -#### MS.AAD.12.2v1 -The following built-in Azure AD roles are considered highly privileged at a minimum. Additional built-in roles that are considered highly privileged in the agency's environment can be added to this list: +1. In **Azure Active Directory** under **Manage**, select **Enterprise Applications.** - - Global Administrator +2. Under **Security**, select **Consent and permissions.** - - Privileged Role Administrator +3. Under **Group owner consent for apps accessing data**, select **Do not allow group owner consent.** - - User Administrator +4. Click **Save**. - - SharePoint Administrator +## 6. Passwords - - Exchange Administrator +This section provides policies that help reduce security risks associated with legacy password practices that are no longer supported by research. - - Hybrid Identity Administrator +### Policies +#### MS.AAD.6.1v1 +User passwords SHALL NOT expire. - - Application Administrator +- _Rationale:_ At a minimum, NIST, OMB and Microsoft have published guidance indicating that mandated periodic password changes make user accounts less secure. OMB-22-09 specifically states "Password policies must not require use of special characters or regular rotation". - - Cloud Application Administrator. -- _Rationale:_ TODO - _Last modified:_ June 2023 ### Resources -- [Securing privileged access for hybrid and cloud deployments in Azure AD](https://docs.microsoft.com/en-us/azure/active-directory/roles/security-planning#ensure-separate-user-accounts-and-mail-forwarding-for-global-administrator-accounts) - -### License Requirements - -- N/A - -### Implementation - -Review [these](https://docs.microsoft.com/en-us/azure/active-directory/roles/view-assignments) -instructions to identify users assigned to highly privileged roles and -verify the account does not exist outside Azure AD. - -## 13. Multifactor Authentication for Highly Privileged Roles - -Require users to perform MFA to access highly privileged roles. This -configuration provides a backup policy to enforce MFA for highly -privileged users in case the main conditional access policy—which -requires MFA for all users—is disabled or misconfigured. - -### Policies -#### MS.AAD.13.1v1 -MFA SHALL be required for user access to highly privileged roles. -- _Rationale:_ TODO -- _Last modified:_ June 2023 - - - -- Refer to the baseline statement [Highly Privileged User Accounts SHALL - be Cloud-Only](#2.12.1 Policy) - for a recommended minimum list of Azure AD built-in roles that are - considered highly privileged. It is also possible to designate - additional built-in roles that are considered highly privileged in the - agency’s environment based on its risk tolerance. - -### Resources +- [Password policy recommendations - Microsoft 365 admin \| Microsoft + Docs](https://docs.microsoft.com/en-us/microsoft-365/admin/misc/password-policy-recommendations?view=o365-worldwide#password-expiration-requirements-for-users) -- [Five steps to securing your identity infrastructure](https://docs.microsoft.com/en-us/azure/security/fundamentals/steps-secure-identity) +- [Eliminate bad passwords using Azure Active Directory Password + Protection](https://docs.microsoft.com/en-us/azure/active-directory/authentication/concept-password-ban-bad) -- [M-22-09 Federal Zero Trust Strategy](https://www.whitehouse.gov/wp-content/uploads/2022/01/M-22-09.pdf) +- [NIST Special Publication 800-63B - Digital Identity + Guidelines](https://pages.nist.gov/800-63-3/sp800-63b.html) ### License Requirements @@ -874,462 +497,282 @@ MFA SHALL be required for user access to highly privileged roles. ### Implementation -[Follow these instructions](https://docs.microsoft.com/en-us/azure/active-directory/conditional-access/howto-conditional-access-policy-all-users-mfa) -to create a conditional access policy requiring MFA for access, but -under **Assignments,** use the following tailored steps to scope the -policy to privileged roles. +#### MS.AAD.6.1v1, instructions: -1. Under **Assignments**, select **Users and groups.** +1. [Follow the instructions at this link](https://docs.microsoft.com/en-us/microsoft-365/admin/manage/set-password-expiration-policy?view=o365-worldwide#set-password-expiration-policy) and configure the **Password expiration policy** to **Set passwords to never expire**. - +## 7. Highly Privileged User Access -2. Under **Include**, choose **Select users and groups**, then click - the **Directory roles** checkbox. Select each of the roles listed in - the baseline statement, [Highly Privileged User Accounts SHALL be Cloud-Only](Policy MS.AAD.12.1v1). +This section provides policies that help reduce security risks related to the usage of highly privileged AAD built-in roles. Privileged administrative users have access to operations that can undermine the security of the tenant by changing configurations and security policies, thus special protections are necessary to secure this level of access. -3. Under **Exclude**, follow Microsoft’s guidance from the previously - provided instructions link. +- _Note:_ Refer to the Highly Privileged Roles section at the top of this document for a reference list of roles considered highly privileged. -## 14. Permanent Permissions - -Do not assign users to highly privileged roles using permanent active -role assignments. Instead, assign users to eligible role assignments in -a PAM system and provide an expiration period for active assignments -requiring privileged users to reactivate their highly privileged roles -upon expiration. - -**Note**: Although Azure AD PIM is referenced in the implementation -instructions, an equivalent third-party PAM service may be used instead. +- _Implementation Alternatives:_ Some of the policy implementations in this section reference specific features of the AAD Privileged Identity Management (PIM) service which provides “Privileged Access Management (PAM)” capabilities. As an alternative to AAD PIM, there are third-party products and services with equivalent PAM capabilities that can be leveraged if an agency chooses to do so. ### Policies -#### MS.AAD.14.1v1 -Permanent active role assignments SHALL NOT be allowed for highly privileged roles. Active assignments SHALL have an expiration period. -- Refer to the baseline statement, [Highly Privileged User Accounts SHALL be Cloud-Only](#2121-Policy), for a recommended minimum list of Azure AD built-in roles that are considered highly privileged. It is also possible to designate additional built-in roles that are considered highly privileged in the agency’s environment based on its risk tolerance. -- _Rationale:_ TODO +#### MS.AAD.7.1v1 +A minimum of two users and a maximum of eight users SHALL be provisioned with the Global Administrator role. +- _Rationale:_ The Global Administrator role provides unfettered access to the tenant. Therefore, reducing the number of users with this access makes it more challenging for an adversary to compromise a tenant. Microsoft recommends fewer than five users and CISA decided on fewer than eight based on the data from federal agency pilots. - _Last modified:_ June 2023 - -#### MS.AAD.14.2v1 -Provisioning of users to highly privileged roles SHALL NOT occur outside of a PAM system, such as the Azure AD PIM service, because this bypasses the controls the PAM system provides. -- _Rationale:_ TODO +#### MS.AAD.7.2v1 +Privileged users SHALL be provisioned with finer-grained roles instead Global Administrator. +- _Rationale:_ Many privileged administrative users do not need unfettered access to the tenant to perform their duties. By assigning them to roles based on least privilege, the risks associated with having their accounts compromised are reduced. - _Last modified:_ June 2023 -### Resources - -- [Assign Azure AD roles in Privileged Identity Management](https://docs.microsoft.com/en-us/azure/active-directory/privileged-identity-management/pim-how-to-add-role-to-user) - -### License Requirements +#### MS.AAD.7.3v1 +Privileged users SHALL be provisioned cloud-only accounts that are separate from an on-premises directory or other federated identity providers. +- _Rationale:_ By provisioning cloud-only AAD user accounts to privileged users, the risks associated with a compromise of on-premises federation infrastructure are reduced. It is more challenging for the adversary to pivot from the compromised environment to the cloud with privileged access. +- _Last modified:_ June 2023 -- Use of an Azure AD PIM or an equivalent third-party PAM service. +#### MS.AAD.7.4v1 +Permanent active role assignments SHALL NOT be allowed for highly privileged roles except for emergency and service accounts. -- Azure AD PIM requires an AAD P2 license +- _Rationale:_ Instead of giving users permanent assignments to privileged roles, provisioning access "just in time" lessens the exposure period if those accounts become compromised. In AAD PIM or an alternative PAM system, just in time access can be provisioned by assigning users to roles as "eligible" instead of perpetually "active". +- _Last modified:_ June 2023 +- _Note:_ There are a couple of exceptions to this policy. Emergency access accounts need perpetual access to the tenant in the rare event of system degredation or other scenarios. Some types of service accounts require a user account with privileged roles and since those are software they cannot perform role activation. -### Implementation +#### MS.AAD.7.5v1 +Provisioning users to highly privileged roles SHALL NOT occur outside of a PAM system, because this bypasses critical controls the PAM system provides. +- _Rationale:_ By provisioning users to privileged roles within a PAM system, numerous privileged access policies and monitoring can be enforced. If privileged users are assigned directly to roles in the M365 admin center or via Powershell outside of the context of a PAM system, a significant set of critical security capabilities are bypassed. +- _Last modified:_ June 2023 -Note: Any parts of the following implementation instructions that -reference the Azure AD PIM service will vary if using a third-party PAM -system. +#### MS.AAD.7.6v1 +Activation of the Global Administrator role SHALL require approval. -1. In the **Azure Portal**, navigate to **Azure AD Privileged Identity - Management (PIM).** +- _Rationale:_ Requiring approval for a user to activate Global Administrator which provided unfettered access, makes it more challenging for an attacker to compromise the tenant with stolen credentials and it provides visibility of activities that may indicate a compromise is taking place. +- _Last modified:_ June 2023 - +#### MS.AAD.7.7v1 +Eligible and Active highly privileged role assignments SHALL trigger an alert. -2. Under **Manage**, select **Azure AD roles**. +- _Rationale:_ It is imperative to closely monitor the assignment of the highest privileged roles for signs of compromise. Sending alerts when these assignments occur provides the security monitoring team a chance to detect potential compromises in action. +- _Last modified:_ June 2023 -3. Under **Manage**, select **Roles**. This should bring up a list of - all the Azure AD roles managed by the PIM service. +#### MS.AAD.7.8v1 +User activation of the Global Administrator role SHALL trigger an alert. -4. **Note**: This step is specific to the first policy bullet. - Repeat this step and step 5 for each highly privileged role - referenced in the policy section. The role “Global Administrator” is - used as an example in these instructions. +- _Rationale:_ The rationale for this policy is identical to the previous one, except that this policy applies to user activations. "Activation" occurs when a user that is assigned as eligible, "turns on" their access for a specific period of time. Monitoring this action closely for Global Administrator helps to detect events with significant security implications in action. +- _Last modified:_ June 2023 +- _Note:_ It is recommended to prioritize user activation of Global Administrator as one of the most important events to monitor and respond to. - - 1. Click the **Global Administrator** role in the list. - 2. Click **Settings**. - 3. Click **Edit.** - 4. Select the **Assignment** tab. - 5. De-select the option named **Allow permanent active assignment.** - 6. Under **Expire active assignments after**, select **15 days**. - 7. Click **Update.** - - - -5. Note: This step is specific to the second policy bullet. - - - - 1. While on the **Assignments** page for the role, select the **Active - Assignments** tab. - 2. Review the assignments list. If any of the assignments show a - **Start time** of “-” (i.e., empty start time) and of **End time** - of **Permanent**, then those role assignments were made outside of - the PIM service and therefore are out of compliance with the policy. - 3. Delete the non-compliant role assignments and then recreate them - using the PIM service. - - - -6. In addition to checking for permanent assignments using the PIM - Assignments page in step \#5, PIM also provides a report that lists - all role assignments that were performed outside of PIM so that - those assignments can be deleted and properly recreated using PIM. - - - - 1. From the **PIM landing page**, under **Manage**, select **Azure AD - roles.** - 2. Under **Manage**, select **Alerts.** - 3. Click the **Scan** button and wait for the scan to complete. - 4. If there were any roles assigned outside of PIM, the report will - display an alert named, **Roles are being assigned outside of - Privileged Identity Management**; Click that alert. - 5. PIM displays a list of users, their associated roles, and the - date/time that they were assigned a role outside of PIM: Delete the - non-compliant role assignments and then recreate them using the PIM - service. - -## 15. Activation of Highly Privileged Roles - -Require approval for a user to activate a highly privileged role, such -as Global Administrator. This makes it more challenging for an attacker -to leverage the stolen credentials of highly privileged users and -ensures that privileged access is monitored closely. - -**Note**: Although Azure AD PIM is referenced in the implementation -instructions, an equivalent third-party PAM service may be used instead. +#### MS.AAD.7.9v1 +User activation of other highly privileged roles SHOULD trigger an alert. -### Policies -#### MS.AAD.15.1v1 -Activation of highly privileged roles SHOULD require approval. -- _Rationale:_ TODO +- _Rationale:_ The rationale for this policy is identical to the previous one, except that this policy applies to user activations of privileged roles that are not Global Administrator (i.e. the other privileged roles). CISA separated this policy from the previous one and designated it as a "SHOULD" item because in some environments activation of privileged roles can generate a significant number of alerts. - _Last modified:_ June 2023 - +### Resources -- Refer to the baseline statement [Highly Privileged User Accounts SHALL be Cloud-Only](#2121-Policy) - for a list of Azure AD built-in roles that are considered highly - privileged. It is also possible to configure additional built-in roles - that are considered highly privileged in the agency’s environment - based on its risk tolerance. +- [Best practices for Azure AD roles (Limit number of Global Administrators to less than 5)](https://docs.microsoft.com/en-us/azure/active-directory/roles/best-practices#5-limit-the-number-of-global-administrators-to-less-than-5) -### Resources +- [Implement Privilege Access Management](https://learn.microsoft.com/en-us/azure/security/fundamentals/steps-secure-identity#implement-privilege-access-management) + +- [Assign Azure AD roles in Privileged Identity Management](https://docs.microsoft.com/en-us/azure/active-directory/privileged-identity-management/pim-how-to-add-role-to-user) - [Approve or deny requests for Azure AD roles in Privileged Identity Management](https://docs.microsoft.com/en-us/azure/active-directory/privileged-identity-management/azure-ad-pim-approval-workflow) +- [Configure security alerts for Azure AD roles in Privileged Identity Management](https://learn.microsoft.com/en-us/azure/active-directory/privileged-identity-management/pim-how-to-configure-security-alerts) + ### License Requirements -- Use an Azure AD PIM or an equivalent third-party PAM service +- Azure AD PIM or an equivalent third-party PAM service. - Azure AD PIM requires an AAD P2 license ### Implementation -**Note**: Any parts of the following implementation instructions that -reference the Azure AD PIM service will vary if using a third-party PAM -system. +- _Note:_ Steps in the following implementation instructions that reference the AAD PIM service will vary if using a third-party PAM system instead. -1. In the **Azure Portal**, navigate to **Azure AD** and create a new - group named “Privileged Escalation Approvers.” This group will - contain users that will receive role activation approval requests - and approve or deny them. Users in this group must, at least, have - the permissions provided to the Privileged Role Administrators role - to adjudicate requests. +- _Future revisions:_ Some of the implementation instructions associated with this group of policies may be revised in the next release to incorporate functionality provided by the the AAD PIM for Groups feature. -2. In the **Azure Portal**, navigate to **Azure AD Privileged Identity - Management (PIM).** +#### MS.AAD.7.1v1, instructions: - +1. In **Azure Active Directory** select **Roles and administrators.** -3. Under **Manage**, select **Azure AD roles**. - -4. Under **Manage**, select **Roles**. This should bring up a list of - all the Azure AD roles managed by the PIM service. - -5. Repeat this step for the Privileged Role Administrator role, User - Administrator role, and other roles that the agency has designated - as highly privileged. - - - - 1. Click the **Global Administrator** role in the list. - 2. Click **Settings.** - 3. Click **Edit**. - 4. Select the **Require approval to activate** option. - 5. Click **Select approver**s, select the group **Privileged Escalation - Approvers**, and then click **Select**. - 6. Click **Update**. - -## 16. Highly Privileged Role Assignment and Activation - -Since many cyber attacks leverage privileged access, it is imperative to -closely monitor the assignment and activation of the highest privileged -roles for signs of compromise. Create alerts to trigger when a highly -privileged role is assigned to a user and when a user activates a highly -privileged role. - -Note: Although Azure AD PIM is referenced in the implementation -instructions, an equivalent third-party PAM service may be used instead. - -### Policies -#### MS.AAD.16.1v1 -Eligible and Active highly privileged role assignments SHALL trigger an alert. -- _Rationale:_ TODO -- _Last modified:_ June 2023 - - - - - Refer to the baseline statement [Highly Privileged User Accounts SHALL be Cloud-Only](#2121-Policy) - for a recommended minimum list of Azure AD built-in roles that are - considered highly privileged. It is also possible to designate - additional built-in roles that are considered highly privileged in the - agency’s environment based on its risk tolerance. - - - -#### MS.AAD.16.2v1 -User activation of the Global Administrator role SHALL trigger an - alert. -- _Rationale:_ TODO -- _Last modified:_ June 2023 - -#### MS.AAD.16.3v1 -User activation of other highly privileged roles SHOULD trigger an alert. -- _Rationale:_ TODO -- _Last modified:_ June 2023 +2. Select the **Global administrator role.** - +3. Under **Manage**, select **Assignments.** - - Note: Alerts can be configured for user activation of other highly - privileged roles as well but note that if users activate these other - roles frequently, it can prompt a significant number of alerts. - Therefore, for those other roles, it might be prudent to set up a - separate monitoring mailbox from the one configured for the alerts - associated with the Global Administrator role. This separate mailbox - would be designed to store alerts for “review as necessary” purposes - versus the mailbox configured for the Global Administrator role, which - should be monitored closely since that role is sensitive. +4. Validate that between two to eight users are listed. -### Resources +5. If you have AAD PIM, count the number of users in both the **Eligible assignments** and **Active assignments** tabs. There should be a total of two to eight users across both of these tabs (not individually). Do not count the same username twice. If any groups are listed, count the number of users that are members of the group and include it in the total count. -- [Assign Azure AD roles in Privileged Identity Management](https://docs.microsoft.com/en-us/azure/active-directory/privileged-identity-management/pim-how-to-add-role-to-user) +#### MS.AAD.7.2v1, instructions: -### License Requirements +1. In **Azure Active Directory** select **Security.** -- Use an Azure AD PIM or an equivalent third-party PAM service. +2. Under **Manage**, select **Identity Secure Score.** -- Azure AD PIM requires an AAD P2 license +3. Click the **Columns** button and select all the available columns and click **Apply.** -### Implementation +4. Review the score for the action named **Use least privileged administrative roles.** -Note: Any parts of the following implementation instructions that -reference the Azure AD PIM service will vary if using a third-party PAM -system. +5. Review the **current score** value and compare it to the **max score**. +If the current score is not the maximum value and the status is not **Completed**, you must perform the improvement actions. If that is the case, follow the detailed action steps and then check the score again after 48 hours to ensure compliance. -1. In the **Azure Portal**, navigate to **Azure AD Privileged Identity - Management (PIM).** +#### MS.AAD.7.3v1, instructions: +Note: Performing a manual review of highly privileged users to determine which ones are not cloud-only is labor intensive so we recommend running the ScubaGear tool instead. ScubaGear will provide a list of the highly privileged users that are not cloud-only. - +1. Perform the steps below for each highly privileged role. We reference the Global Administrator role as an example. -2. Under **Manage**, select A**zure AD roles.** +2. In **Azure Active Directory** select **Roles and administrators.** -3. Under **Manage**, select **Roles**. This should bring up a list of - all the Azure AD roles managed by the PIM service. +3. Select the **Global administrator role.** -4. Click the **Global Administrator** role. +4. Under **Manage**, select **Assignments.** If you have AAD PIM, repeat the steps below for both the **Eligible** and the **Active** assignments. If a group is listed, you will need to determine the members of the group and perform the steps for each group member. -5. Click **Settings** and then click **Edit.** +5. For each highly privileged user, execute the Powershell code below but replace the **username@somedomain.com** sample data value with the principal name of the user that is specific to your environment. You can get the data value from the **Principal name** field displayed in the Azure Active Directory portal. -6. Click the **Notification** tab. +``` +Connect-MgGraph +Select-Mgprofile beta +Get-MgUser -Filter "userPrincipalName eq 'username@somedomain.com'" | FL +``` -7. Under **Send notifications when members are assigned as eligible to - this role**, in the **Role assignment alert** -\> **Additional - recipients** textbox, enter the email address of the mailbox - configured to receive the alerts for this role. +6. Review the output field named **OnPremisesImmutableId**. If this field has a data value, it means that this specific user is not cloud-only. If the user is not cloud-only, create a cloud-only account for that user, assign the user to their respective roles and then remove the account that is not cloud-only from AAD. -8. Under S**end notifications when members are assigned as active to - this role**, in the **Role assignment alert** -\> **Additional - recipients** textbox, enter the email address of the mailbox - configured to receive the alerts for this role. +#### MS.AAD.7.4v1, instructions: -9. Under **Send notifications when eligible members activate this - role**, in the **Role activation alert** -\> **Additional - recipients** textbox, enter the email address of the mailbox - configured to receive the alerts for this role. +1. In **Azure Active Directory** select **Roles and administrators**. Perform the steps below for each highly privileged role. We reference the Global Administrator role as an example. -10. Click **Update**. +2. Select the **Global administrator role.** -11. Repeat steps 4 through 10 for each of the other highly privileged - roles referenced in the policy section above, with one modification: +3. Under **Manage**, select **Assignments** and click the **Active assignments** tab. - +4. Verify that there are no users or groups with a value of **Permanent** in the **End time** column. If there are any, recreate those assignments to have an expiration date using AAD PIM or an alternative PAM system. The only exception to this policy are emergency access accounts and service accounts that require perpetual active assignments. See policy for details. - 1. When configuring the **Send notifications when eligible members - activate this role** for these other roles, enter an email address - of a mailbox that is different from the one used to monitor Global - Administrator activations. +#### MS.AAD.7.5v1, instructions: + +1. Perform the steps below for each highly privileged role. We reference the Global Administrator role as an example. -## 17. Managed Devices +2. In **Azure Active Directory** select **Roles and administrators.** -Require that users connect to M365 from a device that is managed using -conditional access. Agencies that are implementing a hybrid Azure AD -environment will likely use the conditional access control option named -**Hybrid Azure AD joined**, whereas agencies that are using devices that -connect directly to the cloud and do not join an on-premises AD will use -the conditional access control option named, **Require device to be -marked as compliant**. +3. Select the **Global administrator role.** -**Guest user access note**: This conditional access policy will impact -guest access to the tenant because guest users will be required to -authenticate from a managed device similar to regular Azure AD users. -For guest users, the organization that manages their home tenant is -responsible for managing their devices and the resource tenant must be -configured to trust the device claims from the home tenant, otherwise -guest users will be blocked by the policy. [This link](https://docs.microsoft.com/en-us/azure/active-directory/external-identities/authentication-conditional-access) describes the -detailed authentication flow for guest users and how conditional access -related to devices is applied. -The implementation section describes the cross-tenant settings that must -be configured in both the home and the resource tenants to facilitate -guest access with managed devices. +4. Under **Manage**, select **Assignments.** Repeat the steps below for both the **Eligible** and the **Active** AAD PIM assignments. -### Policies -#### MS.AAD.17.1v1 -Managed devices SHOULD be required for authentication. -- _Rationale:_ TODO -- _Last modified:_ June 2023 +5. For each user or group listed, examine the value in the **Start time** column. If it contains a value of **-**, this indicates that the respective user / group was assigned to that role outside of AAD PIM. If the role was assigned outside of AAD PIM, delete the assignment and recreate it using AAD PIM. -### Resources -- [Configure hybrid Azure AD join](https://docs.microsoft.com/en-us/azure/active-directory/devices/howto-hybrid-azure-ad-join) +#### MS.AAD.7.6v1, instructions: -- [Azure AD joined devices](https://docs.microsoft.com/en-us/azure/active-directory/devices/concept-azure-ad-join) +1. In **Azure Active Directory** create a new group named **Privileged Escalation Approvers**. This group will contain users that will receive role activation approval requests and approve or deny them. -- [Set up enrollment for Windows devices (for Intune)](https://docs.microsoft.com/en-us/mem/intune/enrollment/windows-enroll) +2. Assign this new group to the AAD role **Privileged Role Administrators**. This permission is required so that users in this group can adjudicate role activation approval requests. -### License Requirements +3. Assign the users responsible for reviewing approval requests to the new **Privileged Escalation Approvers** group via the [PIM for Groups feature](https://learn.microsoft.com/en-us/azure/active-directory/privileged-identity-management/concept-pim-for-groups). -- Use Microsoft Intune (if implementing the requirement for the device - to be compliant). +4. In **AAD Privileged Identity Management (PIM)**, under **Manage**, select **Azure AD roles**. -### Implementation +5. Under **Manage**, select **Roles**. -[Follow these instructions](https://docs.microsoft.com/en-us/azure/active-directory/conditional-access/howto-conditional-access-policy-compliant-device#create-a-conditional-access-policy) -to create a conditional access policy that requires the device to be -either hybrid Azure AD joined or compliant during authentication. + 1. Select the **Global Administrator** role in the list. + 2. Click **Settings**. + 3. Click **Edit**. + 4. Select the **Require approval to activate** option. + 5. Click **Select approvers** and select the group **Privileged Escalation Approvers**, and then click **Select**. + 6. Click **Update**. -Use the following instructions to facilitate guest access with managed -devices. Although the agency implementing this baseline only controls -the resource tenant and does not have control over the home tenant, CISA -provides our recommended security configuration for the home tenant in -this section. +#### MS.AAD.7.7v1, instructions: -Reference [this link](https://docs.microsoft.com/en-us/azure/active-directory/external-identities/cross-tenant-access-overview) -for a general description of cross-tenant access settings to become -familiar with the terminology and configurations. +1. In **AAD Privileged Identity Management (PIM)**, under **Manage**, select **Azure AD roles.** -For the resource tenant, use the following steps (for demonstration -purposes, the home tenant domain is named “home.onmicrosoft.com” — -replace this name with the actual name of the tenant): +2. Under **Manage**, select **Roles**. Perform the steps below for each highly privileged role. We reference the Global Administrator role as an example. - +3. Click the **Global Administrator** role. -1. Navigate to **Azure AD** -\> **External Identities** -\> - **Cross-tenant access settings.** +4. Click **Settings** and then click **Edit.** - +5. Click the **Notification** tab. -2. In **Organizational Settings**, add a new organization – - “home.onmicrosoft.com”. +6. Under **Send notifications when members are assigned as eligible to this role**, in the **Role assignment alert > Additional recipients** textbox, enter the email address of the security monitoring mailbox configured to receive privileged role assignment alerts. -3. Open the **Inbound access** settings for the newly added - organization. +7. Under **Send notifications when members are assigned as active to this role**, in the **Role assignment alert > Additional recipients** textbox, enter the email address of the security monitoring mailbox configured to receive privileged role assignment alerts. -4. Click the **B2B collaboration** tab. Under **External users and - Groups** -\> **Access status**, select **Allow access.** +8. Click **Update**. -5. Under **External users and Groups** -\> **Applies to**, select **All - external users and groups.** +#### MS.AAD.7.8v1, instructions: -6. Click the **Trust settings** tab. Under **Customize settings** -\> - select **Trust multi-factor authentication from Azure AD tenants**, - **Trust compliant devices,** and **Trust hybrid Azure AD joined - devices** +1. In **AAD Privileged Identity Management (PIM)**, under **Manage**, select **Azure AD roles.** - +2. Under **Manage**, select **Roles**. -For the home tenant, use the following steps (for demonstration -purposes the resource tenant domain is named -“resource.onmicrosoft.com” — replace this name with the actual name -of the tenant): +3. Click the **Global Administrator** role. - +4. Click **Settings** and then click **Edit.** -1. Navigate to **Azure AD** -\> **External Identities** -\> - **Cross-tenant access settings.** +5. Click the **Notification** tab. - +6. Under **Send notifications when eligible members activate this role**, in the **Role activation alert > Additional recipients** textbox, enter the email address of the security monitoring mailbox configured to receive Global Administrator activation alerts. -2. In **Organizational Settings**, Add a new organization – - “resource.onmicrosoft.com”. +7. Click **Update**. -3. Open the **Outbound access** settings for the newly added - organization. +#### MS.AAD.7.9v1, instructions: + + 1. Follow the same instructions as MS.AAD.7.8v1 for each of the highly privileged roles (other than Global Administrator) but enter a security monitoring mailbox that is different from the one used to monitor Global Administrator activations. -4. Click the **B2B collaboration** tab. Under **Users and Groups** -\> - **Access status**, select **Allow access.** +## 8. Guest User Access -5. Under **Users and Groups** -\> **Applies to**, select **All users.** +This section provides policies that help reduce security risks related to the integration of M365 guest users. A guest user is a specific type of external user that belongs to a separate organization but can access files, meetings, teams and other data in the target tenant. It is common to invite guest users to a tenant for cross-agency collaboration purposes. -## 18. Guest User Access +#### MS.AAD.8.1v1 +Guest users SHOULD have limited or restricted access to Azure AD directory objects. -Ensure that only users with specific privileges can invite guest users -to the tenant and that invites can only be sent to specific external -domains. Also ensure that guest users have limited access to Azure AD -directory objects. +- _Rationale:_ By limiting the amount of information about objects in the tenant that is available to guest users, this reduces the malicious reconnaissance exposure if a guest account is compromised or created by an adversary. +- _Last modified:_ June 2023 -#### MS.AAD.18.1v1 +#### MS.AAD.8.2v1 Only users with the Guest Inviter role SHOULD be able to invite guest users. -- _Rationale:_ TODO + +- _Rationale:_ By only allowing an authorized groups of individuals to invite guest users to create accounts in the tenant, this helps an agency enforce a guest user account approval process which reduces the risk of unauthorized accounts being created. - _Last modified:_ June 2023 -#### MS.AAD.18.2v1 +#### MS.AAD.8.3v1 Guest invites SHOULD only be allowed to specific external domains that have been authorized by the agency for legitimate business purposes. -- _Rationale:_ TODO -- _Last modified:_ June 2023 -#### MS.AAD.18.3v1 -Guest users SHOULD have limited access to Azure AD directory objects. -- _Rationale:_ TODO +- _Rationale:_ Limiting which domains can be invited to create guest accounts in the tenant helps reduce the risk of users from unauthorized external organizations getting access. - _Last modified:_ June 2023 ### Resources - [Configure external collaboration settings](https://docs.microsoft.com/en-us/azure/active-directory/external-identities/external-collaboration-settings-configure) +- [Compare member and guest default permissions](https://learn.microsoft.com/en-us/azure/active-directory/fundamentals/users-default-permissions#compare-member-and-guest-default-permissions) + ### License Requirements - N/A ### Implementation -[Follow these instructions](https://docs.microsoft.com/en-us/azure/active-directory/external-identities/external-collaboration-settings-configure#configure-settings-in-the-portal) -to configure the Azure AD **External collaboration settings**. +#### MS.AAD.8.1v1, instructions: + +1. In **Azure Active Directory** select **External Identities > External collaboration settings**. + +2. Under **Guest user access**, select either **Guest users have limited access to properties and memberships of directory objects** or **Guest user access is restricted to properties and memberships of their own directory objects (most restrictive)**. + +3. Click **Save**. + +#### MS.AAD.8.2v1, instructions: + +1. In **Azure Active Directory** select **External Identities > External collaboration settings**. + +2. Under **Guest invite settings**, select **Only users assigned to specific admin roles can invite guest users**. + +3. Click **Save**. -1. Under **Guest user access**, select **Guest users have limited - access to properties and memberships of directory objects.** +#### MS.AAD.8.3v1, instructions: -2. Under **Guest invite settings**, select **Only users assigned to - specific admin roles can invite guest users**. +1. In **Azure Active Directory** select **External Identities > External collaboration settings**. -3. Under **Collaboration restrictions**, select **Allow invitations +2. Under **Collaboration restrictions**, select **Allow invitations only to the specified domains (most restrictive)**. - +3. Select **Target domains** and enter the names of the external domains that have been authorized by the agency for guest user access. + +4. Click **Save**. -4. Select **Target domains** and enter the names of the external - domains that have been authorized by the agency for guest user - access. # Acknowledgements @@ -1385,45 +828,15 @@ Dr. Mukesh Rohatgi (MITRE), Lee Szilagyi (MITRE), Nanda Katikaneni # Appendix A: Hybrid Azure AD Guidance The majority of this document does not focus on securing hybrid Azure AD -environments. CISA is working on a separate document that addresses the -unique implementation requirements of hybrid Azure AD infrastructure, -including the on-premises components. Meanwhile, the following limited -set of hybrid Azure AD policies that include on-premises components are -provided: - -- Azure AD Password Protection SHOULD be implemented for the on-premises - directory. - - - -- [Enforce on-premises Azure AD Password Protection for Active Directory Domain Services](https://docs.microsoft.com/en-us/azure/active-directory/authentication/concept-password-ban-bad-on-premises) - -- [Plan and deploy on-premises Azure Active Directory Password Protection](https://docs.microsoft.com/en-us/azure/active-directory/authentication/howto-password-ban-bad-on-premises-deploy) - - - -- Password hash synchronization with the on-premises directory SHOULD be - implemented. - - - -- [Implement password hash synchronization with Azure AD Connect sync](https://docs.microsoft.com/en-us/azure/active-directory/hybrid/how-to-connect-password-hash-synchronization) - - +environments. CISA released a separate [Hybrid Identity Solutions Architecture](https://www.cisa.gov/resources-tools/services/secure-cloud-business-applications-scuba-project) document that addresses the unique implementation requirements of hybrid Azure AD infrastructure. In addition, a limited set of hybrid Azure AD policies that include on-premises components are +provided below: -- Service accounts created in Azure AD to support the integration of - Azure AD Connect SHOULD be restricted to originate from the IP address - space of the network hosting the on-premises AD. This can be - implemented via a conditional access policy that is applied to the - Azure AD Connect service accounts and blocks access except from a - specific Azure AD Named Location that is configured with respective - on-premises IP address range. +- [On-premises Azure AD Password Protection for Active Directory Domain Services](https://docs.microsoft.com/en-us/azure/active-directory/authentication/concept-password-ban-bad-on-premises) SHOULD be enforced. - +- [Password hash synchronization](https://docs.microsoft.com/en-us/azure/active-directory/hybrid/how-to-connect-password-hash-synchronization) with the on-premises directory SHOULD be implemented. -- [Using the location condition in a Conditional Access policy](https://docs.microsoft.com/en-us/azure/active-directory/conditional-access/location-condition) +# Appendix B: Cross-tenant Access Guidance -- [Azure AD Connect: Accounts and permissions](https://docs.microsoft.com/en-us/azure/active-directory/hybrid/reference-connect-accounts-permissions) +Some of the conditional access policies contained in this security baseline, if implemented as described herein, will impact guest user access to a tenant. For example, the policies require users to perform MFA and originate from a managed device to gain access. These requirements are also enforced for guest users. For these policies to work effectively with guest users, both the home tenant (the one that the guest user belongs to) and the resource tenant (the target tenant) may need to configure their AAD cross-tenant access settings. -[^1]: “Cloud-only” user accounts have no ties to the on-premises AD and - are not federated – they are local to Azure AD only. +[Refer to this article](https://docs.microsoft.com/en-us/azure/active-directory/external-identities/authentication-conditional-access) to gain an understanding of how MFA and device claims are passed from the home tenant to the resource tenant. [Refer to this article](https://learn.microsoft.com/en-us/azure/active-directory/external-identities/cross-tenant-access-overview) to configure the inbound and outbound cross-tenant access settings in AAD. diff --git a/images/aad-mfa.png b/images/aad-mfa.png index 3f641b3d7a427bb93f551c9870c5fe9f25ae6961..563533f41f6b10ed68707c303330dd96a9c1e2a9 100644 GIT binary patch literal 46669 zcmcG#Wl&q)8$DVm6t_~`S}0JUSaB~7#fuh~;_eax#id9o?(XjHR@@1i;7)K-g5C7} z&D=Zp%m2fjxiiU-9CEfiXP^D7XRUQ2RF!3MFv&4rym)~lFDLc&#S3Jo7cY>w(O)5s zRD8mfLi|B;{VFT*qH2=z5b*`YQd~*=#f#cltOpZR#CHrQxo@s7Uf>S=dm|;X;8MJJ z(YPfqC9dIRc$$g!BSW+GDSJ6J^OQb)!olYZgU79aPFnRur;3*NWNV=u)NN3WgB6G~ zi230|AP$N&)9gDG3CzRJ=2M`D#nZm0he}3;yc} z*#-SOmsB=zYs++Zch~*-6K?P`zLPDeYN5`2>;b01yeo$D?<@{@n%w)XWDG(EtE2hS zb=&Bdn_?(yqlqkyHVe#}nwq6KIXQsJ{~D8l%+Ac@vg$Qiji+#?3AkFobhkhM#X}17 z>VN4uE6-S3S6BCc|5PHma+n&RxIGj-7e&U^1|mo66Gh{EA3p+h{NH4NDwdX(FurZ$ zTD6k@9r+fD!T;ZoqCWPcWc;toB$NN+jBf?-)-nWKH4F^aI~NhNA^j-){BY%S-i!7~ zX&@PfyU@CyRem^E?CHou4ZK#P5#?~+lIq;Vaa0wihIPMGQc`L=EK1iO6OC7t+~cNEC0>*gC9QKf6i}e(ozw* zNtk#EqQG}bt<}_sdHt|bgb?aW*^{;o5B}-?9qobpMf%Eo0QUd-K&>{wDp|_sW-3gAhe`>n8iv2hoB45E8={z$z+<{x9gs$@S_ha^;PpvrZWJ8jHPSx^swMwE|-S z5t8$bo4YNN?t@NRZA0%uzw;oP12dZY6#qt31%;oGeQ5jHEjTCE|6%(H_Id01>FoKT z{_(_8?AWm0)3kPpI$OEtZt8`J`xtBU-!l;rSERn{a-+vGJhLRD$0KbQiDgHY2;ku}9v1^#83)VTEKiOVAGaQ>ixWYy&8e>}UHwK`lCK#Eh)nus>4ZD23eU@rW z+Cd?M5zPMjD&R+`=l!YvF;BI3^t0dN4an0`saOm#mwWeY!~&R0)^~|`rtaIy4Wqv7 zE>_9Ta{jIV|k-?>-)mKr!&W82s}7 zb=zhrh1-gC@g2kbhJnwp5V*FT>oJAX?79oqsiJ&v2gwzrbH>wa)Ca9_}LF&zP1T7~ZFDsz<8)Jy|5pdDArkksdj`pHXhha+P8 z;ML*#*4E_xEP!&dp-*Xd6QSi(npdB)@P(8>Zjqz!HU&S!gFE=Psrk-K0JoZgx~bZC zm&H%DS5^$J)(Pu8yMcI~EWKlF;`YA$?k_5Anelv6?ce#_$&QJMd3~haz2e_}T-E*{ zGV43awV?!9C^u{jE9N8=wgVY>X5v{AcSL@^VxpE~^x7RLjD7ivcjIxO-jcNaaMt;G z=)b50kqFNEU&d!E#*%XO0sM3eCpVz7ZyDUbB{%E4txp;RsUNaeQFOLtr z{Kq+m|K4QZukAkw_G||xPhk-HgQb5G-zh&RE1pv0*Ep=VtsA!cKV4;8GhWXkHfk_n zPbv~&nL7UPUy!L6L=K*+D`;(dAIk{)< z+rfLZ)6>(Z_+u*cU{u4;jFdpHHNX4Qw(S_9ho&*M_Hn?bS5;^4^+&I_WZZq1hbsOn z0J_W<*QHrV6#T?@{QGE=XoDi z=ifXg-k#df?Es*!4uBBk)+Sv&8I0Z>-;SJ~Y4WkMPt}&d3`H zuA}Cz8&)wVWM_{VX_7m40AcHAu1^!K;oM1lT^G?^5!~3X#WOCW!i8iCkh8ICII#Io zkYlh1f9andQVb;chqc7>#j7prLI8i9~HNoT9r13SP zt|Mz`eLN-JWMQuki&|Tk!z_z7X%tltPFX6=CBUXMvqm3`KlQV_9;V`P%{>_7><3`> z?d^*_x5B;?bSor%To(Bh?`MKPJN7R{`FYj94R5WXI?qu`;~w#UMkKQ{S>Htv2;fMa zFLTky>1})Ndx{lIlCN@+6ip)rhLPRhHg}&&)L5TozK_YK?a8k z?49#4>311MPnXHX&xmu~9jSyLx}RaszHMeE0~=t5_y6F;u53>&9^Eyy|HH-l@gYpg z=lj;;FN;*wd7?c(nho-k{w>TIXyef54Z`fd!Oij4N_5anj>~S@7|KI?Ug7hemwr?V z;^F}+H2CnInf;H1jQqZkrW&z*oMCm*&!i!`Iyx>PH`Sa?@Ig*uyP<8z4~|KB zd9-4$JspGn+*8fxDIkA`)`vq~hBWG6+_l$CDmO!{MX#Aew_*~d!qUJlVzyloAeGA&~ z+Ix$6#YBb{Hum6iYHM`7??xMgZfOG<`1a$8o*VUIG${ZZ{CbuO3+ON5pYdbt3QYL= zwm(QhjQ%avWu{76sYDu1J{D3nMn3j(*lu(8V)lt$Xts zUyLXXa|eE5+iQ_+J`U!@nPRWVPwyZzeAw)XgqlwsRe`&wG<4ztPYzKp1}TO`KhH7m zZ)MmGV-2radjT&f+ap_5x(mejRQr`(p9{RJ2LC9{a>A6v>Ijwjd#B8Y*KD|r>Tpy@ z;%_h0Sd1@Cvy%7sbvKuN`aGaN?=F#_Z;YOIL78r|^6lv=-dga}+N>+2sXoUv4@rnn z&vBS`j8o2;p$fWeA1Q?_m?sJm@%%*@`>-_1#_XPU@C}<$x^Zr3U@~@zIcH=<8bMhH z`^FkuKHOFyf2PypdCg8|dz)v9Yn;)*vb- z&w?mvBVB}Y>s&6W0@Us$+vdfKLWZfV!T@e*9#*Y1XE!qNgp zc9V^u+3_=gs3S8J%6u5Ia*OvAvf(d$hFn*2l8$+k>ev=Ei-fcwZX$`VS^w~<3sB!+}<;j@d4~!|whR+v29K44U ztEP`u1aOQ-+_{z9)ZjG=*@Vwe-=cB_s^8}g?R`>&tvm;lzXemlslRuzp`L9%!XRh1 zQP-7AB=ZcV7@>n0>fKqXf09}C_U>(b5eVY?xMcSdlVW=#M+K+lxZ5DTO-_6vHh~L%LVqr#D!_y$5s|nmN0lmc+ZeD_P1GD3uEu__o0)b{BC*8r>Z0 z$A8lA2;X;tzMzUH;~|-4zyEdn$w+z!lQw&DDGV2M?b84djN@;=B- z8iz*3Gi9Cnz$_>%r$z44L;l=|s5FxUUT^i z#liN*Ye#r6q4K%wZVhY4LGp6L-D9M7N8htd;v6WzJ@qHcKu0mwKd|sH>_J?Gbq&Fw z=4V`+ReleD5_+(x%FJpMN2lhGX}?+2d-Sw88FGD9b$)w%K-aq_>38Ej{Bqy~!EgHEA$r9M6z2ik9Dy&0}S?|ji&`uKJT z;HN0D;U<)99;Yk25GQ?k(N2Y;&rCk<1-sKFN1O0)gBb)$35_JgC}1MYg3*)S4+7KovUJw9XFO3Xpyq`muI{w|hi`v=NSKy!SF9Q~5vBtJa4w=UlMRz4Rwx8&lH(Wx-e{jvSH^j#)C z^vOGvGlicPIR-gMB7E;7X6<>P=^|as1|l&fv*%dpqNYWC$mu(lKJfjrDZ_a5>l>3D zQd}@;!L(GujPR>Bs=1OL_}|cZUnx!N%OKsEzHLguI~?blx`s*CGtvG=wq0v+Hv9oC ze~W@bAL6FdLK2J&8!R{C_`-cNnaVYMreXrfkpxAv;hUh_q#-ILl-XAk*##tmd(2|pb735YiC(|!b}acG%st2}C|XZ5(X?Tc2tfb1 zmFgx1dJ(hT=DVLLP;g&X#tacpm52~1NO>LLfUF3>Pt(;=Nu#fvW;O9ALYs`0+a`bG zvLnEZrjdhhtZ!>{NWA&Q5X+jE`#8*3nm^8>)aw^}i&l#7JO?h{4$&n!RuB@lS&fSn z3MJ|XRNPQ%JYpaz$I~@UK8NXh!mSwOS9rsJ;^-d#P+_J|cSof5mR{6z*q}@F-Y!)8 zEntaa>dAz@GLc0B)&D9(pto$Vt8+?9^fv>&=>c-abuyDbtp?`A1De?nC_+e$b5#fa za?oP6sAMIEbW!$v_>7X}eEwGPAU`BUGG|l1&lW{o(R_&Lkgj5i@`4hsOzRSO9<Se~ph3&<`28|X zxCHd)L*LCg{#NN*$UFW+qhuxyu3Y2yClYPuxXdzt)JBknvkJcTF>2KOZFovY)D*HY zbhH~E!X;$=QE&`Hw`0Y?KbeFH!}-%9Q@}6YdEPEtp0TM)=E~>xYEXnz3ueqcNL>+U zRZJnOudZKt=X+iZ4%mhDPscUf--0DHAaQaFd9Ed?%tUfcZ8#IufO0@9I) z@NHeMSb2!XYf^fpmG`mVv-}-FD-jsw(}D2krD09d z2Mc_fz6hRQRhn891L&L01(-HU3N&`oJfxDe}&u-}) z#;UxX{o3!iGBWOGSaz%5EHihnu0#Os;C zIB6B<4V)`+F;_^8`j5aFf3}Wh_IRgkFXceX{v|Q5RZb~ScYeMw6o#|Zu|=g>Oe1A|fCji-A!_Bh z;?we~w$U@$HaeUQ;9$FKH}_kkY3Uz;TnyK}@l?N>7qCBqGDWi=$AMb{Ya~%g^w}JY zw6132a$^OOvp!Z}bHjcPfJna5opKw!LA*mN-doD0WGL=`lsE9{#n~on^V(Lr1{uz{ zpNz+6AI$u_fR@6AmyTR_0d5LD^x45kf~gz_k#V3MoVKQGMGB-@fh^}q5(|t!D2{A* zK~Q8jg9GbWJR&PW{LL59a7R2|Vf1B5Eq$D$9L zc%En0q_WfL#J=q4@p2=3=*!{K zj%}EXW2>9t zPqXfLm{Ifh9|)Z@PoMp64&>j?_CSsDzaQGXokbtm8zR*7Rtd_s$9u)*52M&{- zQ2@m+s52KIc`3kqz3Kcvnh$Gmt6x7R4#(1*-Mh{@ruyY%piRv;SkHANTTNyNJh9SJ zO8P_o(W_U!@VRUR-cMJg5eCie1Ogf8Iq zsf8H)Qa~*uO9bEnpANGlza-l3_`uSx!)`u&X@6rK0Nq# z(*V(zheY+$UD7x#))A7LZwkc!`SIyn9R{KweKzDr6!ZRuIanQ@^BEU!RFxn!`)S9iFk?c z^F0K%8km!ds9RM}5e%jhf{R(k;`IBcQrxbReHd_jg&}?riXVel%_W8I%r4@MV0llQ zUC+=}gYmY)wV6Ks!9nW1{cpQanR~BPbrQrOt?&G-*JO9GYV9Cn%*h|Q{g3bV-W>5m zui{t=f7F>`piHqN|8KHqcmU>gXJx5wPmFOgma)C{3B*Q!0T!tMhe} zxg}Pn{5Td_47MQ+!c7JsQ2uB=WIM1Fv+qAvC@_52V^WBl3Dbx+~D4>e=3 zZ~X_Q0)!-4kqu?QHZ)12PDA}R{24vXL?A}K()yL#?j*DohwQzK`umAG>`9Ziq)IV% zmT3%WmH`0{pBX)&=>W5w*YRIpPIUBa&{U;k?Bh+1mSd6G_2;~soZ2~4)`uS!|FAGC zO3k~A-&0EaKz2RQBk=0!JWVvs);iMMSlvq5qURT(*ORvZ+RFs1$?sx|Va?4>{-5VQ zZjN8eD1W|p_q9By-ZxES+0#M+lMj5x$O_V4zVKDVK{1*2Ierl1=lrMna{kGIkmM%@ z_}QUH6=(ac!05J#T*fKnXt)MsNll`SC3QFhf8U^U4d~$0hhy*6eW!YCB6W{+G803; zvif9`+T|I}CPO_dW`Dd`*=0oD$JwDA_t=Wt7YD=-9~Z_4%Vr9E$)3rq;d|HLN>&(g zZnB3YGj@r6ZM{w88ZJ5T8mNVVCX+yWNh+djBpgg0-%mG+uXxRal|PI@_qn7unh$)C zoqknAlkXXDb@kEYJAb$LDrO)NCwA1pd*6Q1&BXX{xtu9lkmPk8M-Z|^g7^D7du&m~ z9`(Z}UQ_t0igZDI%&tec;I`f$!Efu{qH}gQ;|FWuJ1M^F>v<`KtG+NjLY+%` zi*;5bjyT?z#C<&Ya^buku0O(emhnx|OE!?+V-rLe z-LHT;ewictOin$8tD{f^_Y#Cl8vEo@IJEToGwQ!ZZ^7?cqszmq{bP*Z;jd^d-E!-D z6~)Q_pF)qgTJi+!tB68-snbG*R5Oy_*sq7f$kI!eO9E4ZkY(Svfj%%yyN6SP@S^YD zPm+snBB57duyL7s?_%HzEo#;RXqAL*YKM?I{StQnUTi;}z2&}W+uStWu~t%w?pBe~ zQE8!`h(*tz?jT1YLB{3`mXkoIolaSenffQ{g70CQc>YU#jhA-su&ovc%EMZA(zsc; z@K%$%A9h7<`+v&CGxz=6Q-LP$Z~A!ckfx3bc6huK#z5-`43`IIQ=+)xyKUaJ^7Z|U zYxBY(7#iB>`=`why?xm$8UJ40<^%_Y5?GgFh;sgGlP8~@H0vXSwrs-NJ*y@u{dezE zK0L12R^I^E&p&LkN(#?tOA7k&ed+>7D8{dH&IO`kvV?Z)I-2Boc3uk7?vxux$ zQl8Y=2wjumY)|+ktj0{NBi-vl^zl#ykShoIoR-%r3Zk_;Fq7k-J;PP|nH*zbfx-*C z?c*WKfkG?>3^;WwClz`u7Pyh^O&3WcCv2g$~KW0f;V&t z=a?51wS%=8FYzhE(NPF8&-(?1Rl-xIDI+{FV#$>vGh$D~WgM?a@rBZT#|@+aNzJhdc`J7G-`^x>ehZ<#xS#)#2L0ECif z|1*Vr$Kkd#be-SS()rD4=Br_bQp#4sOZS&bZnfkYqBKQ{M@e_~<+p^L9~ zBf|JbS66o)3X?3-Pk@s`ph7A5Bv7Jcc`S)`UL&5(B zMu`$9S8$(>xc?NwFj|mehPUVIG_wr zXhOOi{Lj=AB|elk4nRM`v-Xh>*WX=)Bk3Q z%|M<#zm8MhShC}mx!O6(5q0vPDQL(z&$^SiHFlXkzs-*#G%oQ!lL@JmaLt`K%rlP- z;q$N!L0tKW|8?814%ge3nqU)=+)s9^{)A1(^1med;#>VLF7Pt9+XHO4rq#TPhQ5p66~T zYswuoC{}Zax@wE8rmvrA@iaD+E}udcXEx6UNjv`6drpSXWkwZyy2Aovvv6tqox@xh zLStIBYKm32jTH80bBLivw-3*^+s%0|t=wfu-8J%htetq-Gd za#ER|060?c8w#JWXIkK)?;z!V#s1%&`HGniT%wYAY2FCU0K^l|JWmwi3B0F`3(uP= zp*<|H@pJ$cDWx|!touv=EV2xB_>E3kaaQW=!>H3?9eeD$WwO~`GO@z&mOU|8Mpg=+ z(G;tG#V(7swJk7xC0?KkU%9N4E_ZQHhCc21;UaV5=1U`AX0W9|3t_@A+K^1DMKoPH)xTP+sKzU}2rf zD2;%;G~E!>H`OwY3sw5dF^zKMMj{PnEl!D%*)P%xp&zOX^hX|C1|!E3)O9M-+yWfG zP;G7HmF6m|h+ecTR(>nYIPrO1Lzq3dE@;Rv;{^zxcCN=3y!r4~!-b=OY-~+5QSg+gG z1@VkkFWxC=E98sXvR8{q{T?YeI;Lo-FO{5HEW92cA}>Co9rZ+3oDiCCHBbGmm(0}o z^sUr7*;JEIlmA$lNJ&7`TiX09+Dq!Mes0$C9}7$AopIPB%h!npYjvt3v9NrvtSs}? z<)s%=C)GYORz9qi(5f+BW;h+Y!SH_$a#wW72?#8ohUG4tl@@2swm5Hdn+-+%KXFBx z3@!!PE|fz*T`XEkJ@g>IA}yeEmR3LgQtkCQ^ZB7_M$}PRo|8_Qbl*r>l|-Z_`uG0UgwGj07l}RHvHRFSxpZr-i*0oKcHR#e5Bx)b zouQ>ThC20<-FL&ZK-g`u`-Hv90UR>5K!wM;FsjtZa1ezg&&^orH4coBnm>H61pu@k zc`jJXD(Oo1m%Br4jY{JuMGY?Uz81Q;CMXvzba)r0c{+ThrE*q?5zMG@T^@#+|7^P& zFyoY7-*P4^rc2CEAatb<@&3Z_8ommI9qJi9r};hP(;VUX`zylOmkJhy^z45_#H0QN z$Y-#v@&-QSNDY$he#QeHCdVEKbpyVLwU||PJ+3m|++{y2JfAKa!S0J2y)D&Y1c+eD z2@-@lek2-G2k6!7f>AwgXEP`94anh5@ z8|iW<>LbuC9 zOY5~@d2(IdoZlVcL|Z|m=`!D6aQ!MGuvU5B=%LW5WnZ??W`DENRxWQ(mC4K$&O**Z z=uzP9x4;YB2E`sP`gi3_u(1j1KWs#APe^cMHPQ<C+AA2xvtY~U{t;*{tnbKxzrq1OB zuDr=a_&5c3chtFoTRIcunq_K|3Uz+?K}vM90L300<5z({B;N?vdgVL7SCQA@v4ij{ zGnQ*uvDV>}CFtlvnxZr3=b#IBN1l!vg|@$xPLm0OnJAaN?x{cS^qP#8d9Z51pc~_9 zE7RDeNA(N!+KOQ)qCfVq(X+2tPT}q2Lo??>=+MpF zDoZAs28z0TX=yk;N}|P7?9*YoykQ4hG%wVfA4z-NV~<^_gh=XTU2xgESxi=r#1ZKu+T*bTiyl{0zzC{l45AD$i# zT*PX6IqIlnVmuI4s9A97)|Y+a519!bc56BI6pPHuvw1@}_GJd(vRf(#YX_IS>h;sP z!=&JPJtp_95rx7IZJ*l{GK2-W2qAFtIGm792p)aV#G$FI+mbMF>+=F`{5EqxWQupc zjN%lu-}{g$;##1b!mqd+vdjvOl0;z9nX{hs+jg|1gMCl2;vp^V@@Oe;U%9xdj=!Y9 z)6V?^JsN%^BOq+q=gPZYLsRQOM9{tJ7BJU|bwk4VI>Ue)mr#X$EeA)>=Af(6I-mJE z4m5c&Q3No%9bg7-EDYP)Y1X>vA2vB$DYNR-76QsmzOyS9>Ag{6=3^`jePHH!6Z74{ zuo2_{s+zEEus!vt^!uKeBvz*zjlhLX1+%4E><^?Z)AL!XdbFh(Ddh=*aYN~(#H{)y z2>nOeH9NI9H?cp#4Zyc>HXBtY+-divwMbizD|G*GU_?{Uen^gL8%5u_tC1huq5{MH zMSP`F$ruQ9&?b~Mdx^snIhdDr5{#_mcIJc(ZDH!?u|H8|$5r-doHj9+21{x~)}Wn^ z?c^(NM-^)1Uw=b@y!q7!a&AX375nM6X#2>71lxhXGt8vAm3MlpH#>0R=B@?D^!D0g zgoTG{W%~6@T_%RTLtOT=&C$U-L9<142p=0oErSN#DRYX3+^m3ru4?vT$LVP#s7mdw zYA|w-sN8PtV>C67KE1SZhGu)ir!GYT#(Cb#)k6E5QyU5a1tm?{Qu?^Xn!XeZ9G2N4 zB8BTEbrqXOIL;G!Wo4yqr;jFxg2n?n564Mwa2xzmsn-tf4r;8ZSUcmxuVI)6$1fnq zXiL|=)i5kWJ;%S1ZRxgq0P(jgerjMSWNl5fVJV#rl?s6BfeYG= zNsk)|yMuC@bRpdLO(Wxo*E(O=t z3*pAb<~x^GmxJkwN|c)c6#cW270=vDQNaNWp2XxYpWji-yLDJLh()&80ZESb{chRU z|AJ6QN1_i?M(D0fStjReB43{&9p$l9WCnX|u@+_W;K28)Y3A1GDH18iS@&Yj$0eyVzj)^@+~P&rHhX*e&Jpxa?Pf!Tr|X&m>N%zOihO z*47*MA}@eIEadBRT&@Kh244MPc(8~nvB|-Bd*mv*)WyJwO88o)!cEVm;NYbTPeFsK z;f|{&He@D^u$)H+qX!%a@5| zmE~84C8=DNR#NVXw6(shI@;y-?h|QSm!R-mjqikPM(%KNeWJpL+ctEG=EgLX8*J5LP-iKB@q@{8 z)brQwYa(rB*2M09*uo|s5tw4-lG!;7D#n@9i>+1_uNr9qU&fldw{3w~8Vjq|i9`(~ zK7L-?5xf!JEZHO%Z5+koOy0>bcFksUv@__^v?X!W?i(~viB59504`p;Ji<@adD3q4 zKjw;I@Y`+VN&nQ?$9&ZBLY*^wd#Ap?yp)lz#Hwb5My~a1aVbxESJvBnuImcTBU&r8 zuTLVoxdm70PtQ%MT)ikCAIP(P(=|tOP-JGYNaKB_!HB7S#o1-BNhpUJD_f1((R9JQ zuO>s1jqRkAeH2x-TgCLSG{f%QS53e2MOLGN1zV8qXv`s~7iVE4eU4kp6Zh_E(RXnYveWyDn?5MZbMvzSR7bH*R~P#W=bmv^KkVct_vy;Y*>GEa5Jr_D*a}!h`lyb6ELn|e=GG{IipZWQ>0FAPMNa&LN@o-C zVz!4Y=cQ+Zt4^bN`Scy--8?Xw#|N=ENZ19G=XZ&B1bZpf)D?=;3{2*?r1S}Y-mg=%NH>;x%xcxPDH*d9;Eq-ixa6%$RxV{SW)B%Uh~w-yH1 zL}--=@M;OfnZop#J;W3DrS!7y$IlE+M@j_AGb>kWB*(Ih$~1p!ms$XV7TF*r_h-P* zQ&W0H#3W)kN(7CKUoJGN$}5K6xH_k7-)G_Wo%4B^Ay0aZc>B4=YdP4u zGp;3^s5*bsrz_GdugOEV-pBN_sTCMyXPNzDt;t;JWWlwt3Bwy6qIFEAZghQ^1SRm!`!oEqfWPi^le344Nt z8RkF1GpZPl8>rWl%G($BSwd_-9AN@JivE1gT8v-aYO|H>(#=F4c5M*Dx8qKq-I1=h zC;dG1DdqF0*0#vs${j>4n15A72wr%^nu(=Wr>DYFknQ@?^B5W|wBa zWb&C;6lo_Qii)1V;IX(G}eyt#_LvM5;3MlYen(dDA&!r|GeL#(O%S<^X7Ny>-6 zr-qN7R#zvzJox@Pu#)j)CwSep-9>Y5b88vn7fF6+rvVQSk6#%R%9`=};m5IwF--%v ziyf?3Ozn*sx?}$}Phg|W9Jqw7O zB^8ED9fSn7`Y=3I>=Cgp#-y?``wpT<1Mk(yz3()L^mR&??ucxJn+y(@^>_}~7?@Pn_ih*cKyO}`|J zclXSoN8D0sdra`=hLD1%wng231YgbInsT5g&;Vl<@eq(PLKFrT)V8WMgC5npGoNKo z*IFda=a>`u>UC>fNR(HP3cWN05~bM;5pe%gXk9_MuuDkQPnu?MW*OHq&meAoovW)0 zk>+@{iVMMWWjS_ayJEak_o~5Q@v>&d{2Netx(cYBnO#*psT*tI73X!bMSF* zj;!K#NQ;M0sDI&IV?*)6>>e@fP(;K5DC@ck-J7f0*7>T;=T_E3Hu?^AZ}*UOn;Dba zBb?BpYhCcLuN9E{ZGKSY{bpn$PWnRE_rjG$JB{PE2^)iYLn;NW4~^bGY30+J+F_Q5 zPg&bBRHu`Arq#%TANiwm9&~ig$G_EzW!SSg-|y^F>X=a?S2i?gn46oo%jV+>>VF>0 zn703DHA!gB39Peo%? zS=>~)xUSM_2IBS5jEoYO$Fq)q+|aa@+c|(8W8O4|(6_nU2iUB-dce*;N5z3@ma~d& z*KUuK-W-ScXkR%GqY}u5fpI3()@v$sjEpoY0DL6;oU(+HFkG4JubK(vr1_MYpZ|>L ze>lkGI9}2$9%AL`Qb}|yJ9gTNR)HJZm#N*ytU!V4WW%1!>&vB=50pxzHq{G9tY%@v z2f@zfqITW{FzB8=`yYK$u4pOSau*6)O^tRXdiPaL{dR-eP{G1O_tPdz-iZ45>us-# zG4@-ohzIi5wLigMQ!Xfe1lURUg>bUvbds_k$xlM5_!=aMyqTV3CLaTeqt!|p1Z&Ql zerzOC*zN2{CDO2~Ui>j(rWBKkAW~X+ibh?zNxb_qzFK$<_n-&yFpc)S+{J*9V@*_7 zal1VKo$y?Ax5s)mb--E8(7e8{<$*rAKkglrTw=N=Xz%&mcnL*wwvehK<6iauoXB2E ztB$cHEBMPyN>KB)r3?@ZH(V8mC6aj;r54Y!d4o);QOH?UD`!(y zWx8d~!e%SAp69M2pZg*zpZm7qTbZa$$E7!;eO^9`VSB8S+k5WHHdRZN>NNxFPjKS* zM3wl(TJ&zqOT4=RoU*Q^Brbl=x3k}#>t&jbXJ<~kW_{kyonjA(V?74|eD^Xasj2ev zd6b8nVnMY6@ouw!x83?G2;J-!K2BIsRg&@KbGHLCED9N|bY1d_-ZNOam}cBl79U2` z`lYT2D66Xz^04w4a{b=su5^uJXpWtk$8Cz8xt^>|iz6>ib+}jb%sO;{j6h*bW()^B zmMV+m81x3H*_~&j<8&@ zG*-v+Wix*K>T))XXCQ89r<+{?6M&Ml*g+l9lLrF5Bom3E{`x=Js2BERX+mDqi#h@O ztBMdJT{D*ZnA!1TIuZURU?Yoe@YkI_W1T`|LS!qtvnlfC-s?b@gXcNA2c{@NgNKes zbF-UFKAOtek7taRU+X3?_R9V5qMo=tgD&->AwO-j!;@nwwQg$TH3iqqbD~D1fK@JP zDau9jE!M?N6GpjkoK>Je&>R}rzgGjedujG&UsLa!RFl$p)R6tnuX`svc>9>*oL3?CO z`Q8VzF;{aUR`CqhyxSF-LJA5E9nI2%U%6j6_6xb3)Lmq)bir~lx3I)Y9hw$!d?R~3 zBjM>%ZGUVeCXWO*enb~fYQ7}`7CML8mXzmo_~^GYB)hdpte=LxbtSWLHc(7Y|G#+q z>!&!n_KOz|?l8E!LvV+|-903@1a}|YEm(k{L4vym2p(L64Fm`bHn_V>&g6c+Z`FJL zfm22C15?#Z@9uqd?`yC1Stc$XJ0tDIqTW;If_E*|Y4*}@Ys;o8@~h)Iev!HuB?@WaQxYAHUtMKcW1^R$?oOT|KvBb z{=LIi&k5U(DGbPOgZgn^=C-M}GHW@mp@Qc}8kL#P$1kn?M@YB4z}tl{yunRT&}U;} zEM@V_exjC+hNSjD9UkWzg}mTq^qBOgFh*7b;ZhUh^KQojQNj9}K|-MH7dsbiMfC`L zN;LHhFq3Oj7b?qxPNIJ9#;}e+uWS@I`$; z#+XV}nb=~Vxe0P~YhEC4lQSjD(^zV@F%>12&h0e5splIU?$WCl0Hy-4Z}g~+=*iMa z3TItNsVNJ2+6M%fY}=R|+L(3{<|Fs*5|xu?20ykil~(chd{@DT@KzNYTCMJtY;z~p za4gKU;3h8Rmun|7x_lK=+;dakC#kZ(Xe7%dtE8PsBWvuEpYs@TP%dD z^hn=xqNuN$usOEA?Y5Od6P7B$n$UD`@H51Rc>KBd$$K9r?70F-^;tO}=WPL2@>qjO z=~Fwr^s2`_(=@ugNqHkF>a$4=GK&AC+jrYIRhMNjycWmxAsVksW8GYouC#R5Wy2Zw zpnZWo0pyX$1U+jMrn0NX?ThtAJ5(6yqaRD1oYMbNCXRfuvwPR{oA6`LRL;Av_~?r5 zsIQ~)b9x_mmBfthXp3|0)*8B{uMAua;xMi@%PC4h9~wo)MDwD3ki?26cW^Fa%^(GJ zH>~m)m+1zEMZ>jXg!c9e`owB;kLWG5VlP?$7bZcQ(}|1DM4!S z`vh zCT6}^>s;IqJXa(IWa9Uct%S{j8IE6){Vb7%sLIr;@o z26^}nF|5@$#PCK*HTq@YfjqimMSi{pevJeQ*efh_WK9^ zUY@Sv?`c7ho(xTFF2BYK(*Q8ZB-Ku&v}$#=`>=ixL@!;PVkhCF-ifm^qwz;NRMFLb z=AXDIl}bq}tHJssnz}C1`PFDY4hG|7ub0zCK9**d|KzpRDV2C!-V*T8E6rKX)1t>V zeziORLk3mvpYOmaO4U7#g@4kbkGASXG_0B$4w@yy_ZZc7!i2CJe`l%+Gp`95lD$7~ zI&rp;b7&0+$Bxd;!gzWP^cHNb^!v@kc$7mh&81aX{gG(UGjDZF8(jL7^k`F>n>X&B zT@p0p!05A3)z*ZWSoU62Q&u7I_n?)H-LEh1RTPGGpAH@LHS$UdixsO_^2_@nK*Am3 zs$PzVQpWLm7T?7r_7Q7gn}ikBS!+x>WMg~>CN8FqrC^$;V+==`6C(v|Rz1Z48Bc>V zt=Db$sw{!AsF1-p1cT3QwttSGh(5ey?A9d^FkMS)b7foY2Lm&p$sUzJmD#ZB0<_;_ z{2Y&%npON~wQS;8MLcB}zaFRq8vaRhvEP;X7y>?a&@C=Tdzsc|6t$HhWxgz*PSwK0n?#mQT`>;a?339J*8zm`er== zajzL-36bMIQXdt828H zE96cNjGfn-OyY?ptD@McXS(El_cudc<)+22O30SM9)EvB`oG%b9``*=BJV?wR}kbvKUDfBK$+(j@ntpJ?HG#m?v* zufqgdaJkLkO$c+wL6!sl-0&NCxG3V9m7_6~wI5xdXvaA?wE4L-kp^N|O+VCe92Lwx zqx`J(#t1HH!8n`u#CcVSr|#CC77vVg*W>oH^=zrm#z8!fQia*@i=CrBIesSJPgBMC zqP!E+E|?^1T$#sNbx{Bd0ojYXZ6NU`Oe`>gW$O2@R0>JgrH-;@2T|i(E521hqVm=G z46pbnUWU~9onnvclx%r269-ol;Z*L$wS$2xFGFiJ#Y`1uthjvvt4pt)YneQrs$Luo zQl;y13AbTY1QT65g`p>0UwgQ|3^VQBL8C^x*^0BjaigjXhAq|y&Q)d?y87F$`ifO@ z-Y2qp#(EVXk394i(+9@lc|6iWN^g#3)0J;IWr8OTPK$MAk%udI4qi}~>ZhK{R{c&g z!{(Mcbun_W=3s+rpSJ0yB1jGOtaH$Yzvep(;a#b50yi$EqQ{N`RMPCE0j3RXoB?zz zQTz95r5fLy-G-}X^`%xsbsW^WMLBB&ZGR+jDIdtDZFN{Wz?O(sHWYp!&*7QytTL?0 z#m3(cImWmK%DF-a*FS;o760u^IiFCfFz9MD@YJ>pFnULlbHIUq8P8VTwkn($-c>mK z;Bep3mzjNUY%Qx;UE$Pxc;t}ov|9S<@Q>lTpv+&xF8TNcr@3WHb;H({59~h84tY;K zfdTRFoE;a2^RP~RBi^~#&yP>G_yG%WOaN8vv{GcQLT)E zYTsWh3*O9`hau&Ahx!9LqQz~x^;8)Pdp6sLM$8%e-g7E?Uw+;hpphz)$*uI_yF{lb z2Pn#P9_F-I8^pKH^E=u)rxEM5sMk8UIO}>E>72wh8;WAIl)8Uu<=3m?UaN~s7t=SK zsmaNZaju}Q>sXK>+*aWCuuEY|s+wQIO(zrRQqdj3T)gIy74U!Gu7JsL>Z)qWrH!{WgWlOOlnK9)mb4is#fq;iX(JrSG>ytbaXCt0X$wYuuQt* zo(~@VO#1>x$V@EOxow+9Kt=3J=|wb38Wr^p-ZvIeiZws{p{}sFN@L?>T_~F*Z?Ty3*%_SpUCE0@?wMed zf31+1=T_t439>d<@rz5?|_x!(rIjuUrh2)Jt3g#CA$XJV_9tNRFHg@aPc7rVLshiQkQ)V&t#oj~#1bIF^HF6(8T z^}5ScI{miN5*AIEoJfPg@~Px@O3xrf%xZ@B+jG765IGgg;L2bee)kM7Ox>Cw%Xsi< z>PwM^n!H|0!8>_rLu)@=$#36icE|ISzK+L#;`d*ccNiB@VP9ORXroaap%gHsuNv3a zl29JW1!Xg-=kBr>VR4-J-^amJQa^gC$%8L-#c${5mK!X(EmOWg8z~C^j9-G;Ceu{n zElo$g{nl#m#Ii`a;ayyzSjmtQs@20fbfG_4A~e&p$NU&aXuGnl$$lJUO*Kd{~r{?%1RV znxE~l58get^6vA4NpE$_92fR=n9)~nay2I6<)3x3GOG)BhN`MqZd~oTk-0vspwuy= zw(d-1IqPckL@&i4Ad{hXXG!SIN1;(oExx@K+}R^$k>sjhX%{>fcUnM!y^^2s(~0*rxUF{?vd8}DJN2ViYw{z* z9oToh_908j$RJt`IP30!`5bSy(=;FZ$u@6B>67md@QL2O|F#aJ5cSY(5r%OG-n()6 z0MzbQeGArK&j)a-%gToD4j4n$J*UNC7O>ZnC=B99-wdi#boRR|7-&J=aiQjdP&OY! zdO+;M-3S5>@EgotK`r{YUyP%2f1`+sAm;;vt>L?KaptC&gO2G;_baTLykgh``L4ZC5vyu zG!>5M(GgJl^2B`o>+wu^TN{%cuPDQY{gZY?&Uce3#opcA+&n%^hn${$p9q-u#@cB6 z<>;nY))gAQeKLFVSU#n(^-_Yw@kt6GS0YU2?Ir|ENmA zlvI_r1wjh|S}=~=^8>&<7bWBE2k5j=z^xP4J;42KtZs*&n@QP6XnUK%G2xp0IQ?J| zj~fq;@fj&MmGEPf`LR>9*T3t8N&!^Ek+}cn0<+U`RoSTwx_ApzdJ9Zk#J!Q3r+r+) zY4rLBY;)%J+*SJ$Q$fV}wcQ%IULA#nu|xKccLNK8~Co&(AZaRehXgVL@WDKIR+1`K|JV5qHAC=vD@)<&@6DY z-wzN0Yqb0SW7I}0&!cDlPn*Ov)5ne*BZHY|Hk0TVZwdq8nChw=*ixX=}NpN@K{XC+s=$A)KASt zy(cpoHCtc!kaiO*onz`Jk)QbLR6^fFFNKhswmT04k_JpukI-mbkTjhU8W?XPF<5@) zmmxX-8iYBpB!*CilY3EMZjR$iEsS{uD_Op-=OYQE-&YVCgxaWYZK;VAwr5?Di`Q0C z>`^h%@qxqy!Cu?L@owLOSXn>-Q38#p&O4{bU7>ywi%`^W^#s$Zo64J-1@xCopM zb6#-cC}fuh2O<@b3&&jRJg+8&0=Q^QsgmTk&(%;#p`UDo5fRrIBN6rnZ74M~16`kb zFMyz4PzH>0ckdm^J^^#U?QezcD&C^a3I7AIp2K4psR`o|B}=}xX;z;F-*tA=$nAfA z6(MqEcUR19NPKk!4J=Iw2s2+qyr-v5rP?BBqW65J?>Y6(O3+Jzg~mbl=V17Q(=H_p9??B zsh#g8{>l+6V!Wmf|Fup)6mma6-KEIDm*7v8<_x$4ImF_i8$wYuQKBUKV`Vbn?_QtI z?vTV~&|QhcWBW?z9bDrL4DT^F zBGMYUejRUli01SQC-@wJ`W6)dj1W|CpXeqU{9IghE9i@YrX>#glEwNXSuSNN=LpqQn;WItbc6YN78NxwH=jAhK}V)nU*tEm3pf zLDto;ysRRSkrF(g;8H`pR{Sr-w31FXZGW0B2zZo%gBsw>}+;{(9X5o zum{O0E83BfNSDfp zl7R*9`fdP%xkqk9kKKfBKoonXSfP#V3p(U8CU;p-YSJG`d@w~(bRd2X6KohaNWg*9 zwtJ9cYB@@PDQJ~<(cLWj$vs$(anFi;S{33ZzG3m?O~s(5#OAkp1&_=0kdICur6lgXnpVvd&tk@n6@pU zk(Yl&zB`#KTIBMdvLv+q0C6u5MJZfUf@XqIX(bw}aKJaMQkp&dGqi9xE;K5#!8dy} zr{}}8Z4qtqcC?4*;ZT!J(1O)xT*h26yF4}Eju6_jC#9p~9db~f$0q7&1F3{*J z=#D%PT1zLcy{|h%uYd~=Om^R<#lBeJ!9pi2T$6(2`5#vL!`$v?bBeA~Qgr*cX`su| zl_kbY(R}DkIp22jT4>O~Rzlt%YGK(1+E^VnmCa@G!f9$kZKut!{+{iTmoW96M>wbD z|1c4M^vn~FM_|HW$Ma|lIhHRxxdewGXO?GN2ZH0!(f-~o=R!Xu9GraGTWN;p#gLaw z&hBfSGr0Z@b0^lp$`^VfVdm&8_`G20e@xpTjyy7kNkx7x_rQJpsBZ%x_sQz|o@L){ zg|}`JKm^p}84>bntbEokA&QvMKCA1LsiQYmMiwNctZJveaKChH0R(`-O zJxAJK(~m1M@tc2-hUfTjR_d5}rsE7*`aqsV^kvL){)@7jp>5-m6*`-W3oV;~bVN|mP&ozTCC}9tvFJ1*s5d=p0 zBohH2=h;ZT1_Wc%^V;Vq-p|!1hiBb~!048poqw~u@3=#sRgn^Hd@k7z&;q37lliCK zptHT%4q;0<);xN10DzOrQFu$cq-2X)I32jl7c3{R=H!IB-l$usoDB?3L?tBYK{&{H z?)9$Bn$g79Ru1mnQm{^k)jLr{~?Wo&T|*dLb`u!0=aI#W?;*4{d`F3ExDnM z)hPbUZT{37Wk{GE8L1|TiwBI81xB$3>1U;emT`cw1r#2&H#hs}70Z|dSsN}E%-`EZ(;JJRM8|8akQh2-&iCRH zl2pv(DsCn*qtGkxsb|@|3G2Ne;gUnVm=Lkk*zz|fE*=qglbmPZDIw7ZBThy{VhJ45 zaC1W;#B{N*9-!bXq=II-zEI}+pR${SLC_Bj6k+G6l)D$Q3k^V+1;qJqX0BgNM*LYuf`KD!kk@OkO&<<#tn#=>Tr2+l|&jy(dcvZ#zX z-U5VuC6*YBaWN?YL|M~ba95w|>rtdD(7}}gB0pJNb2VVa;yB^BM~*7Gr7S4XFCh*R z+v6F@NbEV|>9LvqeO!FbPS3$$pczLGKjF9X<8u!%#BA@7(4Pg0Q%glq^03;7KxS4!sfQL z)f0U_bQF`=Bmr}IhZ4HYbGjA4is7y_GL5dzSGouuSG+iU?Ostl!R# zQNn$HtXAmN*aI%0@Y`-6i5QqYIte}xWF>AH<~_)zkPtwJ<>m}VTqn&NYdL3v9-tM$ z(<^zx(;*g9CD1DrJe{1KLx5HQSE;tN0yL{0U2fV`R9!^p^Mt0PW*9~3XP@lY!~I9v z9#%}A-Q4(~0TJH2okxNqV+`#viDR6=Jqo8iP!g@Un?|cU@F~@&ooZc#8aaP!iMs!L z)8CX{MB~56U&Bx^+{3y1sW#H-e$EZX|3KGV)Hg8MnIpeNgHz}jn9{O`an*x&r=w;D zBoJpKMvFYgdMIRvk~}{vG`cU55V7TNQ#zqej7Yw^yKbHPXcO@ap{J|m2q`Zf$2TyT z&^I-R=xG6*P|16?Oo}~J9)8^jBNs;37Q@GrSbrh{Gd{Uf7izNJVJ`_p+MYLWW$%&2 zny{@NYp!ik33K@f#LDNmUhLxM2PML6O?)&+6mc03y&xjvAqI0i@ijuA$VVAG;kdkC z8fAI0VYHUy;TT(kH-D0acb6gfi;B;i zvle~k?!a&+&nWNN03N1-L3E(cVyNFw+|;o_p0#NL%i zEvaL3`Ud4CUf?6YViT6OY!nT}fG=CX7o1o|M4F4_pbfHERwu>x_gH!qAB2g-1}?rx zQzYjV_s1%7k(Wexx40)ufRSS1EL%?=r3`1SuZg}GOu4qH04{_qwg5&M{@V%F^H95>c?!>`}yW=F@^^ zaV02J{Xdegv(|%Lf;|(@e{Fv7yOpvb*|gpU8Vf~IFK&nxJV(1F2cd0B&+&z4qxZOP zU@kG~8SjF8D<)@f!VD2flOsP}45cS@=0zs?M%yYhYgf~y@TMcSFgmalDx^DqKETdI znc5FAzmIc8$9e=eXo;XjAwdyv;Mb-H{&0kL$qj`u(Zg=uUa2knjpf3beXQ%bzD}u~ zR2i72%zbj9)+GZnT*k5i}T<_GaNvv8^J}WhN1(xC3EUG%9daoB%e9P6@`acB0bM~J?Y=r zDG2KcFZKcF3Z;Z+l*v*Qeo8)GeBM1k@t+h}ynp4w-0sCt7nL-oam%tw)>s8yUVzdT zl?;O1O`v)Alh+K0EatId9nzn%VLfVOUW8U0iU<-Cs-zJ(F7i2QEi37Rf6bx0yzK+T z$A9q(#N2`9u5Z*UK*#4Zn=M=3oY#({3aBv%H@!&pXhUrW}JW-2p|c-kz?7SSWHmNdF_wC0kNY^@lGWUu2KPYbT7Dl#M8 zWZtAoD4}2u?5&+csn9W_r3V4Qg{)g{(%&VEw@G-0zn^~L2)+6eOfnpWEuEQ;KO5YKp3$o{aH89Q^z(^igt4J^l9~7mn!QxJp4xh z>f8waa7AqCvF@hG0Q%<(3NUrtZcV;@SR0)rbZl#FDLJZviE>6iR09GlXI78PjxbOB zmKKef_85)i^#aq(NHTC~4k52L3)WD^RDz3{9ZriTj@BrMNQp%tS+&8e)dV zZSBYV2}^g;4wCc@j|w4T(bu9G0mn+LF8S#4o@6$7&d6TqNws5y$SxGtwWlIzt*Kbb zOldi0N<;Tbp5PE70RfS)3iky$REr@P*I=8ugP8_|Y9>c->K-ZNt}M(a4tJ0=j{o!- zTbOHcOG4QCsR9Wvj=x#+cOD67aUnu)dOP!HFAwA>b*89i_cN|U~mZ& z>Xo$?#qsNz-l3#3tZ~Xl#RaMd7m>p~B%g|-z^A)8u|IgZ3Le9pj1KU1zL-lAZUig@ zL! zLOQM)r~@?wXjy_Zh!^1va6uJwxI7;Cf(nZ-aE(NfvVec1p{s(0Nmv6oL+5bepv#mJnhKU64PO^$E}4jR@x-h;}1i6n@* z5@X(PGs74P?Clwp^vix}kfo3nwQVwTB1(e0#1c$eF9|S2sbEMU7Dj$j`k*RdDe1)8 z8qSGQ;&}^q$s-txHd$HXKK;esm|9ct;nNetB;O_{U9#==^RGGOBfPzrVWFPQY1L}H zhXiySpRg@qEC?HrbY< zI$#>R2x}`8x9ef|>x(bC3L@ghMbS4|3Udlji@Hq#Z!0|wiC{9S%(ex=hc~ivwA0<@ zzzal+whHkk?69aX>6zK>VgIQyfi_7XutqV|?JY7IPmK0}R`k^+(3ra4)2ig+upvKc zS1%H0h4gpA45O1>lRSgD+y#a98*W+_DpvG6ngu(VZ9`B2Hglvh2pO8%ASVSbNDKaE z0l>M7_9dlHh8wxZ_nF`2`9^^K%ybIq8pMynMZy}U!krN8PjNF3!3<(jo4DNJ3i%_n zm#P5hEWzrJl!?EN*cf>4$pvA*)07?+r;q*+YY-`RH`>z1c?Uoz?D2Gk&?9lsVQaD; zp+#);!30tz)?h+tlnU7a?o((j4Hx~#{Y&Ydzc8%V{t0%Fu<{-#<_}6hs5pI)wzL&B znBOy6XA@2i?;-9~1eKS~`Ip-p2*NFoFs3jHe9BfMPpsHlwA2u(d)!jL%^SaHU_7PY z+}E{j`F9msmduSmQEBqS-~v$fBN?V;@@eZoC$|aSh1SY|nv(XQ4@<;i(M#JxcQNYB zIHWJ+FwBzB8v_4W3QSC7lzPnQq;TTGC=@KXUY}d6@GzNzmk6N*XM$XQPhJZ~&pvJT zl3pBh5@BR3Md$P!*66q+T_yUi^OAENMP(v@=WR@;|Nf~cg*rZzbGoZdbjc^9y7XT$UhrVmgF=O9<3_1O3 zYhh+?)hBp$DyKOMR_tgQBn3BnLqQm)O8!;h35N zP%LtVj-lZc>PAm#68JkrX)Pr3cr1nxD_K9}+hV%m#%-bed32Nvl`t`E*QUQk#O!^j z=0eQbv8qLq@YcN>X9C%pR1P6`S8TqU#MC6SLdsTHz;=LezVoIbiLJv;F1>NY;t9M8}*c`zk*Xr zOvT$-vvi;`5^vWJk_Ic#w~Jq!gj*!1#9|ZTP?3S#^S62oTx}chk|C_OagJ%kfI0}q zot!V3A)lT9PW!0l_6H}DaslOtShxrAVV!J})ptQP~kG?^O9H1T=#Y zo*E>&UXkgQ)Cn8I4KS>x{SlFeiMNtynUA@vj+2+R*0?j~{Vz_V_9Q9JYa&_Q2gG&e zn1kEu-%Kl0SV6{C0-2vHZ?@FGac|}0x=L$lbDzHry!?7C)n+AMN&c#Xjl(jAPfUzR$M|Dgma|(^;TH^qZdOFFLfU&|ffzTy9U{WDn zK$|qsV|@YTbc3`3#uDr>KAk5R%bjn&MIz1VF$KM6x!)%ahokjG;pRsbMkE|YN9Y&f zQ7IuE#E1qYEA7*$ZYJ&*?kandN5cV3QRy&=j{xSV!VYO9gsBWKK)b5mSm@NAafzx! z4Zplw2rAmROi<@SF+9MGBu#`=scQ z?eO|WH&W;Vxvx=`>tg!Q;5p~J{Csi*QGFjX&3pX>$O~fd`%&NqzSD<4(nr#-y@Qd> z-}0}{{F*1$ilw!TlLUV>lO>}yNij$`MhK8og-b^m1Xr8huyN(T=}i0ZVTpWc{$KlA zVtuX!YQA~@f>x|Wao3fM&@Qy^_xfwg^q2y5^k4c~4>V~;OoxWozN!pNgj`695)I?o z{R%@DPJQz-1dv9>;sy6$Vj*!V&=4enRsp8Z*lVJLR8MZeJ?y=4eg^SHxDo5R;z~GL znOc!h5cGZBh~HAapTxeO3nHl&M%2u+Dpsb|pG?jC2=BLmsS&=b+&=o%tJeo?ROQ

D-@fQCndJ@y${(p`tOd>F<`(5(0tI09@PVY`- zKp6Bt65l&DH466y{<^Dzda(=6+8ocOzb+)O*U0~HpF@L#DK^Eg?H_VX{F6AzW?@7= z|Nmp`#l^+ZYiy-;bXv3!rRUapb{dc>z|Q#}tCoa^$9>!0uwMSu%4e*iZav!lf1!{h z30Yaf(Em5Hj{^RGm^fM{rX+sN1J^`+fzE5pJToxtUtz=j4{(f)j~|mJV01deOxyP@!{UlwB9K@BQbOM9Rlj~2 z>)Mq6&XP*A*!6#aR;hnqF`N6w>Tx&s$lKd@v0qGx?`MAEy};xDsLBWg`1o9udr83Z zqlq%3n=uZ}LzkYFShHfB|D9tm56=Z2H#G54kJaqm(Nw#TJ+AtKAarqG_J70brKZ+} zn6MB~=8a*S{O_p#!&W8qg~r8YhNj)T9^iNOWF$1= z{!}Qi{Fi}hrDbjjEj90-KWaJD_qG3>o7TBVq5!LUVlaZ;yIR9i>xm3|7|a?Lig9Wx z=JwubrBI*+ZAY%dfC4@evVUo;UK4w#%9yKCdJRh+wZGgRBjf3h{t6qgOPKJcqNGF) zM*KK3wIUfV)G{)vhDGwJ{Qrlye#3WL4+fR@+{|Fh=Z1?B;3`&>LJE8fj0?H)%xd3D z>bd>jt!_&a6#uVrxSyltXq2{W`gNu?C$hC|dX3X)wP`i4xJ=-8kj?+VqVxl>qqfh+ zK5bEnt-bigs=Amp5B*2~w4gxLi26tHg#G*({C0$JHx%Nsn0dOg#%Mwx14f(TsBD%9 zR4A?M{@8W{qqR$i!hZXMAxqzeR5Okaump520O^Fptay|9+V<@^Mk^+?U$s=U|KaNx z3|YMhClguI)5?@Kx!6`a=^6e!~&qp_>s0rRV~zbDTg zFjLlpoXlGu|M{!_kBhp`crO*5NKy)p``#j9QuKSwvQ~NU2GX=+crm|f=(l*Ye7>Ex zJgZgx2+8AvG+?ES(V^$8v+D27?`4mPzYZ$}b&I=3 z62-M49SR%*M!yTQmhtlr)fDHm)!2l{e#0m(-p8}wy&=byIikTOW$I-0upC5F+XBB& zrat{nd0sGZ4uy7*Qli3e@BanwUgLF4Z!7AkbU>T=ekeJ!7wD`O1T)m;mxBW<>523M ztg3VJdkoascdPiw3~U+7u)mmzmfC3;%0Flm?v4;94ik*Uv88HsT$Q!hyx6>)PDviN zuD@z%{xYh;>RkSKMfLB*hH)7W9CBd}^5rJ$_*NMAQ7*HiLv$TtK@vgPEUUS^h4q*M`ngnUw^YBxT{d^mabQzy-KQcLu-zq4K2+mWcEwDxzvChFZ6 zI*nd=!uX+QNKxFBMhm0Kvv8P!9$*n8K69U0^0m>W^F`wY<_|OMYR|7*jNWXN#_W#L z`Yw%$f(3PcxZH7Yb@lBF*cFEYbhfd)6$N z{nF%P@>+Oj4<2;)zcfoeI=hpoiRL)^LK4)hvVP97gF{~J<(X&mWyov1O~p3tQg3f6 z#XzejyerE!wf1d7`=>o34zqTZi)XqW0_@qy+23SFCc7Wkd;4H^ZK{dVVcgP|7JX-D z=bjDWR1C}3;^KjTH;EAu4fInm^631`%(vlTg_h>#itpdQ2jCR{>>u0-F`F%!ehune z105-JUzU0MuTu*h9pN}HYErG2k{2wMI#RDy!jvlN_1)GHoG9wYC5LcG{j#p)g=$#CsKVVwJ3c+Q0XF#fyF{^ z#fC4Qlo}@>plqt1fM8Hu!w#=XQ_v<7$A_lDkfxgVjWS<_TyKjY`(`sh-}P~(?!Bo= z|A|`i>&Y0OLv7}5!9|Ao;T5ZywPw2e3`EvHDLN)rGF(m$bIwt5ExTk%%O@dk;B2{wOJI8 z(jj^K@zteP{f6_|NWl78Nx;dhdh+O96<_*-B(clvNpdZ?puo7YGyi>Az;5l_<;mo# zfk1*Z%f={)iWe72y_#{Y-CZk!v0V;~+KEi{0|p~~JS89(bUK%*gQalB3v{`HHer#P zW&e^dnJ!?i#;2R0_N*VxzBTo#``_=J=fr}4X!}Z-mFFmwFUUv=F$?C}XjuRiWmPT7 z-sMz7!zqS5Rt48|WGP2ZmSJ`9i^W#&hn@pwf6=W)425(#58=EE|z?4sE% zrmChIEdvv;FKeE&PI;ccgiVBP!%cZ?bD1#N4>~F=gpp0C+sOA84)-({s|KuF3B^`^ z|7vq}lX05=+&270OjY5#(c*HDOvNnj{p3i-L2)^b{`_MvB>?1f4(Uy~j>RQ{fnQ*; z<7H<9ACJl9$b8IUF|}(LKe*0Hx!OkAT`Y=bpP$3EUeD6qq8r4o60%3!dUA6q)U&vy zVF~D~j!!5r-8hi&+LOm;$<~AEc(M+*l2~5b6-$kV$*QSER;w!kKfC;B!Xdqkg016s zayJ@&^DSk~?S;CYLe2Zxi5yjqUdX&%Of!^{-k|&*x8RnwKuGUl$Zz6i0fCA##zN|P zwSyk9kUE}_r|{?s+4`Q#mK<#Xb)$?$`{5`)z4d14pZB}d%?|T_R7`H=nb$mSb`NCv zIm%7%Aa^*lO3v3D|7W3o-uXgi~ouS3&-vX6C zA_~=KF&eW5gt}RWqGCsG979$_$8+8@ob0_rKN1$|AhWGRYeS$9T^X081nw&@bJLc_J24cx{>-NV(`QQGFXgd<8iJW+~oVm+lHzz}sh7J2jd0mG> zpW3e_9=>>boi>-KcsK?j*#-ploCXAbUnpU3@qYGOUR$mcnj|UOf+qUA^vN(cZT*7= zA#{C;k04uQr>_i_5DkeM7@4SlIfhcnL=$ zn#pbTP0mrm{H*S$n^o25BZx9Wb@W^T62wG{g!0*;1G5bN{jYzQ zE0K;?DkvYAV#dM7CLw=NyLYmhPQ?@DRMUL;efNE<@uyz5?KSlEyz|;scD5aS4$%^0 zf9ZE{)auXjHPikD?Ubff`5uH^w2DrW5&gFRt?j(j_CaJei%C6ae@^0oV`N7%$I8ga zkT6k!(03=ZUeDXi_uIcE)^Rsm#?Xv!41BD{LSS?-@NL33jAkZqU9YC&^FF*J)~FP| z>q{O;!|=*y_pmG-N$)iMNRD{zyBR0f{E6dbP${+hyTz2^g17ARRnZlH6ZdKh`4oS? zH~m(=dQmgsIq_`5WAeR0i5(J*bSi`${?m1Q(e)iMh&BcP0M9>~JvUFv5SBGdoh!92 zps)w;XFHNa*>m=14d|-&lh=Cuqq;ZL+GL95#X~(?MNv&hcTD)j*|s#JT;b4`T{WH0 zD;!^V?xm?AsEx{{0=!*0ckLFG{@UOdTP9+WA?8%n^Rq;5J>TG)(ISraO&e?Q-`Qft zCr8~-QWRK*pILx;43$UvEKM^LX8h5kLDI}$6D{u0lm(mxL&6<*_`v^hLAYVGojbxm2xPr8W*Dw&O72PJHM^(n-m z)g-?M7#W#$h7>>AareA%Szq^vtz`mcm%uriRix53@+>wq9@;I7dAF~rS*z_RT1G}Z z;@B$CHlCXJEciMZiswckN1&pHr>YCk0z{5k9k{7)BE?3h4HF$MtHvAw@m&>jEAaKi zmgx-*sjt#LJbH|z>hZcX0GeEm!HQiIGc=6iZguX53xWT<8dNh;p2fynL zEQR#bu*YxGF>iM~-M6RcRqu^C#J0a&?Ay^f=L}z$&}&k5U6axkp_hu5H3v!W^kdtTlpi_4mC?tO|AO1 zcOyWe$Voyh7Na|E6xWD4{?%2YA;JC*Tn)@!hyx!z}DQR)ud**x(y2p_wrq%ZQbq=zK zY#2`dq{jJX70x(sXr-o&PjINtD^YHuh4oHPV1y|S8^}W(IQ3;LTSDIWON(H6v!`m} zySJu=SnP|A6T^9rE8;i~7grN{Ic7BwrF`_FD7OEnv$u|G>iy%trAJ5z$mkfY2q-C& z?nV$0sS!#^2*~IfV{}PMh@>K+2+}cHrCV~Nr9(z@A3opTKleZP^j#u z*Uq`#@8|OsPyZRcG760?gn2!(1{%MqatUQ|D+=cHXtB_`w4a^hw(ZAAKQKBeoIzs4ky7cf`NAcKscU zv^Cx~!DsF4;%i)%@t^5&T>rMu{`%YIz^7$yvO3Zo)B5-dKhj&NYVjvJ?`&xG%+A}&Ll2b8glI86;Yhe} zRmfR=?c$A@q7SK*YtS|s5C|UL>vZnqZf!JsJf18a?ZBS>uvq^(@Q*${otFTrwzkkU zsA8aX8dlX|^i-%n=clvtXs^0rhXwsN!K?{{jblKl7_achVNo2Tjw3w23|^eVl&0&T z+yE4AziX0x7JGehKj#e^a6ETBQYw zrf|vzq=?ikNv^~MNxMqD(ccM!9Ybrp2-fG^OywCaI=K;@s`r!=D`p2GTQ4caLKibZEe1TlQ zNtk8!7+~Y4l3-*UZFv z{^|7)_Md0XH+Z%2v)9AOsfR-S&&$P$%DxM>X#QHdSCc$A`^+q_)#%>r8g|O*b$P`z zzqh$Id=v%;rO+BZy+&_u&A7Qw%NaRl;1{3jlkES1XNoj@$A2d5$OKi>oXtOt>U@y2 z7Dw=^Eml#bP1GH4UjwgNlK%scA9x9Ndyy}Qp-=4yen+ERk9A23u>zT zK*O%x`-^{jF@OF=Q(`Na=4bDaRNxdP?d%d@z6@aF%>$tOzz#9?remi$W4^^~#_K)b z4zIZ)$njpt%Wro6jV))3lyfzO2De*i(_ZwoR1l)1^PjxZ&X;|=s^1*+c0+d1WAnnV zc@y`3Y$DmHrHnK1Z?P`;JKY`OEqmE!I4I6?LopVXm~9BDbA+8S(} zV_?}iq~g{Er|zm{Sq8cmSw4D&vV7vXfOejae+%5?zBqbcU*qKP1{;^zlbKE;S^EO4 zaXR*yH}LoN;d#Uy0oO4)lQ#P3YEJ+1FxWB5EJTdHN5JWe0w)7RuY z?#Zc6mIXce;CNxbMDD$RWYf?1tTeiL>(P`tPx7B6!;-TLiQDB-&dcPdOqoo@q$#{k z+Lo!^^sz(h9}PZhQhI9@Axk2i?7k^NW?y+XXhOJBU9ZWW`4~IEOJ=%{$MoYgO`P5d z&INTC(FlwRjHmpoO)4paPOd~<$F6?q`cDh-zBfI|3o{o-2a<=$w~GTwcR`ZX=a|kc z{p&dK{43_pJE<%OBp+klIUktn&6iM_4Z4CdNV6=b(_cUNt(q4q`bxoNM!6-Bz_Ye_ z+lRU4ty<&-D*sX;a`@d*s)^C&qcu~QABWhOxP!A+T$UD><_dS}uNZrXv?i}v>S|8h z#an#oO!fK?I_G`9hODGGzE23+U`HII2G2Xx%ISs|ndhkHGdV)kIUCG`Y6M@ogYc-S}-yRTVvN3-etcCchqnW5semHDwLp}mOM=|Au;+Hk;k{TI0jrSQL-A74UES|xnC#j;J z+YIGfjJYr`T^vCq|LpubFZA!O;m`@6H(Y;Kb9n&qkrME_dZ`n&ms=LLkucke*&}!3q@I`jb@RnWkM5$tMRN(Mk#*| zXN zI}Vpl5YJ}=FSBP!)B<2@u!+FO7x%6sUpj4G@0*Tt_y`9rHDL?6G=soKERN zpjZ0U+K$izsycR(F+|oxS-ilojvKgn!50(zfQjkv_>SPi{WQemw_8Si2+`<9v61Pi z(qkmAN>1I9&$mxHala-@9cE2eo~1^m+pct*Gx^Xc)kcXttRq=2AtZ>u6U!2R22HC@ zzx>7sh;5z_aPcJeO1jRjlOF+(f@b^>H?$~I}E+E6w zM>y8(vFTU$s&lHBAfF~D!xG(pfx`~Qtg-=hR;5!Io{oFbi7;k*uK112HA?#pH>}VL z=|J;*-e(PDoAa!n{ISPT%WriU0KpT|Whx*0XK0XS48!8`R%Op#lfSkg2}&D!L7!)*|P<|Md5|v zKXK04rOpQaTGfBvZ;mg!m=n~Nf7OjjBj)*Imio7I*m~vNSD$Y!q^ZTMS-}zvFq~#R@1rQFQkBpqB*1>cwnSRt66PTo`@ykcT0PWi2gs{Hh*Co7}W_7LVxhAZy_NoN?z*Q4_$6{WS+><_Lr9tzQ?dq;= zV#+@@DcgmN8w5WsbUF0V8S>Ac$2SRWA3p*k_Zs#W!d$72h!r$g4QEVLT9r>^@dyg{ z;|?2Y)IN)Q{M|e_8F3soH6`a!vv#s&0O_GGW!6j6t@4h|0edFHKy zE#OnDKd7wtU$QX$S8WGc$N%5NB|>7>MLpUqG2>xELP8|pg;VkmU2TAmlHXME!f_L> z3oRBv(P_^4n6gssy^K!A zaA6nyJ>wJarbH++2j%tgkJi&ygxF(%LOvSAgRTYQ=1PLE4)bpGA5{G17aMxPBNje$ zD@)x#ejw+WiW<&`DuP!Pw%nU^B}AfntcX_+>ma`FCS9%Y`y>z7FTL3DX+2a7!w*Iy zNTXGO6pssLvI+L9y~vw_Q?Q=U^2&+;->bcG@zue+N&s0_870m8a~*{saF+FFO(&rKZn)fHRtg~#jprsok65oZ8-yBRTnjv&8;8WpG| zOx*0|4%Ycdr5%|*e?Hy3+KcwQ0^r&SAaBjras!hP z&_6kF^7X9;Qt>95C#0x}--UF5wrA@{7kosd+HFHaHysiD)IfxJ2@t2#wY0xeLlAkz zwaBj@1kA=}?4yA_^2~Qc2C53*ZF?x`>FIqH)IyKe-mvhzyUp5!pI;HDKf~u)z>PR?#(~#Z7a^%(+>OC3nVQ=kAfY0usl7#yr0j#dIDdfiY z(!7Q`Q4kT)c!2BkMk!TvRWD9Mgc9|n*$3m=*XEU4R5C9AnzW8YFj$sKHgD)yqLSi! z4-xEGiu~@tmL=BRJ=_7nZW-J-QY?XNVLwb%hV*_X?d9olmzK~X=pHt+jz@S72=_Mo zW*0?OZJY4KI01TqQjKF;v0_lqe#-yU*AEDr{fhq#qpx2t;N` z_Lgi5aP3S=UhAJcy;YT~NZj6YNjwN5B4uR3>vox=8@ni`ZvHp%B2YmE`i3n&e~*ml zF%bop*h3!H6Vxfb(b%d~htWVMLR5W;38$skvX{DuZG475skpG3Cu;%|`1orKCEPtXtaO%2-+&cvL$ zU_&^q4~nCc(Pk4k++T&aqDauWKf*W&sV!%j*{Y&w`Ofs>?X5bA=4G1VP;%I;?_p1{ zv`JuWqBlI58WIq+3}N5j$noU5Fueh_^Nj0caoSAWZtgnhu#0Oz8Fc>2SF~~wn6i+t zToYl=Kh)hQ;oKY%&TI|#PH7Ki_%)WHbbh3^r(T{G!7qi4!0_?;v1<(}(^+nzr_+EP(< zioxy((jx9n79D7uQ3#PfQDE`BZ$FM}y$)=RcVB5L^d0$gHLoo%%Qd+D>rlh|sRyrK z61$(FM^~d3Nh?@e3}qyF~Oe55Wf!5yi7K00N2WYA(LNkB0k8ELGvO(;H9cqEMC z5>~o#z>KjzVk1*;Vxeof@#zG@pYB;-=t^M-Ej+sDWw&T7=&m|{ov!8WKA})J8n#n6 zzf%JA0c$J7??IN9p0)K>#f1@h=w9S_PdvYpv55%Wn}O1rrw;300o&B{a}zPsq46(7w-pHWYajN)^!7Bf~|PA6kNHLiNP1 zwG*hy+9}Yv2OT_&Sn!`eWV1SPmlfnjkSoSqP@=SUQmcB83Jo1-gXrGP(w=`MtTX8p z)H%-1`<{H8S`B*75r5cwScT!#9RdyY3Y904B~3|h-m;gajItF}F?wr-Yna^lR~g)l zn@wWx)oWKe1-L6`pED)G_%CH^UZTV*|fU;d+&kK z(<&Y#b?T-mk}a}hl*pn?DoHI-uMg^*Z~%t9ag-OGaTLXWm3Mv09(+3uu!J1W8*0=g zKiGG#7T!odQfp~X3A+3@>EDQw=M^#(ZCK56ZsJf9N#Ui5o+bCi_eUy)UG_!7vs%x_ zE6<$uzcv6M8*Y6q8cr}mI!Dxdm>omLj0>$=YUxeSM>C92!xV`!Y<-Ojf**b$WQkyk zxE;axnaz!Y(Pi~_W=jai{!?p%4uxBZq^1d?5L^8YE?e7dsk?4$M4UYsRuMlEB&%(> zD32w-2+ec4$8=d^^EA{bax#kvLlCU9v^}0xW+FzO%%({J4ia&tQ$|U|((Fftd>Cq9 z$Izo2l|3yT9u&TeMPX*AZw)GKUv#ivRo&!yZvua+tyC#lSxgJRRkFBQs9({w(fut9 zc3OenW1~SQ?+B_| zP1f2=&Vdu|*eE45%XwrS$1I2noxK1ex_iL9uQV$7F?4BAW*3^btL|o={*&Q6v7|5j zlIQ@04_K5=qZ#B1NhUD)T}Z&xv9P}p`I7}5_b{}Zzf-^w4|WaQugpY}4288Fww(66 z9qa5Oh)!dmr@_~_V9Tnc+~=Tsi23t*oUCxg^?B>{j10Z(@z(_3e3b}fQ+La<%-x-& zb52(jNlQxWen^tlz9y|z;f7w|UqjiQDE2J@^k&0m#b`p%5hPd`@8AK~y8!j8#nVq; zXn4)phc$fF%}%yn$!$ik;&kA9@BLL--mn4Z%c37LrH{Xj#)jMPtWLl2!?8-q!i~Fv z`L(J=5-0zZXuz1%{BiA%jT@a(Kg5f;yF8}qgQ}{+t0PLMG%$qBy@_P(gx^cRnx8`C zJ6ID-)S-@{CF5}FL&#Nl$1>lEhuRET8mA9<| zncUrVzXk~_3&DE$J|d5P1KqzyW+!%Xi!zH{ol=J3yxX=-)9FXr^YWb|W2#eJZ>VJv zoQ`?!1Hh?D7x0t@odIFnYueHQy+X=hnRY3NC{iKVci!2%VdM|?)(RHae5vuoT8Y}_ zvkj^cYnUcFUJwnIB~$@M_@(g#8xwdEu=!%)fapHa!>|u~|@q$d9Ejk4BqM&inL& zu#>bB@ZKm|LNTtSCN(Bfdcgz8@!dh;o?`~}bEB61G{E8@43+8MKvn58;*AhF(&np3 zVIv@MG`gHtNeQK1$*ZMDhreAQfyq8qe4PZ2(f_j9sm-SZ(CG(}B9QEs{Wv!`6~AwY z-T~i!#BD$%cY@Z%o)%)YrV&HM-?}et)==bxV!jzrL^?e)!{Yp&5$&YWNuAFYXt4j^ z{2o&BR8K zEMs1d#s!YV;fmQ`<%md-lx~9E>56wDTIM6l>X>*MtPBS=O>`$CG7gUZaKO6MCxIYe z`*`bP)#k2sh(-d62Py<*9#m=9H0x|Tj74!x&{*bIsZgZU`dW^Noa;*^$w@JEvkfaY zsP)oZ(cvQm);O9WLsJ9$TUtW7dur~U!tJz79J0@+@1nzQkmj_2g2lqNanBs&@K zr55D2$BLm?Cv55J?oPgBkL5+iT%O6y$_*+=aTJDuNLxh@KvHQ{a)S&|as&-V#q?X8 zEr@)ePd0#0TiR+WFN_QI@EB$lPk!zmSP>&)D>py`!lnCC$>a4(*HKxse+a?)Q-AK{ z!^zu+hb4N^4s->&2kj&rDK#S#0c+(s78j~$AAa7U3%+DDc6iRVZ!qs-Xm_mgysD=bYcTBmJbC?M)mtqR+WzT!A4b-%?XKJt(&k&H-D+H;TG zk^F0K4LDBcs?hh22l|xyDTwEQ8YlmFHOQ3O0Oa7p;h5rm^jayK^Ig5L3zJRa1-f}L zqiw+OdC7ex5Wb~fZp0gw(EiJ(#RkJm)1@eb(1xvVzXGn%T0PDBu5TUy^dxCs$MYcS zV<^ca*FY@6D|s@hJAzS3+A4}9S%yl6cWS5}-tB*Dr|ksh_Hwec(}sH3y*y*nUs81+ zT26UgLqMSsOzn;o)xYVq|6f-)2hr@+2P7Nx?vr-fkoCSVNlP?~k~R4*H+{!PLIehF z!-}Elw7cZTl)G#5P4AH&QaAfd#Iqbo23sraZ4sL%?+ry>PV>)Ok~t*XC`e(G*ZdRC zLL;}uI)=5~r4}#5YW5jHxQ>P)zKGpfDidvTJyZ6 zjUydsOX_k#r*J-4~i-abyv#4jGa|-y(S=0;+&!U9Jn>N2z}}hW6mx@*rOi=llA32 z5I#o?$HH1&B963(2!)sU%mk9)ZOzt3g0GGU+QIfmkG${B#l?5N(<;RgMMmoJOH7>tt(a}#2;+L58?k2noqJ!`KBj&a+}G=- zimlccKqHSz92N169``O$AZ?6_nqI}@XN>RKt1dF|)%b@no0sa`sd$y1`L zS@++buB4y;WS`NvMzE*Kqf-vu@1qkphuyNE9aqbw#H{XCV)dhISyC7odKKlLS3ivf zlRF6@3iS*w47Io4_ciY^S9!zrGOrNs@=_zukp5l7wu9iJGeA<ai;LbWH(YOEoFUcXW~YyE_7-u+n?m4TT^Jdm zo$%FqjJC#N2d^VMzdgkIf}dX`ZI&SdIwRna@sLm#|T3U~o)XhL15 z;jdE~H?Zdf31-Twml#hiAStb*Q8QBzAJ&nb0b*W-L)eo@1f-(e(9G}k=I!6{5F3mUd$hu|5%r9VO4cWEKs=;MI0~swT0S3AYWnf_?3DWqaFI1=BP)$uKMVte2 za+xol>BA-ZBDS+4b|J8W;-6ox;a#pi;-+Mzgm_4L2m(`3Rs1}aLOVa6vs()Gn}3hS znvQFXSTq*Qt87DEJO-X-4-eZXBILkNP$b_wa0l3NYY}Nmr9i;XdH(O*nU}Gbni9kV zb>KALQ=~2i8)IXn&;*)wPwT8NPIb0fFtLfY>|{)_57%H%7N*%@caKZlIh#%?$Y)Nu zcZrQ()%Nd_C?^#XGisE2$=Ds|D?vs7L6?s{C7pZxenHE67Vd?WG|>iGOG-sVbme zObJVr`XDj5pG^V?6@v*mbjCY{_6bBv{7u1A)kCvjS&hT& z1cqryvgLlX$;m%?wk1mxZB}z1U(?eBxS}22er$8$$j{3IbNHac>EdZ7LF(EHyrNIK zURbuz-za0R3Pb;j6&D8>UPLF0iUyy41)0P8PLM+TOQy^l=xFLVt3Bch55R1b#l0g66z3Q-~|HoVyJe#wQc z_loLeVEqBwGta#y_=Lmihx#yHGpG_c;JBn#^Kl8WHaiV(rCpwNHZe2U)9C;Z+uVgk z;qkGM($>=api}N-&Xtfy(aeK`k2@N}K^(CHA=G$uMs%S2bO<_lr;tbQRd&jf2D?j# zmb^ljxTzk~hH#>5J$r6JYZyw^T)zsU&A+~H3Bju4j7(8_=sY<3ToHO_0sf}6GjX9; zCciJi8}8rx>XP(8ZX@Pg$=X^*UCAqHQ8HC-L`0ErAI)becwF!-#7nOT;htX)PGET( zQ*6jPqcT;+z6N`sKO%wo`JRqi!RWp(5o3?11vGH#feR%jp5z^_=+5z!ybEJk^ul@A zc~{UI;Vr#ji+GHsw24D);m3|3cn`dQcz-|?DuV;$LduUZZI5iPr>K~<>b}M=NmC7m zt0jmmnhx|;yT9Jz-sOAAJ_0&-x5_RMKEO+T1=QVH!(G|x+6jqPlX6KY+m8?Pu4kDg zVsAxs2nU~PS&gm)iHLZe6jd@K!zp5h6yIUW3xq+ccuS%ASaX2&?`z6Mnz0kdXK`_b zzr2ND&|mkoBx6%1o)N7;J#tzHb6Hx1W7;_kzz}>#SL-=z!0bE$1 zj@lHiPvb(zyOnVIVbR8lka>S_zmv3wx_gR-EC?I>dTY@4M0b?MF~oD^J0fGrJo`O< z)S*7=n8Bfi>+*JOR6ySgP9dYUm~_?;^2?a70MKkm`4gGz{+{zqmhC3{cNH zcitkxuX%7*!LfQ0=M&nM0(s~tCX)>p0-MuMOoT)V4gosKuwe#zC=w5>RuFI zG=<87Ku{exXPwDTs58Y&5Ob#qwJpN7_y^G=nu&2dlpGkiyX6K$?RK?v+9$rmumJ_VGnxM{r9A+} zg#7v+3QIlxrkwY3CDr0rQ%Qpf)Bm|~M~dEhK3X>r+_KZz_}yus@2U|7CLsAA!x|rV zw)WET?S^ziuO-?BOmOFaZ^w1>dHZxY2?e>+<#+Eium$8sN8kx0>$7Q!{j=0`$fZ~n{OvB_`UI)#QqY7Yh|1{PtMyp zvZ7JPB9qyIX~`fX6Z7D`WQUc1ChNzUlJ$qP5TBorwyv|j=uIy(oNx!2;=f__D)MSy zX0%AJ`B}_8(Zvk(YfsEXjz(&?m{#r-otf>Um$IICe>-1AjN6*TxFLb3pZ{j##;#MH@6J;}$S>xikJn~hmY3qaAuZ+C-HCl%LXQi5}EwO=r) zTXGE`+FU5}$5mSmdd~Y(Pwv}Qv|^8UQjwy-GZX-0C-uj|3uK@DOdoIX+|e;pzW$+< zA-lYvpt~Q&|FDbnVs$C)^Gee~$qMy*IhOf@pUdjK z55^Nti>JzVV3&Gc`?9$6K~G(2)TUQ?t3mbdhSNdwMs@YSx`hQ1Vv_%jCu`Vm@Vl#U z_S#S})$|<6gUgJdH~(_u@~W-2$IKn>HskafhBb;4blV9ey8P$Zf?+C?@tIA%LH^m* z&f}pLk^f38O7zTUy~maX9syw!qNV>E%yz7lMdjwzXNYtlidO$#)6}M=`{Z^U!JL~F z%in$Aoc#~ZPWqSq1*exc^{>Y6ce@VzNO-f~@G&u4WslpWRijK{c@wVLuX1;9BK+oa zTbn0OCMw687aHcW^yAti%KEq30U!M6%|89;iyyArmbP~H`s^NF0=1tKNw@jgW}vF9 z1Oo)#8%0{_Z?BoGXFZ=~afPmY-!%5B+_LHNF7bA26b#hEJvQ~2d$uu(7B%sHeTr)- zDe7=MZe3^{^c9&5ojcE4J+|_&n3QFliM!I%(a|}Z_utiN-9wYlImZ(4pxM*$-c~z} z3ktoc)%INdZ2+WZ;LIS*8bwe204Kee?}1$$*rU{w42<0We*tobiRb^1u(o6T|F=p2 z?F32oTZU~a1;aaTs|UF8Zz>#+X|HoiDj literal 42482 zcmeFZbx>SQ`!-0B;2u1CeE&YTg5yy>Wu|Dqj;{pl+woT4~O89=DD4<1aHV zVvM&T)Y9hC!~ZEtjSWP8@BgP5o)Csh5b~cQH99TJ+y4|L2`On=PESuOD=RgutV-w= z(_l~e@=K$xY-wqUgYe45FQ$BNZ|`e=FcL6}-zo2ZUr_vT4Sw{qoG(>2X4~7nCszOU z`}d8iL91i#-26QIKb0iGF7~0PXJmZLp=D>Ui4OC74||wli~TGzrC-7K@84@h{%r(C zzpTH1_qq0;HW$m~ym-qp>5`_VCcF6mwDqmjg}Sk^!~b;W>;FS{WVB%2hus*;7E}I@ zCHl=!^oi9!z>0$=w9L%%bzN8A^Zc&lyB`j+Uj~fAv2h6q_R}%H{avZIwX-`ByrL#0 zCA}FTbGr9_i%DAi_pg0GfWCfap6^*ZIk=O@@7}q&sp;NZTvBo%&T@8k*4X!v;@>Bk z$JaZo@rk@XT|*D}dn;$1X#4b@k=EJeNgn zUH@XgQl-o}k3Ffb7w8G)uj@_U^M}WDPScmfXAb{|3DY}yi~@?6%lLr50-n&LvZ}_$ zd9kHsvw!X38`EsJe9UV4@V)MRUHbtkh}L;p1ag?(`&6=2XL=5n*mixYZk)PmeZ;Hn zzB72;$OG&|)ryGhcAV5+U;A&Pn_dKP_T2B((yq-eEEE^Ti>`{@m2mq1dOcOq!V)~B z0?kX3Br_;w{M;S%OXz!ryuRe;V+m}*^{RN5j17|fYwe$-fY)b;KRt9l|7Ah91@-T~?`$@uOc+e*n?QKc0Wz6bbC<$M~So`yi! z4O^5(DSWG69l<$naRE7A$EeGu0p0oMrmxUttdISVpSDuB?-OMyD#TtNre8p`vT--@ zHG1^}pqEJ}V9~*Wb%3c?*X@!aFb|mm&=)}X0z7SA?uff%|1V}J5dOq#JnazmmS;Ql zJXk8cG|j7A$0L`5p3l5q>J6Q`7ePIL8zyc}odVWg*OawQ-6d5D2WMHuGML)9GNB7$z%4fO3aLnsz zP=`m=E88n1;I(!4emjD)b~2m)L~mD|;=QpQi3Slo@49~KMTi>ehHRdk z`|c&mx*ufPKm*R1)q`+eU@f}7Ruet%d8~cqe-!xNkiigUw8?P^uOpTRJ#IqWAsb%j z7lb$hKI<-{52L{QLCWLOY{#n*hyGlz&Gy|c(CZ82mvwD z!+B1g@nPI+GK&{_tlN8hPOG!q`}$m`B77+wkloeZ-VTfj@8lm;Str9A;QR1CA@+w< z1au7t_snfSRTsKuM8=6`dieYV7OQjeKQV*>veSJxmLF<@9f>EsOVoQGmY?r$6mYyy z@zUuLLCb=H8%rUw`bvg3%Doc>{iO=r=|w*GIIbvzj&|Y`gah-u4@h1!<(cgIxX)Ta zK+*ald$p~{^WNT9ETg)*{(qg|9U7whX29#S;QdyJf0%;c-=Bk?Oi8%3GWU;DqL20g zYuhbrj@OV~0vA(|tc#Sv%IjfKJoFLnJ8B&!TE@x8p9)RwuC6X}lMI-DD=#V< z)ICeUA)4r)K^bLK&f0ULbo>3`f^k2dS|ewatj#O$WTp2Tb9s2=s%_RJ1x6$5FQ=EFSAeDXv?C zuE#I1{4xJKSv_xgntR7WdYENk8pKH!>E#y#OqxE_Tky`LXlGQR2wa{J(r*ffuVVFW}YfC?q zMsgj*!Tl0}_-7zwCw!TsZ43UD{L{gXQ5#`s4d;JHKooafDMJkA&tC2lsHL79QrxKC ztDBDv2f;0$10kI+FQ20cJx(_$a3+4@JyLTqG0SRw`s|o*jtOsh-KHSs@O5h4;ljOa6(APj1 zD%L>O8E6)7QOzs41G!wP%ZO9^0xkMxu=42RASoA;!=s~K`)6b*sD%TP0&R;v1~?J* z!eCc)#NV0E8>}v-LB8jUx~8|IwEAOTRk!mvxuD%bW;=V-E|ka_ookdC@Yir&@jb+J zx8FiM=T}w^)5{tYXfRR!<~BEr&$Nz7J-X?*m^~nso;`E@oRqcw1kon^g(d8%(o*%FU}Vy(RNnr%~oPrH89(GIjd=Gy_JUzQ-{Np%YMAu9I@y=ewC5q`#Z@4r>$ktP`s^}jgjBtMh zLZX2;is7y=k1)4`OHIg3%w-k`I+H^=%_FQGSd8P9rC^&`Sy>@}bjh8kP)Dhq+}Vlf z6L7}9N>C#V?+JN%etdMrQ$_GNUqXF&f%NuT9&^nD{>WPRW3M7RQxJq(!S}y22P097 zEqj2AC{Jo0Dxc04^d<^)VF z_uTP{<%K=jEw*oAtCw@XqyX00^|t!v4rchq$UhIwy?5drDqX}1wSbolGF)K21!fg{ms z{l=OnWP7=SH@y005YW=^agQlzF|B@g&|v{ksfclqx=>U_Zc}>m2^TM)a^l zf8f?eQwOnmjA7XwubQKQ#~+}T zX}33}?;HKcnaj#6E5|{|Y6~gM`+*c^SYL>y5i^ez^LhR;A9_Uhz;E+LEJrIbycqnC zZ@w}~#}2xC-a{Ct~crvf_^cVF0YB!*lE&v~5JIj4g&_$a@Nk;7x81634*ZiR$|MAUnv z(!**;SQSO1rG6#jVSCkn>u1eGNZ=^zAkTP@$_owd!Y2>xPb(w>G8D++8Y`O{3ADd3 z`2~MY-gbbdMUY2xXVLXtpusJQzSaR=4}Z@V=dasruy3xAgDpFKyv7Vv!HspD5^Exy z=L4Q*z3@4s9W0$4oZv(on`!bmShs_l_tWq^9WCyDjN!VXXd1cu1)}z?Q!{g^j4F6D ztefbK1;AF0PfUk>V9OkA>uB^O;kK@JqAzea(pq1)V#o{E%b(7irIDg%+aEH#&J$8o z_pwj5vfPWS7z-u!?-1|Ya_l;f>|^xr=+igLkXi-s_Cdx>vwSF}ZWF;$EZ=AW<~SJO z{D2-xwn+ZyqtKw`K)psRga`HeCW&|52)iRqtRvI<6xqV|jSP|nKP{ee;iQ&q-pE3We0S zyUrvR`q@W5a}^r?Sitlq#pp(blAU4>rURvWy<})KeM3qbG4eSigUjJct7bEB3IjjL z9pp&Ct6{x&14;BPjVomKN1gqaTE%GNNcHyi}WXwZIX?g7B2ci+fvP!#lLBK(#fHE zfOY(eMWiA(T+)9|QI!Ll1hDk2#WuP7TKU(VHOvNXk4I)U;C0&yI>8~;aD-0BJv3#C zZNMN}><#?g{Xk;8mMAi3Zg{<|N=AXgtG|uYP!9VS&l6qoyhHxKmbe`Ji;Y6+<|}i} z*Wz66iVtc!DRn2bZH2jEc3d}v#0=Dc#YB8O7X~&g@Qw|}c0>X-i%P+d7~C{O;rdDB z%$y__%~d1urLF#uXNSAS*wm19eg_1-3p~1cN z30`j@zhj&lBC+X^!VbcVauUGV1Tm9WUaHbal0yJa)S#(*)>@G}OA=>?t->*cvOAJH z3=9Y&N2l_@s_O|K&h7b=f>ikCzXV&kCOZfoz6Q2jYss=2O{ z7(fVx;7(hrBCg>Q5XRC7r1fTgdUH|Dg%};w2k4= zFaYHDRg}Gzatbz=hmux2R+C8GQ-6s>(;UDVLE%Y(o3FwFV0cq)-Dd+ZQNj#qGMxme zB6G{$X!OUBBxxS2n8AngPvGuWP<>6>MMNybxX^1m5k!(sSgM7=#nCx$5UFR=3*-;n zO2M4Al|T#2jvf%NIM(N9gNPm{q{_*f8r#hRVId6f{gOe!E-}9-lTS!FRo!?aCD0aFygxsNjvyS|gh_uz^ z0kF+zANq|Li4X+Du`HdR-y9nhO+y6{yjSm^K&CDgaS;)B)np)jrC+?Szm6} z$I}!D%I=6V7tb!q?F_43=TV03idV=&G1MiPXfklWDs|ET-n9x!akX8egb#d_niW^d zK#QOXHRFm7x%N?TBwe3Z6+1O7rbFaD^NXWhxzt0%BWTUxK9kz?utA|?8A5AgwgP$BvH!?^Myj5@;xnU$RJb7$xda zoYw=V?6%YN!!MjgMmSw++{pQF5Y%0-H&9L7gOWFJ<+Ltt%yJ9;Rz|z22!)Z&NO>Q9 zX;|1!-=pLqpJdv#-Ezn=y(yb9Vv9G26ueM%28Gfj1j0JFIt$yEoI8c|RkR>33$_U` zqqtFh=(FnsM)EmJi3R0}fMFZBYx^et6hUr+6#t!0cc@JY&tp-ls=&E5mS;p>Q6*H zQ?#RlEX}kl>J^QJtMvyThBOWLpkS2`iE4t54yZQz$an;0h&V4nfoAoT*!XCKpZAg) zYt;=pHRZxj3lh0QM-s55xao)rCb=kwaM}PEa&JF;R;u`{-}&S7Y8L`ny!4N%GsiNW zGa)we%mVOV5kQH1qP8+?ZdE|R!ksP&B~>hp(lEph=9{5=#1?%hoDA})-uOB! z6?XTQ`m+|!Pk;c<*JAPDz~%na(fL56qd+R`r@w8AL-{yk-*K!ibNfh0&qQ&E*(`SC zs09DI)dmp3O*pHoMuQ8u1g3Bj4QE&`s?rk(k!8(tEF?a)^-Y}RqcUPYMtL7$jc;ON zU!0;0p7rBh09ctC`=lS{@5%MV!rExO-Zum-_xU^5bb_OyUSEdkt-HkasCwWyDIcSv zT%A8KHj%9|oE+ZpR1aRy0^d-)=dZ@g(4%|{n_GN?1swN2HqLhAh`=g3XLE`0B)BhG z#1wb!KV)PZF7A==2&P=X$al)fkY?TSk1MW&Go5|3lQ-TLPvwSR%(qC%0l%mU9kmzF z0vDt#yjp&TAT(fx1dHMyKD%!j#pnvpBL2F2n=vMCCU`DSS(*EDlaXoj1xz1;!~4;>ry;|2}vAM zEt8U=>$JG93kc7gkH{hCo=BMRucbi=0{0StV`}(B($@==QCRnr(v^~UeGQ+=XbwF5yV>^Fe^eEq;Wzb2V8WunU@Ny<48Q8EZ9Nu)XKs2Wb@V3*?)Nt z3-T#2H%R{7# zo_Q1gNN=&JQKsfQxZCL2MVUXKA!O-C4W>)$cxAA>U; zAL6UqdVp*8fNoJUB?2)5HIf`Y$Y$aROg{s#QPBKzh(8O{PZ>sm)4(MdBr0L=E-wv; zh)~U4KqxdyfdpmDoG~QUl&%4?))#o1CIBIC-SJ6G&E#}cCZps`K&aeb`=D91a9DDC zoBOQ}jZ`X%c_`7FMhyPjwEeGKf0?OBm_EVJlEcyk3h%M0Hs4t^tJOLl&;=biqRg=i z1zFJN;b=&85hx@Ju-EQdI~A5k?VD*^O_^szWM=m%%TakIn9G-rxjEIUVqnlk?DgDC za@K3%Fn5V7iEsG;hd3hl_R=by`!CN(E@;}PUB&sRXaT`(V##!R>RE6e zV+dcO{Dyqn&55tfBQHMtS(&=<#=o4B(j3j5Qu zQFDnAUMCYd)j6^{dNVG3aq_ec|8M605Z4h8E}u%`Y*)gJY=8V`iD78c3T_wY5GAhK z6eH~nHij41=iKdgDWA|$lPF!`FJ#0?FZv3))W?QCyeVs&F!K?OcJJ^gx!{8X zXS$>Fb!=;TiGI+qFS_tfJ9BoS6Bd$2N5V!mBNe;UV^WCgBqj~lB4(k%M#RADzwSh$ zBVh=UYg-|+&XN2%hFtGlAGK#GmhT8#)m5XL9j5y`PSRRKa4)9u;1C-dp**AVj$^-- zN1P{^+lDp02&LX(aTQwpLrYL>r{pRAUbTp2CW_xFU6O)_>v#j-uZBCGuBydVH0ke! zh9?Q^BE!Mpcl$jVO3Q$_&|{!IBvV+)OI99VEcm0xd~j}(^}bbHC+D8f^qVgTZRZ~C`xF<2;vbD>s-o## z1|xNx+?BGHt{SU%y;HRPoorw$9SHf@L#<2DeYjJD;3zhgcu0eC?PX*Rg z78VvyyNGdu1yp~)*12s2QPg<99nEDh>WQnBhk-iB)+>9kGR8gr0yIt(u?0atdQvz>Vo^B8rmK5`@ zIrU3~mzhq2VM0>F=me}QE+2=+;HLHk29*PC%(9seFhtsK69)d9$-VfnMbbCm6;!to z6ig2s!0g3gh5ul#7h$Fw?oG_mkKPZ$_`zlPR&u~Y{cOmjEnfd)%Fd25aRYUH^ljfs zA73bP$>##rO~e$jzT`od@GQ7TR5*s8>5o!^7i{8u>mu;|Gn!iuffDNkGt;qH9&^b#p)q>cy}S zqQ3bdDmHdBPlMQnuX{D$BzLE($yP3PY2+U*3}lJG0o?z=5{_?BFp5!-0M1#P;SfgH z1Q(XVf`gl|^AG;32F{CX^uLxZ3DLK30Q9j@-ax~{NoJ21&#I3I5Vp9`f+FG$*Fgct z45W`U_-%w>p)hQK(;bp%Zzn(Vh4&j1+&iHw#QSXjpvD-Zo-;7QUFVfsfzk%Ia~!Ks zUY&1yJH&baEmLyt2B%TqHQ9eiKdJmTgIvGk%*P`B2xDY&U5~MI*r0I!OYTVJ!`Bo0 zNxZ_yzMF`^dp_*~qEQ@^f1w7WP`~_d3Uvn`mw@b?`#*f*Og2>kAU_HX^p(nD?H`Ks zAHuYPA8&pI5>@iY~1T#78Ukucj6YQb6htAi(h8qnC*d!;eUBiwp*DUH%xRw zww2Z&l#tJ|{~=>B!Z+bGCmfdkB|gIwLX}nd{_{+nhX1=({l8{HL;C-}uCQQaM5ej5 z)yo04A#RS zm!=>1$Mz^3R4lM`o3Y{BknQAwNQF>@!Uo$#7FYn3O8Dt{YVc11=YL=P4-4BLhMS5K z0b2=BxBX)=L?Rh2n)fhdhHw32EF2?Z^(g0m20!>80$j@Z|G)YFYA_VUk2=2a+UatP@$M|X@UO&iU7eR=2l+b=Wtur zW1m3xC@Khn*KSoyIZr@hzEnxw)4Fu2&aiBDm*MNk?@y$ke7ZJ$ykbUFvubDY8SDm{ z^s{)KDm3`O%)Qk*e?Ak8|7M*{dmq34#ruo3V#~*mjorPCDcQ+IT}GUyCV4RGPTNSM zFsZ?HKUJ%uyul>*WkwS)2*dv1fARZ)N|$wfqRDJqvYX4V$%H~oHd(i3KGfAhd{BtGU=X(ooo#mjiCw^zq#m~rDvC+Isj2kRxI6seWC zzX(V(wMy0PTzRZLT4d^eEg7n3^Kft&%V)bbn@eSlsAQDS?vB{4=7eSOxb+;c8I)Yk zgYCxFif;b0O5I+Ooge4c&-2(m@k|;rGueYTeKkbKwE@qP{1k41j>28} zj<<8{vZrO8FaDumuw%SVzRc#}WoxdhYR^v)rR08;B_-I*Vv<6_!z{ux=_Sye3hB>`Ag>!0yGpave zwqA6IM)z250&IB94|g2>e0D!^dOX_1@2Mn<-!xr*-oA$B%j!4^`iY4+UkBVg1xsVb zu`Vc1aNi8fXpUX~y&u{0S%YeF+T|QAV>j9OHqA%GUFWC9> zu@SfP4&WF4_}JVUux0ek--byapY6Ap#%YCZ#XJQ2`xW&+dQPw?)W13DdMk%0R2?s@ zFI5bD7ZiCtRwMUazZ87FnfF*L;ylTWsy9g1B)W_4C;2x<+%UK*+TPwAGCe<^xj^>= z!jBWKBMuX;P3Ez?KvH$YrHvFBd&%jA-@|LU2Pk1S?~yHOk!cU3CvET1TK@f~uqxkQ zO85P%rm@$aF3(Gpn|8jSR@g+|!i?c-rD5D-c&%7rzN5fCa>vO-`px}!Bavod!}w`X z!E&0tn)?+)YD!8)ZBM=3Y%8JmB45SN28mAuv6YZWG`or}5!YbH_FYF2=nz%+{iYIT zeyhpRFlAD<^FQHF)|7^&<}`Plt$Zmf_Vf2YYFn?4muz>QPQBanvU6z~#v)%^dc4l6 zpm%>lJZ3)C9SS|=bw5Ko!96?Y5l!n)bADFd9*aaUg%O;3MMcf+o@$9q@xoz)7vbR? zy6SSQ?B6no<7?44o{6U6opkDGZ)xiJMyc+(fN=Y$1q?oD|^8tAjg%fcPEsmcG^Gk(Y!VMZmD?j;meBUwA9Z8Z{ zZF{mRnex^etb5F@eI4EIIH{>8{mG^anVy)LP}FGt_$?U^Z;2VG9IP`uWT*WkXthsN z^`l2+pEuT^L)27Lr<9q#Q)%C0a?_tIHA%PTZxT!M?Hj2{SZ8V1qZEuStHP%Z$}B}J zuKZPx%u6h50>IVjUV5hy0EMeM{`dt$ZhY;vl{t^nAFVTUOFtquP0p4_`zh2PetoVx zS+xOw)wignOdfDnlQBsxtr@$B+KcA^Y)n56qMI%!RM;)z9w-7~tK)m=k|jIv=VsCz zy)s2)(YjX(|ALpt6CkPk?d-V0U3H3(jBqhN*uyY(Cp2;x(|Oq-fUgW?Fs!qgPy9?aB*q{kZY#Oox-w&xT_Y}!)>i>wEnBx)hX=GqiS@d_}n8nrYJ;i4CTb{UH zd&Po4Ah*m7`Sd0fL`70l-ulS-&kZWQcGYtYp6rY|wG&JA{Bajoy~Ufsh zz>bIb{N)@QRoy>bj0BG}H3oi=$x6MuaF(67-|n@0=Tam5KQC`CoAUquHRI99f6`t; z)?8AoKroDC(D5ZI9GkKhrr)Wkt(`K}sx2%uI;~MYwzt!;R1RA;$m+-|Jn#Dl*tX{!0@tKl?9R<7S%(j%@8;%KN^Q+x#8C1pY>QpyII+;nM%}nb-IeM!&S7 zZ^RifY++~gQ32F$+oclVSrR^?b$H6V=tJAmz^Z+E|Crm%>*Jsur2_D)=E;(gR6Pe585P+gvf{(!?4O<-je6jT?@ zSa$p*Pjar?J1#2u!^{CYU^LsUPL*DfuM)3o-!P4Ba8&D?r>BQI!v z(%ZY;Saptn1{{U=o(TBY5mjtD#dIfdY<#Rbc7CJI4md9@(%#Tn#UKjBQ}54CN=PW6&!fkx zIE)P~{Qdj4mZoNMR(AF?C{M%Au4+__b};p5;yF!5dx`h(&ti$7zkL>kk5|K{&oM_g zbbyW@RV}+oO^I; znyFsFO_^B|!U52XFuD(a8yj`7-&t#YU#w@kQrwFTss?&7mgmb#ih2bk-JSHBJPTjV zp65y5c3Q?lHz>;LgmcPYeSJb+*UsbGP9HyE1zld9gL6mkULbYz?DJRJo5VmVv>!5B zcre}T{!+4RaamI(>#cirS!gQ*O!u1J{O8Xf5r!_ou&}V>Lj&#RI)sh++4b_mal!7M zQZ0n^)UTgaqVdqOngm*v(XUD{P1>6rNOqYQ(wiK1%?L_4HQXJG(unM}{eYc>j*g2} zAFO2=gxI!r{vMC4WmR5K0Q+p(}p*-s5>+kG>RaTSf zFTT;SkqEk!`)CiumN$7g&aXZ(JYT0u`yU;YK#z^9+{Y|Y1uZTZo*kV_f!8|>&j(=` z&j+74Mb7D+9-WG|%8Y0SdrpkC_&g8A&YjeI4Mlcb zmTmoC@|vMf-FCM~cmbep17r-nqWtb=`G7p_%3k)`+kgN;p24-=X94fl{6?Al&QV%U zuc4FZO%Nvs>(UZeBgSBAxpbXD#r$_ve{Xc?wE>|$2H#l{34Nrk96VEx`Bf9=@^p5? ze<;X<%2UHMj51RWE0#R+b>^$%YPLD|VfOuzTx-}m#fZVQJ594qSmGR8?&rGD z7v{~m8f(kV)4Bc)0s#M~>&HbQl?AmpK4j5C4#4ns5Fy-E_z9m>_^4MS&#)*@r zU!rBkNsYQLy18o7>*nFrDH4mEy&_;GAZjigbu)66Myf;Ypyuaa#%`eB-`_u_;`$r^ zt}qx}-u^=(HuiSBYORzwK4Zv-d6Sl=-ur4Sx{0Pt8A-otG3kTBr|hD4sT;-GCV6ea z@ulwZTUxw4cE&rT%DH^noZUA`6u^6P3w&mC7R$EoUi zMJYLGR)ovtyuZsH5olSub7IO7ksZj_giku8P1`}V5$G&@0wfv^~u9l4Cj+Ays z!F{WHmV()+gcC%vU&h%ETGKr$ut{?NT}YaXvr)aP!vj5XG7;Qd6SbCT?%^J*Dq3sF zpYT3g2ewu()a4r$t^B<(K;&4DM5D8s+R^UtSg<9B{`Dchm-~(d_!0tyx;Jo;rWK%4 zct@>;*_6P9JZS8$VdkjeOe+zx^huFulvwuVRqEQx%?)-fEUUDP6OAR>?HWz8GCDtV zJC*HRD^rqk%QCv&vfqqNXvF#Mg$k=1KPKhe}{Zr`x@*>Hd{7?U`KbaR|fmrdO7os#~NaTs#>I z^ANO^$c?+1Q#W1%QRW{YTj0$ef~YR5E`bG3|SYp>?s@-FdxHHkh(A zHBph#3J$?_DS@t&&zfAZopq8}94dHyK0(i0e3=YFh0f=o<>G-V@huJ93vFuh_n!0K zFIQTMmM^sCD=ZM5>FtAGFP?}&=oiUBcFpd|%DS7nG2dC|_|Hvhr#IU4Oxrzv#WlUM zZ`P$_`Ecm>=BU@0PS!5gSug&T>%D6U_|#|s0`loUg4zyg!Aa0(r$nF-mrT9>wl@E^ zq?S%iaC!BN)b8%h@EhZyJ&ALEE|0`C)=m8rYy{lKxo5!*5f&sQq#lckii%4{yq}yq z;XvU+4LzgMrr5A?4ts5t2OWYm2TfpoI$CQ*p;2XZf`W*Ot`^O{FCqho_M`X1T1tAW z@~8H-l-&7>u63+^usf5NX7^4SgWdQT2`O}7&F6a2CF|3-Or1&nA8iCjS*;C9=acJ& z#VIV!z8fW_fGUOSEG z`su5eB%9`d*L|&LZlYQDW=V zDT5r(w!lvjb9w#nu<@|z)O&Jp6t617TEf-UQ~jPpIxHjQ^MuavUw(YQ>0hIA-xW9O zL89r!-=YiOQ9irWDR>pmX@2J^Y-o0?8n3J*X#7P>6ixVbAVxonpjS(Ce)+4XM`fXb zW>Xineza{jsDqBZT4ip1oX%gZU8QjxkGGLW{d#Z zFv+A}6}H)4&(6Hb+jU);)Z8E{KO6hYU~$Z|ur!_VtCT}rivxGzTr(q2y-?u*{HHe2 zA|HVRywT?|2t{0?z{vgSR4r@=B0$_lr)t_|RnY_BUb>sBZThYGb?sFY@RLyqymaVw zZTk!Y0k=wOPeJVE^AJ;I2-{N$@M`*cUc>*TlpgB%s!d8@BW-0`FI=P{cG4@I-|N_d z)pmqH?rf>MbN=dmbl?qzYDPg1A}##g>`Qt+)s8>j&PCGrKVKqpf}XIiJFmMzK;7x3 zBhKN9rrPEcmF*yBYL>CuPtis0b5&6yzM4i?k>jd)3QM6#voA^oXUj(_T2%CoOV|Oj zH0p_?n8zo_w~m|cxqK%I{_?mm~@P~GbyL0T|YuDW~cl)bMs*wJ6k#!I+3 zpc#8c{}lT;rsWM(_asEH>>23v2z+kbmk7xABeE^vnAPkUQv{#5aEct1$aX)+AAdYQ zkG_eVI`UI1YuTvMta^KR`_yiG)`DU!Kw}Z5VBZ8e@%Z^LVIe$#S0d1Y5GQ4^()#st zQ(AS*-Rqf(%u4IJP)lE@OiX$&qogIw;s86Vo*utzN&m~zFp7S&i~`n;9eO9wt1pd& zSf=DeA*JT#Oh>Ht+QyuDOe7r(K%S5-e(BT_ z-{Z-Sxnutsang{qJGTokO3kcp;$sfA&4v0jOp&G)<5CX!4?Pa}AS4rw9PYFxyYD1? z5&8J7M%JLvZvYR#Nz2mT-xP`mx_X(zylyev3i{R9*Xuco=YO)OEcjJ26)Q{cIT7T9 z{c9n}i~ah_8@%~6>jvrctc`o$rofD}&D%(qGSlvneMXjE&1u4`Y})PFfz?&ZYAiOW zIPcM?t?AL1ntU5eW^=R#VO#JzGd+FESxh~ zt8P8EK7@4WgT9IAzVbg4-wK^%A46IZ-1`bZhrab?M-lBdCpMGm$LSq&is=tWM8FOs zF-X#5_RU1CKV7=lW6Olw=ViVuBTmQ2pL;ch&=-&6y|I%Q3wa2{H#>GpK|M%tCm?d6T5-SUAZ*Sb4$)Jf~iZLOPad6({z^9(g?r4xw0yZ7;Hh z$4*sLRu|QHvcE6iNm zFBm?z>&7;>=Zqm&^E&XQ`}9NZ;zQ)i;>*vMKceC`O=88|o#DYR!#`)1WIdLaBD#e) zLF6#UvxMw!y%u6Z!RftbLHo$QUClNPwtDxbB@^Vjd0jG(Gv1zyC!QFOnpZf-e z|6=2Mug^0ZIRJu3J`+%a)#h8#b4>nttgZR9yD?3Do?e?-dm>9$UW*;G3rsWH|E*}E zU&3k1r()V`TiA06LWPDy9tUO9PgLj8+!d4>#b_r=k{^supGWvkR5h<|2P4vtPjYrk z>O4wbEb$kYaDhRA+tONcfbU{@D^Eeir^O0vo_YB0iQvFJY4o2-aisy-%G zo-!zqmrv#`17sdF)7j~01|RSMPJcGf_-1i=l>s8he&q9hV7)z7nojb4pOjeYB$8NK zRz`m>B_^79895eH;sU*%sP;MD_oh+?W2!FAX@BUE4HKT7Rqt>!O6s{u@LHd^js|P+ z+M49Zei0=tvyi3-032Qz{3jb*dV}}G`+*w~$*|A}s)yrT|)y;%1-fcF2 z(k<&bL{_!>ip^)*qSyNP&d(T}*t6q6={~O%tCvUMInfkBGa_qsv~|LGT$SEk_u6Su z4cm1z#TgqFCF`~x(Z!d;q;=(ga4KdQTbs?vmyWTHNSiN?oh4WH| zJ%2H_WwhktB9-*p6wZG~UCy^X%o-fmDRsIfNxDi8<0kc)rqd*rr=(~z`6?!kqi1XB zuhxcl)Y#f4<{OX+Et-IS+=bWJ)^3!xWYySKIqF(^SCLK_Xlc(Cju*--5-e7*bxZ5B z&ZlH(uJ7(~^TJjoCW+tbHxQvEQ_c>|-k75cJp_h>8-+smVD~P8`YNsWY=MUw;Wm zLqlWHGBK#j`fi||x>Q+MY;vnTd2Da5+nJtqvbLbLR@jlHqpibJDZp!(X~)Oh`cr4$ zYH_u}C&WT#N^^azef8(p8ouE&W=rqFhNaS~(hiAc-nD7w?l2TF#2#HxjX?S&5GE@L#ZiU_zF*4@@dz^LTCCogK2owvt1M+E?K~)*^6y+Vt&4w zDhcLdel!al{UKSBk1sOPOJ9+!NoT0xD6 zBIqxWbEjFa^PDOtz|zZ`&2~_iZE#+0eLwbFURY$wo^W3e)Q4Us(2;j{>C19D%*oj69OT-`kk~9RtL?v7W;9nkz;AAvXZLmN)3W$ z-pblKZ3oTn@orxNx)P>kV@3g(p}HSx`AXb}&{)hQn&{dYI|L)Z)#fh{mGBOdY@%Nh_Sa=vgSY?)v566 z8=YW1%n;@$OAe$Tg+7D2ePV$3N-=Tz26er)_DdfoNIkP(juX>**_>vu^P}gnorvqy z73Us@kUJ$YPff_XGmVO9ZL|-;jVCv2*vB_QNwB~OkvNSAXe7>uK+H{`f2s{~dFmw5 zud+I7@p@3`3wJ~@GV=0jQ&QgLHz9JnDAy`)Rd2)oWI}ShcwI3ytb`@<|6uPdzv2qI zHIKVA?$Ede2@b*C-Q6{~ySozz!QI{6A!u+5?$)>l&2-*-@61~B7tDwG-fLB#vv<|0 z+VwoYZCF(qC*R`fQNBRAo5RFp%Uq`#ntmoXxum|5f7D5nR;^nV60TxP_lO{A_Ki@F zZ?#L6|x zO`8b$6?5=@$JJKCD2+Nk5gT z7$TJL062RtQNM56>_8ehDZ3@{q!<;NR(4gHauWi3swK*k#4@pZa9qJs4&tP7=El-Q`G zI*=Ef50$^hG}TO^TU!EGx7zI2E3yb*mRHv7W=%+(PdQveqM$BNFR>2gB4% zBKBoe^Yl7HgU>6*sz&JvVSI}49m;g?z0rSck>Nc+G90e9Ler#&>HJYAzsR+UORL3p z`A9cjzIHx@>4Cu^i1ksRz*c-@ho2$dKzzjU=p?9?oM730udcO~#$Nk5TM*x`-gN6d z*%IwNGJ@YddCT|XQ_tUxIbF_YHv6@9@zZBc*){d@7J35Roa}-h4_VkPf@*fE>}lD# zC7h?;F*1`YoeHqJZ6)gT9U8h#C9)t_yQK}%55w<*O6uBT5RE&fbMCa5n`%3$UB*;} zdkgdPU^Negt=`&$gKbSho9{UG(=R4_TU%RIy;sep6%E_>!ch*;VV=!^ zU8MDg-l+9-xgF>6yYItgz8a_dwX>{&fXE&A7;-<{;`3)y!pG%aRe;SloRko&rtGJb z_p4bCcHJ?}=xIrXvroVTp^yLvjbx}54Sk#G>$MsWSfM41M1?;fE2%C>;^uInZmJWz zC0nx)FE{D-k!`x!U9DflwQMKnzU>xCDEjX*8jv=BD{DW&tgh*t<1%@sp{r9?7~{jT zRN37qyYz5TSzfI?)qTuyezVVcTd{3-7)6=J^+a5g?eoph>(AF7wrePfx*sJt^b$Uf zHM)%m8>9|i>n8@46KS~g}P@lv|d4-*w@rEe*0BZ1fDxIK5C zBZ~Y=YH)vbLa*K%3`wqidpLGr;z@nFmTAN*sw+j7I5{gTYE@nBy3TZ4D+@bisJA|< z=izXCV9M(oRrDrw(=@gUt5f(aa8h5*D_CGwA8iWfNs?e;q@RA^NFxoxielKD*nzd8 zf2zTXQ3zf-7RHsAIR2Vnl`1ZVHC#B$3}wxV-iN591=hGmm&PKk-uv*@TcAjK_f9GK zTmi)=eUBu#_bUk0?%hbA%NtN?JM#c{d*!5Dv+ZwF>bj@3l?d@)*}QW5c+_-0Y9)kv zZIvAg40fp#L~Y(Mr8+v{hZBs-vxP4&mL*iRiwE2+b5jF-3(Z=IE3Y%8HBY3x;xi9I zGIv5hYSz{+KGXOu-kgery8X6DKb>B8Q2h&u4tmB|!0G!<) zo`W=5$zNznnpP{Y3z_NyRB@&X7mZT?-x|5?B2|@=^EXqC70&XK5*?C@nhz<0EM30E zjkVI&R!#edRf()ows|fpI*0MD3GMe>7d09>YTI^Aslfc7mV2PqQ0hCYncO1UTrbg~ zNYsTrYPrR?MbkDR0@nzdGGRBj(Y{UEDglzk!_nPpbed>PBYmO%OD+7ER?ceS4we#w5jp8^&0u(g{aUjO zyXBO!j7&7xFmQi6$zpfCGvM#|eMY&78^dTcNp*&R$50*f)mY3a1|ox`{MpA7Q6 z^t}($1bGY46Ul@OwT%2*BG5?A$oh^l?e71fpkS;_iTdLiP)oM(-{yaHJ@VLW<7|qTfy?8Wwu!iWaVTfKhQbGS(~2z-Aa6!5u6L!V5g zSG&*q`zAF$KK>=bf6Hqh_3sNx9Zzv->DfPc3YL+mWN9KH=R_a6`M9^3S1B0LqD?6o zcP%iVM3xFa$s!yAq{gC=zZMXD6Rp42WuN*;4161+RRlw%?&^LuqIM50R;c-l?)Q5? zZ3p(T6pexzN<^t|@5_3Q&oIa{%7%uye{;ci?H|72nfp&6V4%f%uOW`DQh*hhY1Xm} z@gM2;jSN2nAd$$SeSj8+E)ZKl7R>8<_;3Q`V$%+tw0UVnjl2%MM7DL=gq`6w2YGluLj)(6r$?BM_6A z_>_ke0{Pr=R$281p`5$>xbFB=*XDg^`PcE5PdK2R`IyabgjHY$>>z)#`E$MdahG2W zl*gh~ypL?S#sovuia|&by)jV~3=xT70dR2V%=q|k(2ZLd93zV-ne3{TaSql2>E%%4 ztE_rb8Or;PhH%C{XFfkv^aObPl{CE%C!`pXl>TdFH#fHxjOQ(sD5Smw;0`$=vF(7< z(3g;OSW_6pV7HxtU~?xlDlh|u^foewIO&~x%d2SH0VtlWM2y`5lI3`D^8)IW=_!$ycxWUiGZh z75T$XVBiV$zgQwb%{Q0zpC!b{qtYv#f^+f(I1D`#0zF7DD8gH?3PxNx7=0Ah*L7X; z38BG~Z}kNR_A!I0LH;4o9mZr2uyesX%6(Jf&K45>^LSC=!TCEKKtZ_1Veh2yw>Q6k z#I}zBe&*rW9g6|ELFapjTx{tD63>l>p-|`s@Arq5cN3ai==s5SAeWZ`7%KDkc}O?d z_~bZ6j`=1JT2+$ZRv%sPPrlJ8)fjRvacy*D_>P&_b|hGeIa(&7Uf+H^odeQy>{6rC z_Ku70qW>Oe#y+(BZ3@OoBp^r!JMMy#^$9x_12W_?;{{V$wf#fs%LRuJGsJaoGd$j8 zc#?6J7kmVSvM3$@9#A=fP9_(Z%vog+W`BJzx|j)B{pMDJka0qfo95~4o_3!H_t0BbWe zWQa5hG0$wDpvAO%JC}HvRetS_IqNx_aX&;J$BxcE-v;^)uQwPC_wMUNBK6f;Z@5oC z;Q5ejfy_%5NY_ll-3^VgyOoN(QbY#z!g_(LYI*Yd&jIjIKUGa}E*#JBL{F>> z%04CoS$hS-4vqXprrKlUB<>e<@BZ-iW{t-LIUsnQUuc1*D_!Nubr6-#0~^m7;;k@W zSsozAPecb71T|owl=}}b^wfLZ^GTXY7C;>mE>C)fK8Y_8ilfxwtPqBRgqV~4zdK7UOn{gGm?uY(xk9HLPd?%lzQysX5cAU?zQoKlV zkZK>nhQD`mQBdMf%|PeACE!E{J%X|u@>RtA1g{(GqV3Bm?N3-!Dc)P|p!=Io!zsdl zfVROyLi$;608j4wNWVy60k*zjE+Z@1O5}lRD{)aECJM1Mn+yaCf;aEv4MeN;tlOLovg2+o#teR z!QuXozpY*$z;W=eS46l$PC`g!UEhGWK%w6=Or>|16v(H_IaEA{IvDw7KG0|>9Z~?@ z4K+p=g@_dIY8|ML1+}<7VQ&;IYXtuu(F-#d=5~&3?U|$zhsVznu>}e9IhB9xpT@LD zLB0M>8Nc0$Kxwq_CuW#B@GFog=r(3S?zEi4g_xS$E@_h69N)=N&PVDbll`;WQ zD7B71yH(; z-S|dbQ0%4cebA)*aVQ}<&;pKmod2C`!lX`D>|1dUu_MTH`4{=AKy(O~0VhaNghSCH zm;`KNl_H?dHPQ$SxyV34+%(TV%C;JGg)k%q@pXi;`+{P_9s<5Zfs20x^EFVIwVjJ9 z)C@q!&$U5B4tE+Py^8@fP6FMY$F=R}i14!2&iL1_5xDFK0LBUgKZUKpu=T%ERy%?A zMS>xAY^``A%@VSO*ZvR@5Ug zq|L$|Kq~?Lvma5SBfu~425x?az_9RFJt<0lotXK_6H2^lA2B5v5(%uVUP;YD?+xpG zfTvW#DOt0QIbI_yZx|lN{GR24Girp6H`fc4e>hkCtp^oy9SvJH`IiqcG)Vk~VmL`~ zf_IwoSI5TwoD|uEKq}fsWP$nt>C;|L@)FfSA$vbiB#AE1P&qu zQ=CL6Oe)z*vXuOl73Ne3A8t(eh0!J1YG_ro*Okfq)0ME1+e*Kl!e5sl<6ZxsLt;X- z=xnJ^1J(zdbVP9wFL;fa0Tb-5@5W3Tvm_V_>el=m0R0UFV;B-BV!6-Cv-wmi*&Gyv zOd)u3gt561P3)cqJo((wNMDJl#dS<~k)aIXm?gjEe44r1XPT#mAZV@6N!a*6L z9UwLWp2r`OLdQsRNqCWTg5s`8@8Q>YCE>(LC_=jT0`B3ZvAjFrR;bbaQR`ImrC?bQ zpLRON#QqLl8kO6qemUid)3**9Zteu_8M#Dmc6opF&9VM8F9 zK3;5yqV(v_nwJiKrzmii6!1wKBReuhLfXl3YaH*~L{OmPRC7DH0S#clQ__UF9}(l+g&8sW&zQ;I zh(ru$?fVILj5rZ8&?wE>Hs`xBTT~3Ga!M9Mf)j*0^aCky4rF}*To{DFyEuowS0Z6F zVDz-=B|S@DQ1?cpfAA~h6B1R{SFyOU{aX>;-&eIW&Yze9NIH#H02%+@hwuQFTzCUa z5-Q5NFdRe#9TM5^gCLVIS|~Hv&B)!*kkNATi1@o?a(pIyK>*DC$R$+djfb!}YXroQ z$_aHXGDgrRXA;a;8!a!N>%GEuoh+nKq#|T7MAJ}D1ZWho327>qi|$iZV@jj~RRG5gNJFq%uwz=6O( z91`M-vhqD^M3^#CWbY`%q^Nq3fNo_Ae0aNtrovQx)B)5QZ{9W0#7e4*l8yBUQ^wdI zi@*yIkT_Ul8t1o@t9mj8Kt^DZqD_0gdW848Le2zxM%Y0_VF$t=4czTtD!I(W%w3?c zK?FNX;*WX-+;&}D!V&D~r|TOAt&9>_Ug95j70>RlGgfsYwoV5LdoCSb^PyY#* zZP1JCQs8!u$2w|Q%n9vaq~l@`gX0q=LozfBv21Fu9FPnb12-Ks+3siaIz73nCv42- zkO(5g;}7|P&x#T*%(B!AVG@zGPM;#7qh#B?S_{AY`)tV8eP_)ibRf1e2PktT%D*}zks+WOJC>1zRewe^-Hf4F@G&|2% z<3;$jQ6~jtVPun$>_gDpJfg9lU@F~D(Q_nJ_`@(&5!ONo0!-1_aCR9;Us-i!I{9yA z+9(5wY-Ta6kXlLnA>&Y^UcMn9uT=8nLw!3dVUc$*pZqP#9o=~V3H_7n<@gr}X&82& zC~+$x*?1mGKBnZ4>R8cy{E4JTP{=97F`S^#3QF_&O~3Gj@;RM6)Jl6Pv^_0rAaLW3 zH)+ND?s@}5CUO44zWygP43Y5I4ZbLw7u*@3P}G=2t%2M$mGePds6d~bE6Kg>T<~zz zP3jC`2EjbCfLL0v3h*uc4>QzDdj#}g#OX;A4IU93uooXP74;oib^PuYoakZjSIAFh zLXt3~g_q{gA>ok0!6Mt1&cYM;b@VghuSFl;qsCq%o#29tiIs5e+)rOyPk>8^M>1t| z;K6w=M2~o1|DU1Roi%)%`w;=yTU1IXE4K3{$>Gs*alXgYa^Xc~T=7D+tEm_lQVi^N zy?J6reAtM+vW133dS?LK#*MsL5hcdeP(5@E2JD$8znjyLEw~2Rx!s^5d0@uJI}_6q zhcoke3_d4Ya;jNuS!h5m*mQrh{?kdnAAT~u9{`_^4JP8r3LmBr79(WXxS=SDoWC1A z1`8ciZSiK-xTXk&WKJX>sIA=W=FyGVO?ePHJ>vFt+Dd3<_)Ak_BV;OB$j{{TEvT!p z9*Dz1Q5672=^EDiOcMSTYQa89G)b`XPPC~9v25Osb3g@rnef8h937k+p%|h@|6Ob-b5jQo#JUPha9c zulQpVvY^1w8+Q!5cwC`x150Ud3ruwIf+T=2Dee0b8q5`^Z$j3H{yW4kf3uLozz=6j z#A=7a%-VO1+8jE9z<*4ky`M7H`3X$6w-`mCG>2G`(46-~;Ow`SymYc(OPP$!9_Zf@ z3|%P8uHIe3({Xag$IlYRAce@EQKQSHD#<3gKCo^oG6%!#%=$zEIb5Ga5r>h(s zgnXmf5>vc%B#&Qadr$n_a3fX$057*cSym-YA_>afFdRiZr_$QnbjC0VdLEfp$E(q_ zxhKbm`qG%B7*Tj2G*;~4yMq3c9XEY!s^fi$UE*b}9siR*bo_imP>{Prcl*i4LQkT? z^|cVV{D!pHY@#7|Dz#qb*~bZJiBKNvJ+Lq=h{}Qh%!x!FvjQ;)-koQFW)edxFDZr= z8iXo>bAE1x?-rhu{n)3$44lvOW_vwARsrw0`Yk}JmlH4mK!N+mj0t`smJi;Gnci#- z?IOZ{=esbi&_x)zz!~-PWA3rJX+k4q32=bXS4FTy3Of(+de{^Mki2kLh%vIg?h63U4!RlW3csKHoBYk7)CzjE~ju%{=vx)01iK%KDvbj{P2X6S(6*grHGXz#C5J0w6e9E z?nfy*)>Ho%@(qBl;x2g@P$ZQ;1~35myc>XkzD44QIuimYd?Q!n?{kHJ!UeE(L)U(t z2)aEsfPx$^CMLiY1Kh=-K#O$K;bDekJc)WG;l-jD>+JpB@vjiNRc!^xTD?QAAs(WQ z@AS}%T}EoaI~Oo}p{=10=Cnep1UIMPH6q|!idlaN*$X;`2@&neN3Cy$n27Q$MY9$H zuuZ!^kjmq$AhH0-lJuJGy3z0bTXj5gdt=T+|IC+uR!wpQ7@{yDKp#MfL5qgI3F88x z6Zp=`Neo3^2n_KNpu~>!iBd$@OKZM_#(5~d7GD94+E?;E?rHnb=N?b7npwNBnsZTJbty7*XQR0p_hnIN9$v4@kgZoK!@tLo2G z+Xf!@H2+FH;BOkxi=4rYE)|VrMQ0w3L!U1f1c5Rz`)p(EC4J%tz#fBNaT#cKQ~u;R zdI>3up0d;Zsa=wsK|k-cXmP_IDCS0m-RtT;KaS5Jx&w@=FKjRcAh}tmQawAncRE@b zOMt6!+`(eJ`muj7r-S{3jjw6Q#oKXnu}m2OGzhF=L@Scz`3KI4E~Hf88b{NegI9Td z>ov2mIn;I^x3E=NwemcjLvHK~I!sK~J3rni5R!T9$6ZArcp8u9G)Ct0Xt5sep9)5tzSFj_Sd1-Oz#d%lm?h^!Ks3Z%5=M)@lmmYmb9^73U1Z+bK|Mt?AL_XWw> zc??#nlKg3m;-0P%nm{J79~wO6gkVB^jXyd0=YF#?BMO}yi4^Yd;C|f{xK45+F*RyO zzsR%NAtAqfyO3~<6kk5b6u5jwUMVo`vo_$IV9ovfe6rT=!f9?o7XIc zitZcgU0G9yT>B+bKEfqOuGa2&}DK=a2;R4jmK`tZqKohwcAOe9_3Oh8s-vbCkgxyexLrQNitbt8EjVo@9%+>(dqC!zEjD&5En@$Geg6j} zb_&T-TRkhH^mWlQPj+QM>B{#d*YiU}$zf3pS#AlVP=4fph)w^YjS1`&z?PhOYBj!W z<`f1z1%$XIrgwujIGR@f{fr!}sX0lQPC!f3P_N7{*H%#YW#C(qFm1pXkua^;;(P4j zRZ&tSrcgr$)@X2Xwzm2Pw)qD7u3s4TPNUi1eLQf2jh&Ftc;K7VnwZL){H>qGL^<2{X>e{YLI8-t&`6kP$*{O`CW@^`1+)p~S6-`H{@6qh{ zTkZ6OLKdYo@_98Kv0C(;UE&=jOKaJB)u=?=jGRmc;}xf}>pu$a@7+pDOKr_`Gugl) zu{@?{@6-QPBdP9(ukw4y96ZmWc>Xh}nSYLEonh5V8S^3tdD&XtEpsbzz53MV&_}31 z*lfkpZfcFcr;kr>zuRoTNR^XbPz-DNfX-R2fy>hTEXQ+uq3bGsvE2C^hs96*9(J%O z+3Soz;B6I)@a=`Q=d)kf_Ytb{nxTk*|9f09gPO*>SWX{<@B9KYg}G%PJ!VMOyxK8uIz4V;ZQh`%iZM?9{ceI6kfUm^j zPUT(guCmc~eoUpV24}O4nnN;;VovQ17LBdRBA-3I4Z?5tu17GF6g+C$3@(@~25w4s zn^#d>e4wVl$;r9aT5}bDLntV4k5f1}^}BT%tay4#G1;EeH>!FI@k2FGs|Foeo@VOR zu7nGnl&v_vHDS_hR#?@&<WaP%emd!l!4CgnCAsplxC}kMITyNasHFv6IRI5vfyrJn$_9` zX^dI{w$ZQDG&DX?1r;C}FkoJ)9W(8*W?fx>yI^<_H(s`SE(q45(^<0NgS$uiX^LrX zr(8C0F_m34m- z9(g*wk2cGc{-%Mh7{3h8E>0)I7@D77)g4SaCaOTqymji{hw%(`b{d8j-!e1TQ`2&) zo@2k;o>qD>DXkW7%&!TyrNm&Qks6C1Ho@AVeKP9ZP)dqaVg!SGrf8)f9v%#oOjp%r z6LfWT7iVYl!TRk!6mq{$>NqwC+=Z%}8x^owL~eh(Rp0Hk6MBW{#9oC`j>cJ)KFHx; z%gVRkiSC~vZC?6D7u;8Oh$rz=qf~#Z+{I)Rll-Q`Vd>;{w5~EFt~)raDUfD5N1?WOgFAf!F7k zz(mLUu_)TQ%LnsZxu=c;44i=X_v+3b|G(*^vP&vrt=7`=X)&O+u3Fm@#Q296S(fTK zH5G}@gWD$e5tf(J3dRI=nK!$$DZ-M@V(ya0@d=}scG9=?Hn)qV^ph>vj83b7QkoGf z1}?5Gklsx%1{j8kRN|;zw{gpdijP$VFDYqrKOaxX#iCR9OJ@FMqq4T^k>uY3kIrI_ z_+CqWO->YiU?vs08Ty}($SUTGFZdL^3&~FhmOb_2#WW64N}PRgTV$oC7B@DsZBJrO ziSw(KlM_eD8Y*;M=4tH(ew(7DNC-;eCwS_3#$AnDX7ILP`_+G~2Fr@v!f_Y(3$NvJ94k=C2g3 z)Z3qCw%T_ITr<5=Po(b}2JXL~J1;^}SnTJg+<#YA(rE=4*1EVfYN+ZLN4)THwz|`m zb&Kf9+NK))F3xWB*)9t4ECDxblSRkxE!CCkOD>@_nw*DB^!W~FUNZT`WsE)RKE2@g z%Vd@gpCxy+-J7%YcSBu`Q~1(winwyWA93a9yw^!zSL+ArC@1W#+*>B(n3d$^o5`S? zr{&%rQ+aT`HtaoxXvxV%{`C|I%@ac{P*hKm({;c6(S1=2ZH98yAf?{R3e@NebdPn& zHarRZ;jS(kZ&|!-^Z3)Jr>|GCZdCKxnX#Y5c&W)tpH0yAfWL%qdBXrMB5Lw=**MeuY-yIC4Nwoxue4=Y8q{%Yw40lCaM z+0|8+4vQgin1^4dXR{o;Yo*Bi7q67OSkzQg((;-lPKi>Qoy8h;GhdihI11;X88Z0< zVv7_Qn~1>R1-7=p?CV_Am!Tx4%q+vY>@yGhTI)?P9Hk`gRx^$BwxE1gyc{d7T!RsZ z=t1Rh)FZAkbIFI<{C|c}BhM ztlMyKa14}i_z)}#Q?ysBu_6w?KIQ+pp(SeG4z1|Dd9Za$o0rvFTI_YLiqWBc=Df(v z)hvtsc?9Yokx*Bj7sY zp2_cB&G1dC%6`8p*VJFlBAW941Eh31PVRX6{dbo8ZZT?RrfPY0oSQ-pzYe(5r25yd z)!Tj6R-hGXhGlk$qp6IV?DO;5t_K0}Pb%bN=yuil`NGf7&kQUqT6Q3*(4-j9`h!(s z_I($Vj8u1PiBcz*SVnpE{e0nJ6^ExyY8?bQ*;_!pTiTI#wEa97pTg-m&cLM8>z~y; zxGvQzF)29Jw%WB^J)&YL=xBt;tFuFrcbo&luEt19EG(;7yC;~a`XXcUg@#6QTqZX> zy;EcXY~{a>^OC4Ds0*Kq_VL^zRM2VFWbuCeK3ey5OU1a<1VhWLFna=Pmzt7YoxF85 z%WIc<{@&yAz$fs9Q!!B?Y9UGIMmOh2aq}Yfc9y7tgp^cOV`C$zLKMD0R=u%u-EIC0 zsm#E2i1tRC$Tohv3N&u&3%mCt?n8|pr-y%hg4YuJ5&qGmnSSfHG-nyI+GmsNC|R}8 zmhgwJNA|YMu~ji(j;4Ie zQrcQlN?~(zd~dF(1N(W$uh-2^`zk^rqW6N;8pFVgSnSUf(MUL*HVZUHpN%X+eM4uZ=F+}J4yA{P`0sOzce&8zmw?=(jG$kN0Q_569!X-4-4wg|5AuQ zJGWi|6U5y9?6{R+FWc$5lrR&2s}YflxzEDmwzaUVY4vEXDC$u_pJ7~d|K_^1F<)s% zb9mOgn_>HKiI-(ibtRNmS+|v5+}GVJ(~+j|;hy}Z8T|#E3j$&acbW#=El!bmu%ckz zDfjcxmmGnlxgHTwlUPNv#2GR71c}`nS%C}5vW9^)UkN4pIIK5 zatJ#(#1{5i%L@xMB$gD`R8_0sUg>r{!q`HFsJxffMU=? z|6W$%VQjKsre@`$NbB_#v)k?O>e9WIVDni7O$p2lC|PB$^4rZaz z{I}t$JN-<9`=HLK_wU|;ZkFRC2VC}AwQW?Vv+3Ng>>3aU!%-8tW@_G92>}9=Pi{L8 ze_o1+9wfh}kvU?@4pH4-A;TEzpzaV z0-N5)Y!j=K_HJA0f4;`wM#+MG)XV3qEcTzQmtv?H9~S#*-AAakPL}m9=NLn`7rRGp z2zj_fl$4~^Wi-krD*4pae&WNZnJp;3i{ zFhFdcv{rNPL-z9U)>xQI9$ffrCjA220xk6@lyD)MQ(xP^UhQi2P>`3#Z@|9;8t{ne9(zua`7@1}OQlQf!xIOZ4Nxd%z#=f23$& zHqy?~CxwakZ#{bc7#i4>32pe_#hK=OrqC+u%PNW;JqD$L&tmwdTIFBQ7J23UfBL#Q z##~_#T`YMP7xmVP$Z?H=N=_X?BNdLe(r0d{HAag)+A5E&&ENgv%Z-XL6ec+e%rYdoSeEfw6dd+FgCiEF=1wXP zEA1UmI_Z}60(ub;K$$Z9oj$W1omFB<1YfsVy zLS9V@NxIcEh$88yt)r5Ft7&4nMBXMR{WRD@C4&geBQHrp1Ir!b5u2P!d5fbeClmEAc z`11*y=>UdJSh>cI3<0HWNB!xx=U~7F1o=(926rG+_mbQdp+?7r zXr;WOzAc|jMbf~G4}!p=4}*Clysy5Z#~%EpP3t|2H|5jzfy3(o;>T`iiyiB5XWKc6 zXW6Zh?uwwHt%i$JewJ--J+g(q9=EmSS2r<`-Gt4`RSWP1}Ln)oblcvK@z z5G%G;=eYv-P|Zr9@(l2ju(h-EXF(bs8L6tz>xHI2H4Iq9i>;qaMCcB0zL#{_#%+Y% z4uN0hH|e1Z^l?^#p=NdWzdAm(STCz4@<{B=pb!UR+hB^5@Tr08{+`iM0PC5PY(2tU# z3;tjvIsDQ>I-@DjioQPJk<*z(D&`-|W@`4f54VreF-Fcy<5FfWgVI%F3A`8!h)7tZ zv2h)h^Y_U-9A4Pgo+_*T(sW<+K3q8&H&HtHTJyW~@vO#{*+JF9vZWF!OT$RHrh0^4 zHmiN&RYCRgj2MUNsH&n_CccDeBCky`4H;`O+pzHGo1_MITX~813gpagR1`G>L}N%6 z;YgTVN7>=vD<9Z+xl4jyh|t`vRcE+qwv|JTosW^W85%HnjZ7*tQC-$}o=Y6;{O}@! zwbEFSx6_XW*%@ef`WU`;{rz5C5eiHEuov}Z0i+|#()0)X3?)+PT*Z#6hAIsc-CTN_ zh6VGt4B(axl^rbxOYRR0b+uY13Pr6{j*FeAv1!R_g;U+8H5s6mhl<#=PG&KJXrfe% z^pn#qHjSm_@`)}@3z3GH<+5_)J6sD~&GOc9eg?t8jB=oPw8-yn@20v{WqGPpLT3Br zWP}l=(I>E^RK*!4)F<4J4HPzvc}={%4g%L~1x}I!5+AMkhiyYFPn>IhFTQ!uA=1Fj!87kJ$0ez zIfnZ=ru(n1iwpOEYZH(W1-jt~sVS7sYGM`x57Q96TMwm zBG{%SCPd^meWJg_v5xud8`9aSo2I2z(OR#52vS>8)jMw4wzs_t0Nuqds;hv(G+Zs3 z%M}z{GQT92*47#{>`4sB2#RZl=zJmk^W%3OA|zY94lF>5x8dv*5#`Dm@(La?vD>*R zYDw7Aj&<-DNW!akTLt3k8`WT41b(gHvmmPMAa%9BXZI_w0QIHJIhYdP16>Rl9E3;F zaSiVk8w81T#Wb(hIZ-iG-DN#Y;&ET;u-gAszc@}N+|xzzg^QyLSF{Qll2sA$Xk_RSgq1nHpDsvjY4iNU7me;A`tp3SK}aC} z*)$3%xJlceu1MH)Ud_cEmXQ^ksnwVQI~qwAeFm4Ym~Yb06Ol2uMF4t*kCf>+%3{r6Rv@d0soyD3w{d~vkeTCIG8u8*` zM=F2+s7R1Z?DswFZRs)K)WC_+{gZH%(4)2=VOX=Plvg-TNv7%{(mDYmT+-I6ipZ4J z@b-zj4$F*Db?g#lQb7IC8td6QHtMRQpol_pMs6=tk=&FSpT_jY;DK3xv#dH_vNzb|&0HhT$fp=|I-44>6XwPN(Zl|hS@kF0TXsXg@ZmR3%({NXJYTHJ4Tgg_EKRH&8K{#s zJx~cT5uC*Z#r?j}1=8SKD<{czOdMtP?E?6t^i!!&Hhz~7Pm9;v=iyr7KPQqo>>+N;oe@xQ|R)tUqJNju0#kA?)LGy^Pd{^&& zn|w{$``>Ie2(LfO4CNM8R_YS5H8zvi>1H8=JG>NYdY3FQFgPmPY-*Ma$1e;I{GFXz z`CA%3lyHkMLEv+`8)$oe4G-oLRCp!&Rd4;MTgt$R`BgpF$z-9Mp+Pnyo)3>pjWRcPD)WV}`_F9jkwvTdFN;WdMWZBxQGzt@@T4%L$an7?SHYv3jgD6Xz#MMedy~$ zPcFO}t`Y(2u>UW2CeSJ<=sBTG{Xbs64%neyaC6Jl`POm9 z=bI?Hu%jn4nQZ87+H;TJN@{rsZl;9OHNN=gQ1xImVffAK#k-*Y%wb|KT)XMxaB;3a z)F>Do)~LNtlNYuJ{b!cS|F__#BnnnF{FU|LORuLOS>g8{9@mwTx%u;Ui#MPdMx{^` zRc}8`5D|S-H6Nxbf7AENlVg#P6wkaHcumtf{>|UUKjw#JoX(!z9&VXc_i9~5i;Hgx zWOX=tUcIV%-t%^(XJkwa=W3cjI5z-vd9M;TOf&73(Dxmh zUmS1o50B}1Qc8(io%*smjH0|fU1GOB3|Yz%l+^e-|Gn~S70M|Y0&CSAa-WpS|sb+ic4&*<)6dBqc z0E-EeKYA@~==SQDa+4;Wo1XnuJ~dlYPlEtP`6mD{_b!dL?0S#K7S-*aIpL5(`jLyu%k2Pj zy8O@N^QUePHI#7MHX>(cBL4bYT9telDCeJZ3oY^;#Sw8>ZrJ#DN@E!pejwaG=sY)l z{Mb08{6*l{_;|$S8MQ!q>8Fm!H_trOyf&(XR=VX%@2vQn&B~04X`BZt+vV@Z1oo?W z7DK)q>)o7;zS4M-v{UqDH4<3DM1H?Vq2QhBMN@+A>M%#d(dez-`~ip0Rj6&FoodsK z!g{=}xb#lN5D+Y|8}82?`;fG|D?ISjKP4eyIiZoAt{8C-9O`Zs#0fC!-f9)I-y}1< z$p+?jIPom|a4(q=p3%s8`x7UYceHxl*X@4!r9c)#0hhsc4$lx{`=~ezI($#nE09yavYC=Vv83|YeOa>!12KT~+Fh)**rXgSM_L6yn z2x0ZJ?my~-n&N@)`W|hFyN8b1beQeeStd)3Zb;59zV3DFdH$k)_N{j0GvC>S$${MP z1w+8dzr76tTQ}qj-6KZVt#FPQ{VcqH zJ374AHRR_3M)Ic#R2?jdOQN<7-W4s}qcRF)a{-wA{aW|Qy&wwLMUwSt*HH50let$I zVd9n>ZIn@er5O?ht^uqB5o1yL<{!r{v%Xl^Z8Gr5GWuMzhb!SLAC-du?ZY;IK6|HU z2qq#|Hus`oNb~vIp|DTqEZ4%tCEWOxAy|VnMNTMSkk~W9pN^~*ln_S?+@EaZS%;{E zjzq(5H-9v&uCA`vk21_mjZ#}vF?whC>h7(m|ouf-ko9UR3O*0TlU+rER zh|U4^GJ%t-lv_OJ;Y3|`{DYvMgPwlShbBdrmR)La133F}VaKL$hlL~w^_5Sl-kt_= zD^t#)_I0jnIJRs=YyjKXiz9w#SjM+*^u8JJPC_v8v270F`#wXq$Bs)_waslzlh+jY zOfzk-=32wiOABmCt2HwftPfimbfOqz{2gum1m|A`w8+1Dr;CMTm&Y7+Y+JK{AKe&T zbd4UZZ~Qfc`HJaie?6151K!r$t=C8S0U0H@@!;T06lU9Oe=Btu1QL44{bCGWQ5?CP zoOUQ)FuU{axt_-F3m+L6VPI@Y-lUfl$y<1cW5SUfZv5E$U;Wo3%%ez_6*}`x+Dy?> z$e~v4yB!4|KqRu!5byDi&(+w+jXC~@shFBuv_yj@CJ3A=zj@+Ho zLx9hEPcJd)6%*mGXTd})Gc>pQm`-_l6uz+y^k9zByGx!c4!JnXl7NCo}Cmw25k$S1^JHv(@Cyx_7&+B zJ3BqBY^Wsr&?I?lM7s|IjAvdT-dohGS$FxQG)1pUXcnGNGAnSk%{3j=l;OnJTeyxK zhEz#sXn1`I0wrz$wu<$SLS%Zd<$H4)E)a?77n=|jP0aFh<5GCm2VYz=YuF{7UG5}} z;Kc$VP;@@gxI~E5KXdW-U562CXrpoXT9?%vKoi%zFk50{fSW<&QfL)y_IVC1$ zAMh0HOrE$@P(O17@qu;y+UnX}NjI8#!|va{5gp<>i4g;_HKWcFYUf9K0hNLzDq;NE`QWTarzUY(@kk#R&LY&LE;@W$*tmXO+=S<#as&ktRf#+_)N#5~id zBX8ZvP~XbxoU92vYb1L|L`F|dEneW8)Hn3a)afDurEI<=yMRcOgu}{1`Zc37K!+#m zU~n%^whq~Vbeqzbp-B2m1tYHKH4~2#kiP!JBP!fNA;D_2p9`W!l~U!coY+>bkUBZM zX`Kb$hCH#2}B4e%u}zi&{q$r#2rgqkPXIzOtt6y^u4q5 zRP*UG`()GtPr~devXX=OBgLqS3RGht#ibQbC=<|^rBjLv#zc>Ux}ANfNLl)!m@a39 zqg5t;f`Ax{QK~hS=*a3(bVrE>-qvp=LMDCHz-os$7)C6Z)qsTil|s@n?-BHq7DC%j4}ky)0cK#UYq`NW=>XwYk_92F6=+_%F9>{w?Jg+$Qb4 z8H31=(dTy;GFPQ}b9j#2ePjRqHvliKZHyl`Z}iiE@?Pdd)*1-EhoKwH4ipc$>%>= zVz&Ei7*@ajr|*^yGnn7J#W)^ZBGjXgh2w940U|OhZXv3wS}$dfI6AHporf*4Gn^E^ zq+$L!)nE)h{HPJnTzVIlXB)YL)8B?$w(=`y zjmY?d#_VN^_q$7Il7SL{Z8D#$RffUt&lo22u5|le6Rd-g<95vL(rVM>w`F>x(g0!1 zOH-cW-`Mx>69A2?)&*7A<)o#8Rn{ZqJ?`t1hdusmQoa1>=-EhDkeHBgbW(T0<cAy5tq0%wMeM$CNvsu=_Q za3Z4Mw*gmgf-Y>CjeA6SC0kHXBb7*jc|}wGn?;-NQktGvEazd7dUeVI(&qHPpawA3 zap!LC%YJ-7UEF-hrIFVpgH?Sc2p}x*mXC=wih@^1#(F1(<62)5YQ@moa+xx_Lhh#= zd+}!5Qj=U$sPQ-b#g-ssAEK7zLUZd^6NvgXNFLuYQF@h;*JS z6-=qV9w4+r74j6A9LPd zU#aTJ`Y9HOPD3Qx6Rnf!Q3;v-^x)6f@cKq?5CO72I#Ry4SFFLaD{c?# z-~qq*pquuvrXU59tAfmGIhNHdOdg2{)n6EYvmp*#k%(Hprim27C~q^Z$%0=c$^~~$ zN~7gdjBT^U7~x^sQMTZgPtO{^6_tk!)8YEX2V-%3RqDyA1iH)9aBZ?s!t@1NgDgM! zEwLCoH^E?IUufggd?w-u?s((((90!v6;I<%uc-&>DMGTwLDBTzL@=oLu-V3h8$v9= zWLscYV8wo`Q@+~lN1cc7Tq;mF7FQDzdiV-*R#6D{CW&!kvQrE92i*D)I7f2>#L&|hrt7(9h9hVos_esJnFW5mcc$fMA~6H26&)zYy{WB%;dEgR z?-e`eQNPw6w(kZj%LM3q)FkKb1i0DXoUXJqK%${$78nE?l&lL>zAzcb79yDtDVxSQ zTZGdk$jvl=_y@i96QHJn$Fh^I&xR=n1|?YbYL9{{UZTxd+ElUh!N>{lo2&{1G&@QA z;ut+fXp90UD@NVN>bB+ZjMucPEW0Sh3`n(j{R00$ETf*chLaVL|AN|fFG{cefq&SC zjeJ~Qqv^@}Dt;w)X0N+9CfAne z+bjjj4i@g4M-v1-XGdurGFV;3sSW(#bzMO$7-CgzdtN?iPnPVe&oOI zT*%h_3ZO+-NUm4|IG)^ix(%;EaEI$~e*A^DLFhC`&MHx!rKfs)Jsc$Uu46JpqTIN5 z_mpV{G$DdTr(#v1VLGTr-YCbC&vbt>L)xQtO#6A_9^bQ)VbS>%ostEITdj-Q_v!9- zaBqA}^C1Ge$JNbC&Y}Zu!Ikr*`I@bMM-V0prBX(0I zC@0k&toWIx^br9CiGLOF7U4tXYTZCtI{ZsROiJ_?>-g=JQahr><~3VnSl`! zlf|`b_j405LUQigwSK))W=j8~neprm+zrl5nlBMEzm4n+)F8s#1#&Msr|;-|N@9mJ znmp!Vx=$O1-g;|&p^#@Z0n8**BH^JNdc(`AbXc0nia~e$3aODLj!ZjG{VGk$^{C<{ zD8gyzHuGmHh8bLqJO)f&@&^4xLR6@NE8(3L6R#jR1U^4^B_>^K)mAE)2*vN>|r ztmn+*vw{w+)I8`TE2V@EFxt?k`CAIGys_%(-6>}JWes{aH zAY}!uPG+do9@JVc2}@~9Dck;ie9QmtYKPhIC3)WOE4zz#hUEpuw=)!zp1s^ld@9r; zezlx8+Pz7ibN_^_o!(_}KNIeBC{4In?{ql`oSH?4<9Y_FB0cqbGDFWw{F{DW`}o%O z+>4D8QthwyUF>PL+BdXmWlo6rV{k>2It8(Gzn#+rw=G$c*&4y7b5lFEG7`2yl1NjYp z%c!jKje<}bO!6s+)$#-C(C8S@qE9=!`SexsEd$Gl`;zxanC@>_eK=-sN~(~4-Q(H) z+&QXgDAt-S8?RD$e~xImT!BrqxVfo(FgQugB=fOj=A%TH&8K@&D~0dJom<`WUR*wA zL79Haf^N6`lyuEc*rV!lCv{IJ(XI27MP>G2Av9rnyrOw8|3Xq(T zn*0^gd5uF&?0{~=pBaI&qDf(_&58>Kd^7XsA#jM4Sq{nw6;(kDL)t{=1=M_aR54I3 zKc@^*3t=WA#oy6Yju`nUf%8d&JWv=|qPcOH=Dc(RTZkICv8taa_$qEG&U3`s+<>Hq zzi7?Z8(r$I?w|6hBj{sCq^IySwzRM9qJ;@nogRwExiBMVVp9T7hv1bnj>v)IO*vV= z?BrWGZ8gj^;=uBa?uRqi*EA&z3vvw4mu|7RE-!qjZF~m~pYM zrVJ^wN-JZ#edx3hf=owq__A;sro2PfkdY!gzTNu4KmqL6G9C+~d(fO{W;tS_v7?Qv zM3NRBd!hBPxwXMVoZ7^Zzd?>I;pWUGBR@>MNSiX5S4RqQQ2M?tL1u6nwdixIdG}w= zD%c1m-Lf>*)?dwApJ0mOuI}J*Jen_tWYt4?Xv$ zTEMI{DMoZmDp5Y);x;%!EH?TtmbOOLOO#EcB8aFol5AyeTIQJ;AKXBYd>a;`e-7=OVMn+un6QLw>qDIAPG8%`hdA+*nJY5_`oB zX>sS#<+Vqs@+(VfY>nB}NH9N1RvCJAzmc5;|zM@(o0+3Xh#X~{0@oo?su@OO%2 zi1?k%5YpB|qPQ)6M7|zVtZ0?cDaRHpujk z_QT!Z;52SnfL!ueNtgMLO-c!q88!LI4uq&Mb3TJb@gO>wEd4Uo)MnR0*sufT#6B#5 zD3a)tKrr18kjH}`U}w#Dq4_BJk!ehqict>#SQN=3IvpkmZXT%2cYcWc?RdJ;+cq9yehOR^8_ZQl*O-FF}K1{@u+^cywj|tI}r{ppY?O;lk zLvC#Z7+CJWmE;!;5?0wQrtswOObQ8j9*V_f{qyMOj6_>(g7e`Cf=Y_HyjWe@AgL=+ zA9#|4O8(z1n((BKCxuZI8Z-O9+_(R^w*zcf9e6+g%g_5i4)jxy{cl9y|1z2XeW*St zE2tjy@rNTu5%D(8&d$A=P41gY*4EaYfH%4J4T7&l`M9g=U_A>YqQ>wA+{Rs; z2S*|VD@w*Q)tvil#U&+6*5`URXrJ#LJ{g|-sr9w|L-d}`S$h$?odk#!DmtW4}u6BGSe6b_}am{IKhLx+k-=rc=tZ+gtYIB T0BU|51iVfhw Date: Fri, 30 Jun 2023 15:12:11 -0500 Subject: [PATCH 11/33] Added SharePoint to MS.DEFENDER.4.2v1 locations (#402) --- baselines/defender.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/baselines/defender.md b/baselines/defender.md index 3c066910d8..c8bd6f6165 100644 --- a/baselines/defender.md +++ b/baselines/defender.md @@ -227,7 +227,7 @@ blocked. - _Last modified:_ June 2023 #### MS.DEFENDER.4.2v1 -The custom policy SHOULD be applied in Exchange, OneDrive, Teams Chat, +The custom policy SHOULD be applied in Exchange, OneDrive, SharePoint, Teams chat, and Devices. - _Rationale:_ Unauthorized disclosures may happen through Microsoft 365 services or endpoint devices. Data loss prevention @@ -369,8 +369,8 @@ MS.DEFENDER.4.2v1 implementation: Locations page. 6. Under **Choose locations to apply the policy**, ensure **Status** is set - to **On** for at least the Exchange email, OneDrive accounts, Teams chat - and channel messages, and Devices. + to **On** for at least the Exchange email, OneDrive accounts, SharePoint + sites, Teams chat and channel messages, and Devices. 7. Click **Next** on each page until reaching the **Review your policy and create it** page. From a04eb7be725cb802ab24531d8384f0f7d8efcbe2 Mon Sep 17 00:00:00 2001 From: Cassandra Diaz <47129205+Sloane4@users.noreply.github.com> Date: Mon, 3 Jul 2023 14:58:53 -0400 Subject: [PATCH 12/33] Update aad scubagear code to align to revised baseline (#408) * Rearranged policies to match baseline updates * Added versioning for duplicate unit test title * Removed unused import * Updated MS.AAD.7.1v1 from less than 5 to less than 9 * Updated comment? * Updated yaml file * Comment update --- Rego/AADConfig.rego | 590 ++-- Testing/Unit/Rego/AAD/AADConfig_01_test.rego | 1146 ++++--- Testing/Unit/Rego/AAD/AADConfig_02_test.rego | 2994 +++++++++++++----- Testing/Unit/Rego/AAD/AADConfig_03_test.rego | 2061 ++++++------ Testing/Unit/Rego/AAD/AADConfig_04_test.rego | 1017 +----- Testing/Unit/Rego/AAD/AADConfig_05_test.rego | 221 +- Testing/Unit/Rego/AAD/AADConfig_06_test.rego | 70 +- Testing/Unit/Rego/AAD/AADConfig_07_test.rego | 758 ++++- Testing/Unit/Rego/AAD/AADConfig_08_test.rego | 151 +- Testing/Unit/Rego/AAD/AADConfig_09_test.rego | 1029 ------ Testing/Unit/Rego/AAD/AADConfig_10_test.rego | 968 ------ Testing/Unit/Rego/AAD/AADConfig_11_test.rego | 83 - Testing/Unit/Rego/AAD/AADConfig_12_test.rego | 75 - Testing/Unit/Rego/AAD/AADConfig_13_test.rego | 285 -- Testing/Unit/Rego/AAD/AADConfig_14_test.rego | 194 -- Testing/Unit/Rego/AAD/AADConfig_15_test.rego | 78 - Testing/Unit/Rego/AAD/AADConfig_16_test.rego | 350 -- Testing/Unit/Rego/AAD/AADConfig_17_test.rego | 186 -- Testing/Unit/Rego/AAD/AADConfig_18_test.rego | 159 - sample-config-files/aad-config.yaml | 14 +- 20 files changed, 5207 insertions(+), 7222 deletions(-) delete mode 100644 Testing/Unit/Rego/AAD/AADConfig_09_test.rego delete mode 100644 Testing/Unit/Rego/AAD/AADConfig_10_test.rego delete mode 100644 Testing/Unit/Rego/AAD/AADConfig_11_test.rego delete mode 100644 Testing/Unit/Rego/AAD/AADConfig_12_test.rego delete mode 100644 Testing/Unit/Rego/AAD/AADConfig_13_test.rego delete mode 100644 Testing/Unit/Rego/AAD/AADConfig_14_test.rego delete mode 100644 Testing/Unit/Rego/AAD/AADConfig_15_test.rego delete mode 100644 Testing/Unit/Rego/AAD/AADConfig_16_test.rego delete mode 100644 Testing/Unit/Rego/AAD/AADConfig_17_test.rego delete mode 100644 Testing/Unit/Rego/AAD/AADConfig_18_test.rego diff --git a/Rego/AADConfig.rego b/Rego/AADConfig.rego index 1a99f4dd80..afabf2391b 100644 --- a/Rego/AADConfig.rego +++ b/Rego/AADConfig.rego @@ -4,9 +4,9 @@ import data.report.utils.NotCheckedDetails import data.report.utils.Format import data.report.utils.ReportDetailsBoolean -################ -# The report formatting functions below are generic and used throughout the policies # -################ +############################################################################# +# The report formatting functions below are generic and used throughout AAD # +############################################################################# Description(String1, String2, String3) = trim(concat(" ", [String1, String2, String3]), " ") @@ -38,9 +38,10 @@ ReportFullDetailsArray(Array, String) = Details { CapLink := "View all CA policies." -################ +############################################################################################################## # The report formatting functions below are for policies that check the required Azure AD Premium P2 license # -################ +############################################################################################################## + Aad2P2Licenses[ServicePlan.ServicePlanId] { ServicePlan = input.service_plans[_] ServicePlan.ServicePlanName == "AAD_PREMIUM_P2" @@ -85,12 +86,13 @@ ReportDetailsBooleanLicenseWarning(_) = Description if { Description := P2WarningString } -################ -# User/Group Exclusion support functions -################ +########################################## +# User/Group Exclusion support functions # +########################################## + default UserExclusionsFullyExempt(_, _) := false UserExclusionsFullyExempt(Policy, PolicyID) := true if { - # Returns true when all user exclusions present in the conditional + # Returns true when all user exclusions present in the conditional # access policy are exempted in matching config variable for the # baseline policy item. Undefined if no exclusions AND no exemptions. ExemptedUsers := input.scuba_config.Aad[PolicyID].CapExclusions.Users @@ -107,8 +109,8 @@ UserExclusionsFullyExempt(Policy, PolicyID) := true if { default GroupExclusionsFullyExempt(_, _) := false GroupExclusionsFullyExempt(Policy, PolicyID) := true if { - # Returns true when all group exclusions present in the conditional - # access policy are exempted in matching config variable for the + # Returns true when all group exclusions present in the conditional + # access policy are exempted in matching config variable for the # baseline policy item. Undefined if no exclusions AND no exemptions. ExemptedGroups := input.scuba_config.Aad[PolicyID].CapExclusions.Groups ExcludedGroups := { x | x := Policy.Conditions.Users.ExcludeGroups[_] } @@ -122,12 +124,15 @@ GroupExclusionsFullyExempt(Policy, PolicyID) := true if { count({ y | y := input.scuba_config.Aad[PolicyID].CapExclusions.Groups }) == 0 } +############ +# MS.AAD.1 # +############ + # # MS.AAD.1.1v1 #-- - -default Policy2_1_1ConditionsMatch(_) := false -Policy2_1_1ConditionsMatch(Policy) := true if { +default LegacyAuthenticationConditionsMatch(_) := false +LegacyAuthenticationConditionsMatch(Policy) := true if { "All" in Policy.Conditions.Users.IncludeUsers "All" in Policy.Conditions.Applications.IncludeApplications "other" in Policy.Conditions.ClientAppTypes @@ -137,36 +142,40 @@ Policy2_1_1ConditionsMatch(Policy) := true if { Policy.State == "enabled" } -Policies2_1[Cap.DisplayName] { +LegacyAuthentication[Cap.DisplayName] { Cap := input.conditional_access_policies[_] # Match all simple conditions - Policy2_1_1ConditionsMatch(Cap) + LegacyAuthenticationConditionsMatch(Cap) # Only match policies with user and group exclusions if all exempted - UserExclusionsFullyExempt(Cap, "Policy2_1_1") == true - GroupExclusionsFullyExempt(Cap, "Policy2_1_1") == true + UserExclusionsFullyExempt(Cap, "MS.AAD.1.1v1") == true + GroupExclusionsFullyExempt(Cap, "MS.AAD.1.1v1") == true } tests[{ "PolicyId" : "MS.AAD.1.1v1", "Criticality" : "Shall", "Commandlet" : ["Get-MgIdentityConditionalAccessPolicy"], - "ActualValue" : Policies2_1, - "ReportDetails" : concat(". ", [ReportFullDetailsArray(Policies2_1, DescriptionString), CapLink]), - "RequirementMet" : count(Policies2_1) > 0 + "ActualValue" : LegacyAuthentication, + "ReportDetails" : concat(". ", [ReportFullDetailsArray(LegacyAuthentication, DescriptionString), CapLink]), + "RequirementMet" : Status }] { DescriptionString := "conditional access policy(s) found that meet(s) all requirements" - true + Status := count(LegacyAuthentication) > 0 } +#-- + +############ +# MS.AAD.2 # +############ # # MS.AAD.2.1v1 #-- - -default Policy2_2_1ConditionsMatch(_) := false -Policy2_2_1ConditionsMatch(Policy) := true if { - "All" in Policy.Conditions.Users.IncludeUsers +default BlockHighRiskConditionsMatch(_) := false +BlockHighRiskConditionsMatch(Policy) := true if { + "All" in Policy.Conditions.Users.IncludeUsers "All" in Policy.Conditions.Applications.IncludeApplications "high" in Policy.Conditions.UserRiskLevels "block" in Policy.GrantControls.BuiltInControls @@ -174,27 +183,27 @@ Policy2_2_1ConditionsMatch(Policy) := true if { count(Policy.Conditions.Users.ExcludeRoles) == 0 } -Policies2_2_1[Cap.DisplayName] { +BlockHighRisk[Cap.DisplayName] { Cap := input.conditional_access_policies[_] # Match all simple conditions - Policy2_2_1ConditionsMatch(Cap) + BlockHighRiskConditionsMatch(Cap) # Only match policies with user and group exclusions if all exempted - UserExclusionsFullyExempt(Cap, "Policy2_2_1") == true - GroupExclusionsFullyExempt(Cap, "Policy2_2_1") == true + UserExclusionsFullyExempt(Cap, "MS.AAD.2.1v1") == true + GroupExclusionsFullyExempt(Cap, "MS.AAD.2.1v1") == true } tests[{ "PolicyId" : "MS.AAD.2.1v1", "Criticality" : "Shall", "Commandlet" : ["Get-MgIdentityConditionalAccessPolicy"], - "ActualValue" : Policies2_2_1, - "ReportDetails" : ReportDetailsArrayLicenseWarningCap(Policies2_2_1, DescriptionString), + "ActualValue" : BlockHighRisk, + "ReportDetails" : ReportDetailsArrayLicenseWarningCap(BlockHighRisk, DescriptionString), "RequirementMet" : Status }] { DescriptionString := "conditional access policy(s) found that meet(s) all requirements" - Status := count(Policies2_2_1) > 0 + Status := count(BlockHighRisk) > 0 } #-- @@ -215,14 +224,12 @@ tests[{ } #-- - # -# MS.AAD.3.1v1 +# MS.AAD.2.3v1 #-- - -default Policy2_3_1ConditionsMatch(_) := false -Policy2_3_1ConditionsMatch(Policy) := true if { - "All" in Policy.Conditions.Users.IncludeUsers +default SignInBlockedConditionsMatch(_) := false +SignInBlockedConditionsMatch(Policy) := true if { + "All" in Policy.Conditions.Users.IncludeUsers "All" in Policy.Conditions.Applications.IncludeApplications "high" in Policy.Conditions.SignInRiskLevels "block" in Policy.GrantControls.BuiltInControls @@ -230,36 +237,57 @@ Policy2_3_1ConditionsMatch(Policy) := true if { count(Policy.Conditions.Users.ExcludeRoles) == 0 } -Policies2_3[Cap.DisplayName] { +SignInBlocked[Cap.DisplayName] { Cap := input.conditional_access_policies[_] # Match all simple conditions - Policy2_3_1ConditionsMatch(Cap) + SignInBlockedConditionsMatch(Cap) # Only match policies with user and group exclusions if all exempted - UserExclusionsFullyExempt(Cap, "Policy2_3_1") == true - GroupExclusionsFullyExempt(Cap, "Policy2_3_1") == true + UserExclusionsFullyExempt(Cap, "MS.AAD.2.3v1") == true + GroupExclusionsFullyExempt(Cap, "MS.AAD.2.3v1") == true } tests[{ - "PolicyId": "MS.AAD.3.1v1", + "PolicyId": "MS.AAD.2.3v1", "Criticality" : "Shall", "Commandlet" : ["Get-MgIdentityConditionalAccessPolicy"], - "ActualValue" : Policies2_3, - "ReportDetails" : ReportDetailsArrayLicenseWarningCap(Policies2_3, DescriptionString), + "ActualValue" : SignInBlocked, + "ReportDetails" : ReportDetailsArrayLicenseWarningCap(SignInBlocked, DescriptionString), "RequirementMet" : Status }] { DescriptionString := "conditional access policy(s) found that meet(s) all requirements" - Status := count(Policies2_3) > 0 + Status := count(SignInBlocked) > 0 } #-- +############ +# MS.AAD.3 # +############ # -# MS.AAD.4.1v1 +# MS.AAD.3.1v1 #-- -default Policy2_4_1ConditionsMatch(_) := false -Policy2_4_1ConditionsMatch(Policy) := true if { +# At this time we are unable to fully test for MFA due to conflicting and multiple ways to configure authentication methods +# Awaiting API changes and feature updates from Microsoft for automated checking +tests[{ + "PolicyId" : PolicyId, + "Criticality" : "Shall/Not-Implemented", + "Commandlet" : [], + "ActualValue" : [], + "ReportDetails" : NotCheckedDetails(PolicyId), + "RequirementMet" : false +}] { + PolicyId := "MS.AAD.3.1v1" + true +} +#-- + +# +# MS.AAD.3.2v1 +#-- +default AlternativeMFAConditionsMatch(_) := false +AlternativeMFAConditionsMatch(Policy) := true if { "All" in Policy.Conditions.Users.IncludeUsers "All" in Policy.Conditions.Applications.IncludeApplications "mfa" in Policy.GrantControls.BuiltInControls @@ -267,68 +295,66 @@ Policy2_4_1ConditionsMatch(Policy) := true if { count(Policy.Conditions.Users.ExcludeRoles) == 0 } -Policies2_4_1[Cap.DisplayName] { +AlternativeMFA[Cap.DisplayName] { Cap := input.conditional_access_policies[_] # Match all simple conditions - Policy2_4_1ConditionsMatch(Cap) + AlternativeMFAConditionsMatch(Cap) # Only match policies with user and group exclusions if all exempted - UserExclusionsFullyExempt(Cap, "Policy2_4_1") == true - GroupExclusionsFullyExempt(Cap, "Policy2_4_1") == true + UserExclusionsFullyExempt(Cap, "MS.AAD.3.2v1") == true + GroupExclusionsFullyExempt(Cap, "MS.AAD.3.2v1") == true } tests[{ - "PolicyId" : "MS.AAD.4.1v1", + "PolicyId" : "MS.AAD.3.2v1", "Criticality" : "Shall", "Commandlet" : ["Get-MgIdentityConditionalAccessPolicy"], - "ActualValue" : Policies2_4_1, - "ReportDetails" : concat(". ", [ReportFullDetailsArray(Policies2_4_1, DescriptionString), CapLink]), - "RequirementMet" : count(Policies2_4_1) > 0 + "ActualValue" : AlternativeMFA, + "ReportDetails" : concat(". ", [ReportFullDetailsArray(AlternativeMFA, DescriptionString), CapLink]), + "RequirementMet" : Status }]{ DescriptionString := "conditional access policy(s) found that meet(s) all requirements" - true + Status := count(AlternativeMFA) > 0 } #-- # -# MS.AAD.4.2v1 +# MS.AAD.3.3v1 #-- -# At this time we are unable to fully test for MFA due to conflicting and multiple ways to configure authentication methods -# Awaiting API changes and feature updates from Microsoft for automated checking +# At this time we are unable to test for X because of NEW POLICY tests[{ - "PolicyId" : PolicyId, - "Criticality" : "Shall/Not-Implemented", + "PolicyId": PolicyId, + "Criticality" : "Should/Not-Implemented", "Commandlet" : [], "ActualValue" : [], "ReportDetails" : NotCheckedDetails(PolicyId), "RequirementMet" : false }] { - PolicyId := "MS.AAD.4.2v1" + PolicyId := "MS.AAD.3.3v1" true } #-- # -# MS.AAD.4.3v1 +# MS.AAD.3.4v1 #-- -# At this time we are unable to test for all users due to conflicting and multiple ways to configure authentication methods -# Awaiting API changes and feature updates from Microsoft for automated checking +# At this time we are unable to test for X because of NEW POLICY tests[{ - "PolicyId" : PolicyId, - "Criticality" : "Shall/Not-Implemented", + "PolicyId": PolicyId, + "Criticality" : "Should/Not-Implemented", "Commandlet" : [], "ActualValue" : [], "ReportDetails" : NotCheckedDetails(PolicyId), "RequirementMet" : false }] { - PolicyId := "MS.AAD.4.3v1" + PolicyId := "MS.AAD.3.4v1" true } #-- # -# MS.AAD.4.4v1 +# MS.AAD.3.5v1 #-- # At this time we are unable to test for SMS/Voice settings due to lack of API to validate # Awaiting API changes and feature updates from Microsoft for automated checking @@ -340,48 +366,76 @@ tests[{ "ReportDetails" : NotCheckedDetails(PolicyId), "RequirementMet" : false }] { - PolicyId := "MS.AAD.4.4v1" + PolicyId := "MS.AAD.3.5v1" true } #-- - # -# MS.AAD.5.1v1 +# MS.AAD.3.6v1 #-- -# At this time we are unable to test for log collection until we integrate Azure Powershell capabilities +PhishingResistantMFA[Cap.DisplayName] { + Cap := input.conditional_access_policies[_] + PrivRolesSet := { Role.RoleTemplateId | Role = input.privileged_roles[_] } + CondIncludedRolesSet := { Y | Y = Cap.Conditions.Users.IncludeRoles[_] } + MissingRoles := PrivRolesSet - CondIncludedRolesSet + # Filter: only include policies that meet all the requirements + count(MissingRoles) == 0 + CondExcludedRolesSet := { Y | Y = Cap.Conditions.Users.ExcludeRoles[_] } + #make sure excluded roles do not contain any of the privileged roles (if it does, that means you are excluding it which is not what the policy says) + MatchingExcludeRoles := PrivRolesSet & CondExcludedRolesSet + #only succeeds if there is no intersection, i.e., excluded roles are none of the privileged roles + count(MatchingExcludeRoles) == 0 + "All" in Cap.Conditions.Applications.IncludeApplications + "mfa" in Cap.GrantControls.BuiltInControls + Cap.State == "enabled" +} + tests[{ - "PolicyId" : PolicyId, - "Criticality" : "Shall/Not-Implemented", - "Commandlet" : [], - "ActualValue" : [], - "ReportDetails" : NotCheckedDetails(PolicyId), - "RequirementMet" : false + "PolicyId" : "MS.AAD.3.6v1", + "Criticality" : "Shall", + "Commandlet" : ["Get-MgSubscribedSku", "Get-PrivilegedRole", "Get-MgIdentityConditionalAccessPolicy"], + "ActualValue" : PhishingResistantMFA, + "ReportDetails" : concat(". ", [ReportFullDetailsArray(PhishingResistantMFA, DescriptionString), CapLink]), + "RequirementMet" : Status }] { - PolicyId := "MS.AAD.5.1v1" - true + DescriptionString := "conditional access policy(s) found that meet(s) all requirements" + Status := count(PhishingResistantMFA) > 0 } #-- # -# MS.AAD.5.2v1 +# MS.AAD.3.7v1 #-- +ManagedDeviceAuth[Cap.DisplayName] { + Cap := input.conditional_access_policies[_] + CompliantDevice := "compliantDevice" in Cap.GrantControls.BuiltInControls + HybridJoin := "domainJoinedDevice" in Cap.GrantControls.BuiltInControls + Conditions := [CompliantDevice, HybridJoin] + # Filter: only include policies that meet all the requirements + "All" in Cap.Conditions.Users.IncludeUsers + "All" in Cap.Conditions.Applications.IncludeApplications + count([Condition | Condition = Conditions[_]; Condition == true]) > 0 + Cap.State == "enabled" +} + tests[{ - "PolicyId": PolicyId, - "Criticality" : "Should/Not-Implemented", - "Commandlet" : [], - "ActualValue" : [], - "ReportDetails" : NotCheckedDetails(PolicyId), - "RequirementMet" : false + "PolicyId" : "MS.AAD.3.7v1", + "Criticality" : "Should", + "Commandlet" : ["Get-MgIdentityConditionalAccessPolicy"], + "ActualValue" : ManagedDeviceAuth, + "ReportDetails" : concat(". ", [ReportFullDetailsArray(ManagedDeviceAuth, DescriptionString), CapLink]), + "RequirementMet" : Status }] { - PolicyId := "MS.AAD.5.2v1" - true + DescriptionString := "conditional access policy(s) found that meet(s) all requirements" + Status := count(ManagedDeviceAuth) > 0 } #-- # -# MS.AAD.5.3v1 +# MS.AAD.3.8v1 #-- +# At this time we are unable to test for X because NEW POLICY tests[{ "PolicyId": PolicyId, "Criticality" : "Should/Not-Implemented", @@ -390,15 +444,19 @@ tests[{ "ReportDetails" : NotCheckedDetails(PolicyId), "RequirementMet" : false }] { - PolicyId := "MS.AAD.5.3v1" + PolicyId := "MS.AAD.3.8v1" true } #-- +############ +# MS.AAD.4 # +############ + # -# MS.AAD.5.4v1 +# MS.AAD.4.1v1 #-- -# At this time we are unable to test for X because of Y +# At this time we are unable to test for log collection until we integrate Azure Powershell capabilities tests[{ "PolicyId" : PolicyId, "Criticality" : "Shall/Not-Implemented", @@ -407,12 +465,18 @@ tests[{ "ReportDetails" : NotCheckedDetails(PolicyId), "RequirementMet" : false }] { - PolicyId := "MS.AAD.5.4v1" + PolicyId := "MS.AAD.4.1v1" true } #-- +############ +# MS.AAD.5 # +############ +# +# MS.AAD.5.1v1 +#-- AuthPoliciesBad_2_6[Policy.Id] { Policy = input.authorization_policies[_] Policy.DefaultUserRolePermissions.AllowedToCreateApps == true @@ -425,11 +489,8 @@ AllAuthPoliciesAllowedCreate[{ Policy := input.authorization_policies[_] } -# -# MS.AAD.6.1v1 -#-- tests[{ - "PolicyId" : "MS.AAD.6.1v1", + "PolicyId" : "MS.AAD.5.1v1", "Criticality" : "Shall", "Commandlet" : ["Get-MgPolicyAuthorizationPolicy"], "ActualValue" : {"all_allowed_create_values": AllAuthPoliciesAllowedCreate}, @@ -443,7 +504,7 @@ tests[{ #-- # -# MS.AAD.7.1v1 +# MS.AAD.5.2v1 #-- BadDefaultGrantPolicies[Policy.Id] { Policy = input.authorization_policies[_] @@ -458,7 +519,7 @@ AllDefaultGrantPolicies[{ } tests[{ - "PolicyId" : "MS.AAD.7.1v1", + "PolicyId" : "MS.AAD.5.2v1", "Criticality" : "Shall", "Commandlet" : ["Get-MgPolicyAuthorizationPolicy"], "ActualValue" : {"all_grant_policy_values": AllDefaultGrantPolicies}, @@ -472,7 +533,7 @@ tests[{ #-- # -# MS.AAD.7.2v1 +# MS.AAD.5.3v1 #-- BadConsentPolicies[Policy.Id] { Policy := input.admin_consent_policies[_] @@ -488,7 +549,7 @@ AllConsentPolicies[{ tests[{ - "PolicyId" : "MS.AAD.7.2v1", + "PolicyId" : "MS.AAD.5.3v1", "Criticality" : "Shall", "Commandlet" : ["Get-MgPolicyAdminConsentRequestPolicy"], "ActualValue" : {"all_consent_policies": AllConsentPolicies}, @@ -501,7 +562,7 @@ tests[{ #-- # -# MS.AAD.7.3v1 +# MS.AAD.5.4v1 #-- AllConsentSettings[{ "SettingsGroup": SettingGroup.DisplayName, @@ -532,7 +593,7 @@ BadConsentSettings[{ } tests[{ - "PolicyId" : "MS.AAD.7.3v1", + "PolicyId" : "MS.AAD.5.4v1", "Criticality" : "Shall", "Commandlet" : ["Get-MgDirectorySetting"], "ActualValue" : AllConsentSettings, @@ -544,8 +605,12 @@ tests[{ } #-- +############ +# MS.AAD.6 # +############ + # -# MS.AAD.8.1v1 +# MS.AAD.6.1v1 #-- # At this time we are unable to test for X because of Y tests[{ @@ -556,88 +621,35 @@ tests[{ "ReportDetails" : NotCheckedDetails(PolicyId), "RequirementMet" : false }] { - PolicyId := "MS.AAD.8.1v1" + PolicyId := "MS.AAD.6.1v1" true } #-- -# -# MS.AAD.9.1v1 -#-- -default Policy2_9_1ConditionsMatch(_) := false -Policy2_9_1ConditionsMatch(Policy) := true if { - "All" in Policy.Conditions.Users.IncludeUsers - "All" in Policy.Conditions.Applications.IncludeApplications - Policy.SessionControls.SignInFrequency.IsEnabled == true - Policy.SessionControls.SignInFrequency.Type == "hours" - Policy.SessionControls.SignInFrequency.Value == 12 - Policy.State == "enabled" - count(Policy.Conditions.Users.ExcludeRoles) == 0 -} - -Policies2_9[Cap.DisplayName] { - Cap := input.conditional_access_policies[_] - - # Match all simple conditions - Policy2_9_1ConditionsMatch(Cap) - - # Only match policies with user and group exclusions if all exempted - UserExclusionsFullyExempt(Cap, "Policy2_9_1") == true - GroupExclusionsFullyExempt(Cap, "Policy2_9_1") == true -} - -tests[{ - "PolicyId" : "MS.AAD.9.1v1", - "Criticality" : "Shall", - "Commandlet" : ["Get-MgIdentityConditionalAccessPolicy"], - "ActualValue" : Policies2_9, - "ReportDetails" : concat(". ", [ReportFullDetailsArray(Policies2_9, DescriptionString), CapLink]), - "RequirementMet" : count(Policies2_9) > 0 -}] { - DescriptionString := "conditional access policy(s) found that meet(s) all requirements" - true -} -#-- - -# -# MS.AAD.10.1v1 -#-- -default Policy2_10_1ConditionsMatch(_) := false -Policy2_10_1ConditionsMatch(Policy) := true if { - "All" in Policy.Conditions.Users.IncludeUsers - "All" in Policy.Conditions.Applications.IncludeApplications - Policy.SessionControls.PersistentBrowser.IsEnabled == true - Policy.SessionControls.PersistentBrowser.Mode == "never" - Policy.State == "enabled" - count(Policy.Conditions.Users.ExcludeRoles) == 0 -} +############ +# MS.AAD.7 # +############ -Policies2_10[Cap.DisplayName] { - Cap := input.conditional_access_policies[_] - - # Match all simple conditions - Policy2_10_1ConditionsMatch(Cap) +################################# +# Helper functions for policies # +################################# - # Only match policies with user and group exclusions if all exempted - UserExclusionsFullyExempt(Cap, "Policy2_10_1") == true - GroupExclusionsFullyExempt(Cap, "Policy2_10_1") == true +# DoPIMRoleRulesExist will return true when the JSON privileged_roles.Rules element exists and false when it does not. +# This was created to add special logic for the scenario where the Azure AD premium P2 license is missing and therefore +# the JSON Rules element will not exist in that case because there is no PIM service. +# This is necessary to avoid false negatives when a policy checks for zero instances of a specific condition. +# For example, if a policy checks for count(RolesWithoutLimitedExpirationPeriod) == 0 and that normally means compliant, when a +# tenant does not have the license, a count of 0 does not mean compliant because 0 is the result of not having the Rules element +# in the JSON. +DoPIMRoleRulesExist { + _ = input.privileged_roles[_]["Rules"] } -tests[{ - "PolicyId" : "MS.AAD.10.1v1", - "Criticality" : "Shall", - "Commandlet" : ["Get-MgIdentityConditionalAccessPolicy"], - "ActualValue" : Policies2_10, - "ReportDetails" : concat(". ", [ReportFullDetailsArray(Policies2_10, DescriptionString), CapLink]), - "RequirementMet" : count(Policies2_10) > 0 -}] { - DescriptionString := "conditional access policy(s) found that meet(s) all requirements" - true -} -#-- +default check_if_role_rules_exist := false +check_if_role_rules_exist := DoPIMRoleRulesExist # -# MS.AAD.11.1v1 +# MS.AAD.7.1v1 #-- GlobalAdmins[User.DisplayName] { some id @@ -646,7 +658,7 @@ GlobalAdmins[User.DisplayName] { } tests[{ - "PolicyId" : "MS.AAD.11.1v1", + "PolicyId" : "MS.AAD.7.1v1", "Criticality" : "Shall", "Commandlet" : ["Get-MgSubscribedSku", "Get-PrivilegedUser"], "ActualValue" : GlobalAdmins, @@ -654,13 +666,31 @@ tests[{ "RequirementMet" : Status }] { DescriptionString := "global admin(s) found" - Conditions := [count(GlobalAdmins) < 5, count(GlobalAdmins) >= 2] + Conditions := [count(GlobalAdmins) <= 8, count(GlobalAdmins) >= 2] Status := count([Condition | Condition = Conditions[_]; Condition == false]) == 0 } #-- # -# MS.AAD.12.1v1 +# MS.AAD.7.2v1 +#-- +# At this time we are unable to test for user association to fine-grained privileged roles +# rather than Global Administrator due to runtime and data response size constraints +tests[{ + "PolicyId" : PolicyId, + "Criticality" : "Shall/Not-Implemented", + "Commandlet" : [], + "ActualValue" : [], + "ReportDetails" : NotCheckedDetails(PolicyId), + "RequirementMet" : false +}] { + PolicyId := "MS.AAD.7.2v1" + true +} +#-- + +# +# MS.AAD.7.3v1 #-- FederatedAdmins[User.DisplayName] { some id @@ -669,7 +699,7 @@ FederatedAdmins[User.DisplayName] { } tests[{ - "PolicyId" : "MS.AAD.12.1v1", + "PolicyId" : "MS.AAD.7.3v1", "Criticality" : "Shall", "Commandlet" : ["Get-MgSubscribedSku", "Get-PrivilegedUser"], "ActualValue" : AdminNames, @@ -683,66 +713,7 @@ tests[{ #-- # -# MS.AAD.13.1v1 -#-- -Policies2_13[Cap.DisplayName] { - Cap := input.conditional_access_policies[_] - PrivRolesSet := { Role.RoleTemplateId | Role = input.privileged_roles[_] } - CondIncludedRolesSet := { Y | Y = Cap.Conditions.Users.IncludeRoles[_] } - MissingRoles := PrivRolesSet - CondIncludedRolesSet - # Filter: only include policies that meet all the requirements - count(MissingRoles) == 0 - CondExcludedRolesSet := { Y | Y = Cap.Conditions.Users.ExcludeRoles[_] } - #make sure excluded roles do not contain any of the privileged roles (if it does, that means you are excluding it which is not what the policy says) - MatchingExcludeRoles := PrivRolesSet & CondExcludedRolesSet - #only succeeds if there is no intersection, i.e., excluded roles are none of the privileged roles - count(MatchingExcludeRoles) == 0 - "All" in Cap.Conditions.Applications.IncludeApplications - "mfa" in Cap.GrantControls.BuiltInControls - Cap.State == "enabled" -} - -tests[{ - "PolicyId" : "MS.AAD.13.1v1", - "Criticality" : "Shall", - "Commandlet" : ["Get-MgSubscribedSku", "Get-PrivilegedRole", "Get-MgIdentityConditionalAccessPolicy"], - "ActualValue" : Policies2_13, - "ReportDetails" : concat(". ", [ReportFullDetailsArray(Policies2_13, DescriptionString), CapLink]), - "RequirementMet" : count(Policies2_13) > 0 -}] { - DescriptionString := "conditional access policy(s) found that meet(s) all requirements" -} -#-- - - -################# -# Helper functions for policies -################# - -# DoPIMRoleRulesExist will return true when the JSON privileged_roles.Rules element exists and false when it does not. -# This was created to add special logic for the scenario where the Azure AD premium P2 license is missing and therefore -# the JSON Rules element will not exist in that case because there is no PIM service. -# This is necessary to avoid false negatives when a policy checks for zero instances of a specific condition. -# For example, if a policy checks for count(RolesWithoutLimitedExpirationPeriod) == 0 and that normally means compliant, when a -# tenant does not have the license, a count of 0 does not mean compliant because 0 is the result of not having the Rules element -# in the JSON. -DoPIMRoleRulesExist { - _ = input.privileged_roles[_]["Rules"] -} - -default check_if_role_rules_exist := false -check_if_role_rules_exist := DoPIMRoleRulesExist - -# DoPIMRoleAssignmentsExist will return true when the JSON privileged_roles.Assignments element exists and false when it does not. -DoPIMRoleAssignmentsExist { - _ = input.privileged_roles[_]["Assignments"] -} - -default check_if_role_assignments_exist := false -check_if_role_assignments_exist := DoPIMRoleAssignmentsExist - -# -# MS.AAD.14.1v1 +# MS.AAD.7.4v1 #-- RolesWithoutLimitedExpirationPeriod[Role.DisplayName] { Role := input.privileged_roles[_] @@ -765,7 +736,7 @@ RolesWithoutLimitedExpirationPeriod[Role.DisplayName] { } tests[{ - "PolicyId" : "MS.AAD.14.1v1", + "PolicyId" : "MS.AAD.7.4v1", "Criticality" : "Shall", "Commandlet" : ["Get-MgSubscribedSku", "Get-PrivilegedRole"], "ActualValue" : RolesWithoutLimitedExpirationPeriod, @@ -779,7 +750,7 @@ tests[{ #-- # -# MS.AAD.14.2v1 +# MS.AAD.7.5v1 #-- RolesAssignedOutsidePim[Role.DisplayName] { Role := input.privileged_roles[_] @@ -789,7 +760,7 @@ RolesAssignedOutsidePim[Role.DisplayName] { } tests[{ - "PolicyId" : "MS.AAD.14.2v1", + "PolicyId" : "MS.AAD.7.5v1", "Criticality" : "Shall", "Commandlet" : ["Get-MgSubscribedSku", "Get-PrivilegedRole"], "ActualValue" : RolesAssignedOutsidePim, @@ -802,9 +773,8 @@ tests[{ } #-- - # -# MS.AAD.15.1v1 +# MS.AAD.7.6v1 #-- RolesWithoutApprovalRequired[RoleName] { Role := input.privileged_roles[_] @@ -816,7 +786,7 @@ RolesWithoutApprovalRequired[RoleName] { } tests[{ - "PolicyId" : "MS.AAD.15.1v1", + "PolicyId" : "MS.AAD.7.6v1", "Criticality" : "Should", "Commandlet" : ["Get-MgSubscribedSku", "Get-PrivilegedRole"], "ActualValue" : RolesWithoutApprovalRequired, @@ -830,7 +800,7 @@ tests[{ #-- # -# MS.AAD.16.1v1 +# MS.AAD.7.7v1 #-- RolesWithoutActiveAssignmentAlerts[RoleName] { Role := input.privileged_roles[_] @@ -851,7 +821,7 @@ RolesWithoutEligibleAssignmentAlerts[RoleName] { } tests[{ - "PolicyId" : "MS.AAD.16.1v1", + "PolicyId" : "MS.AAD.7.7v1", "Criticality" : "Shall", "Commandlet" : ["Get-MgSubscribedSku", "Get-PrivilegedRole"], "ActualValue" : RolesWithoutAssignmentAlerts, @@ -866,7 +836,7 @@ tests[{ #-- # -# MS.AAD.16.2v1 +# MS.AAD.7.8v1 #-- AdminsWithoutActivationAlert[RoleName] { Role := input.privileged_roles[_] @@ -879,7 +849,7 @@ AdminsWithoutActivationAlert[RoleName] { } tests[{ - "PolicyId" : "MS.AAD.16.2v1", + "PolicyId" : "MS.AAD.7.8v1", "Criticality" : "Shall", "Commandlet" : ["Get-MgSubscribedSku", "Get-PrivilegedRole"], "ActualValue" : AdminsWithoutActivationAlert, @@ -893,10 +863,10 @@ tests[{ #-- # -# MS.AAD.16.3v1 +# MS.AAD.7.9v1 #-- tests[{ - "PolicyId" : "MS.AAD.16.3v1", + "PolicyId" : "MS.AAD.7.9v1", "Criticality" : "Should", "Commandlet" : ["Get-MgSubscribedSku", "Get-PrivilegedRole"], "ActualValue" : NonGlobalAdminsWithoutActivationAlert, @@ -910,36 +880,55 @@ tests[{ } #-- +############ +# MS.AAD.8 # +############ + # -# MS.AAD.17.1v1 +# MS.AAD.8.1v1 #-- -Policies2_17[Cap.DisplayName] { - Cap := input.conditional_access_policies[_] - CompliantDevice := "compliantDevice" in Cap.GrantControls.BuiltInControls - HybridJoin := "domainJoinedDevice" in Cap.GrantControls.BuiltInControls - Conditions := [CompliantDevice, HybridJoin] - # Filter: only include policies that meet all the requirements - "All" in Cap.Conditions.Users.IncludeUsers - "All" in Cap.Conditions.Applications.IncludeApplications - count([Condition | Condition = Conditions[_]; Condition == true]) > 0 - Cap.State == "enabled" +# must hardcode the ID. See +# https://docs.microsoft.com/en-us/azure/active-directory/enterprise-users/users-restrict-guest-permissions +LevelAsString(Id) := "Restricted access" if {Id == "2af84b1e-32c8-42b7-82bc-daa82404023b"} +LevelAsString(Id) := "Limited access" if {Id == "10dae51f-b6af-4016-8d66-8c2a99b929b3"} +LevelAsString(Id) := "Same as member users" if {Id == "a0b1b346-4d3e-4e8b-98f8-753987be4970"} +LevelAsString(Id) := "Unknown" if {not Id in ["2af84b1e-32c8-42b7-82bc-daa82404023b", "10dae51f-b6af-4016-8d66-8c2a99b929b3", "a0b1b346-4d3e-4e8b-98f8-753987be4970"]} + +AuthPoliciesBadRoleId[Policy.Id] { + Policy = input.authorization_policies[_] + not Policy.GuestUserRoleId in ["10dae51f-b6af-4016-8d66-8c2a99b929b3", "2af84b1e-32c8-42b7-82bc-daa82404023b"] +} + +AllAuthPoliciesRoleIds[{ + "GuestUserRoleIdString" : Level, + "GuestUserRoleId" : Policy.GuestUserRoleId, + "Id" : Policy.Id +}] { + Policy = input.authorization_policies[_] + Level := LevelAsString(Policy.GuestUserRoleId) +} + +RoleIdByPolicy[concat("", ["\"", Level, "\"", " (", Policy.Id, ")"])] { + Policy := input.authorization_policies[_] + Level := LevelAsString(Policy.GuestUserRoleId) } tests[{ - "PolicyId" : "MS.AAD.17.1v1", + "PolicyId" : "MS.AAD.8.1v1", "Criticality" : "Should", - "Commandlet" : ["Get-MgIdentityConditionalAccessPolicy"], - "ActualValue" : Policies2_17, - "ReportDetails" : concat(". ", [ReportFullDetailsArray(Policies2_17, DescriptionString), CapLink]), - "RequirementMet" : count(Policies2_17) > 0 + "Commandlet" : ["Get-MgPolicyAuthorizationPolicy"], + "ActualValue" : {"all_roleid_values" : AllAuthPoliciesRoleIds}, + "ReportDetails" : ReportDetail, + "RequirementMet" : Status }] { - DescriptionString := "conditional access policy(s) found that meet(s) all requirements" - true + BadPolicies := AuthPoliciesBadRoleId + Status := count(BadPolicies) == 0 + ReportDetail := concat("", ["Permission level set to ", concat(", ", RoleIdByPolicy)]) } #-- # -# MS.AAD.18.1v1 +# MS.AAD.8.2v1 #-- AuthPoliciesBadAllowInvites[Policy.Id] { Policy = input.authorization_policies[_] @@ -958,7 +947,7 @@ AllAuthPoliciesAllowInvites[{ } tests[{ - "PolicyId" : "MS.AAD.18.1v1", + "PolicyId" : "MS.AAD.8.2v1", "Criticality" : "Should", "Commandlet" : ["Get-MgPolicyAuthorizationPolicy"], "ActualValue" : {"all_allow_invite_values": AllAuthPoliciesAllowInvites}, @@ -972,7 +961,7 @@ tests[{ #-- # -# MS.AAD.18.2v1 +# MS.AAD.8.3v1 #-- # At this time we are unable to test for X because of Y tests[{ @@ -983,50 +972,7 @@ tests[{ "ReportDetails" : NotCheckedDetails(PolicyId), "RequirementMet" : false }] { - PolicyId := "MS.AAD.18.2v1" + PolicyId := "MS.AAD.8.3v1" true } -#-- - -# -# MS.AAD.18.3v1 -#-- -# must hardcode the ID. See -# https://docs.microsoft.com/en-us/azure/active-directory/enterprise-users/users-restrict-guest-permissions -LevelAsString(Id) := "Restricted access" if {Id == "2af84b1e-32c8-42b7-82bc-daa82404023b"} -LevelAsString(Id) := "Limited access" if {Id == "10dae51f-b6af-4016-8d66-8c2a99b929b3"} -LevelAsString(Id) := "Same as member users" if {Id == "a0b1b346-4d3e-4e8b-98f8-753987be4970"} -LevelAsString(Id) := "Unknown" if {not Id in ["2af84b1e-32c8-42b7-82bc-daa82404023b", "10dae51f-b6af-4016-8d66-8c2a99b929b3", "a0b1b346-4d3e-4e8b-98f8-753987be4970"]} - -AuthPoliciesBadRoleId[Policy.Id] { - Policy = input.authorization_policies[_] - not Policy.GuestUserRoleId in ["10dae51f-b6af-4016-8d66-8c2a99b929b3", "2af84b1e-32c8-42b7-82bc-daa82404023b"] -} - -AllAuthPoliciesRoleIds[{ - "GuestUserRoleIdString" : Level, - "GuestUserRoleId" : Policy.GuestUserRoleId, - "Id" : Policy.Id -}] { - Policy = input.authorization_policies[_] - Level := LevelAsString(Policy.GuestUserRoleId) -} - -RoleIdByPolicy[concat("", ["\"", Level, "\"", " (", Policy.Id, ")"])] { - Policy := input.authorization_policies[_] - Level := LevelAsString(Policy.GuestUserRoleId) -} - -tests[{ - "PolicyId" : "MS.AAD.18.3v1", - "Criticality" : "Should", - "Commandlet" : ["Get-MgPolicyAuthorizationPolicy"], - "ActualValue" : {"all_roleid_values" : AllAuthPoliciesRoleIds}, - "ReportDetails" : ReportDetail, - "RequirementMet" : Status -}] { - BadPolicies := AuthPoliciesBadRoleId - Status := count(BadPolicies) == 0 - ReportDetail := concat("", ["Permission level set to ", concat(", ", RoleIdByPolicy)]) -} #-- \ No newline at end of file diff --git a/Testing/Unit/Rego/AAD/AADConfig_01_test.rego b/Testing/Unit/Rego/AAD/AADConfig_01_test.rego index 89470124d1..fd7c221ea1 100644 --- a/Testing/Unit/Rego/AAD/AADConfig_01_test.rego +++ b/Testing/Unit/Rego/AAD/AADConfig_01_test.rego @@ -1,32 +1,33 @@ package aad import future.keywords + # -# Policy 1 -#--tests for no exclusions +# MS.AAD.1.1v1 +#-- test_NoExclusionsConditions_Correct if { PolicyId := "MS.AAD.1.1v1" Output := tests with input as { - "conditional_access_policies": [ + "conditional_access_policies" : [ { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": [], - "ExcludeGroups": [], - "ExcludeRoles": [] + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : [], + "ExcludeGroups" : [], + "ExcludeRoles" : [] }, - "ClientAppTypes": ["other", "exchangeActiveSync"] + "ClientAppTypes" : ["other", "exchangeActiveSync"] }, - "GrantControls": { - "BuiltInControls": ["block"] + "GrantControls" : { + "BuiltInControls" : ["block"] }, - "State": "enabled", - "DisplayName": "Test block Legacy Authentication" + "State" : "enabled", + "DisplayName" : "Test block Legacy Authentication" } ] } @@ -42,24 +43,24 @@ test_NoExclusionsIncludeApplications_Incorrect if { PolicyId := "MS.AAD.1.1v1" Output := tests with input as { - "conditional_access_policies": [ + "conditional_access_policies" : [ { - "Conditions": { - "Applications": { - "IncludeApplications": ["Office365"] + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["Office365"] }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": [], - "ExcludeGroups": [], + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : [], + "ExcludeGroups" : [], }, - "ClientAppTypes": ["other", "exchangeActiveSync"] + "ClientAppTypes" : ["other", "exchangeActiveSync"] }, - "GrantControls": { - "BuiltInControls": ["block"] + "GrantControls" : { + "BuiltInControls" : ["block"] }, - "State": "enabled", - "DisplayName": "Test block Legacy Authentication" + "State" : "enabled", + "DisplayName" : "Test block Legacy Authentication" } ] } @@ -75,24 +76,24 @@ test_NoExclusionsIncludeUsers_Incorrect if { PolicyId := "MS.AAD.1.1v1" Output := tests with input as { - "conditional_access_policies": [ + "conditional_access_policies" : [ { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] }, - "Users": { - "IncludeUsers": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"], - "ExcludeUsers": [], - "ExcludeGroups": [], + "Users" : { + "IncludeUsers" : ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"], + "ExcludeUsers" : [], + "ExcludeGroups" : [], }, - "ClientAppTypes": ["other", "exchangeActiveSync"] + "ClientAppTypes" : ["other", "exchangeActiveSync"] }, - "GrantControls": { - "BuiltInControls": ["block"] + "GrantControls" : { + "BuiltInControls" : ["block"] }, - "State": "enabled", - "DisplayName": "Test block Legacy Authentication" + "State" : "enabled", + "DisplayName" : "Test block Legacy Authentication" } ] } @@ -108,27 +109,26 @@ test_NoExclusionsExcludeUsers_Incorrect if { PolicyId := "MS.AAD.1.1v1" Output := tests with input as { - "conditional_access_policies": [ + "conditional_access_policies" : [ { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"], - "ExcludeGroups": [], + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"], + "ExcludeGroups" : [], }, - "ClientAppTypes": ["other", "exchangeActiveSync"] + "ClientAppTypes" : ["other", "exchangeActiveSync"] }, - "GrantControls": { - "BuiltInControls": ["block"] + "GrantControls" : { + "BuiltInControls" : ["block"] }, - "State": "enabled", - "DisplayName": "Test block Legacy Authentication" + "State" : "enabled", + "DisplayName" : "Test block Legacy Authentication" } - ], - + ] } RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] @@ -142,24 +142,24 @@ test_NoExclusionsExcludeGroups_Incorrect if { PolicyId := "MS.AAD.1.1v1" Output := tests with input as { - "conditional_access_policies": [ + "conditional_access_policies" : [ { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": [], - "ExcludeGroups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"], + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : [], + "ExcludeGroups" : ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"], }, - "ClientAppTypes": ["other", "exchangeActiveSync"] + "ClientAppTypes" : ["other", "exchangeActiveSync"] }, - "GrantControls": { - "BuiltInControls": ["block"] + "GrantControls" : { + "BuiltInControls" : ["block"] }, - "State": "enabled", - "DisplayName": "Test block Legacy Authentication" + "State" : "enabled", + "DisplayName" : "Test block Legacy Authentication" } ] } @@ -175,24 +175,24 @@ test_NoExclusionsClientAppTypes_Incorrect if { PolicyId := "MS.AAD.1.1v1" Output := tests with input as { - "conditional_access_policies": [ + "conditional_access_policies" : [ { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": [], - "ExcludeGroups": [], + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : [], + "ExcludeGroups" : [], }, - "ClientAppTypes": [""] + "ClientAppTypes" : [""] }, - "GrantControls": { - "BuiltInControls": ["block"] + "GrantControls" : { + "BuiltInControls" : ["block"] }, - "State": "enabled", - "DisplayName": "Test block Legacy Authentication" + "State" : "enabled", + "DisplayName" : "Test block Legacy Authentication" } ] } @@ -208,24 +208,24 @@ test_NoExclusionsBuiltInControls_Incorrect if { PolicyId := "MS.AAD.1.1v1" Output := tests with input as { - "conditional_access_policies": [ + "conditional_access_policies" : [ { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": [], - "ExcludeGroups": [], + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : [], + "ExcludeGroups" : [], }, - "ClientAppTypes": ["other", "exchangeActiveSync"] + "ClientAppTypes" : ["other", "exchangeActiveSync"] }, - "GrantControls": { - "BuiltInControls": null + "GrantControls" : { + "BuiltInControls" : null }, - "State": "enabled", - "DisplayName": "Test block Legacy Authentication" + "State" : "enabled", + "DisplayName" : "Test block Legacy Authentication" } ] } @@ -241,24 +241,24 @@ test_NoExclusionsState_Incorrect if { PolicyId := "MS.AAD.1.1v1" Output := tests with input as { - "conditional_access_policies": [ + "conditional_access_policies" : [ { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": [], - "ExcludeGroups": [], + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : [], + "ExcludeGroups" : [], }, - "ClientAppTypes": ["other", "exchangeActiveSync"] + "ClientAppTypes" : ["other", "exchangeActiveSync"] }, - "GrantControls": { - "BuiltInControls": ["block"] + "GrantControls" : { + "BuiltInControls" : ["block"] }, - "State": "disabled", - "DisplayName": "Test block Legacy Authentication" + "State" : "disabled", + "DisplayName" : "Test block Legacy Authentication" } ] } @@ -270,43 +270,41 @@ test_NoExclusionsState_Incorrect if { RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." } -#--tests for user exclusions and no group exclusions +# tests for user exclusions and no group exclusions # test_NoExclusionsExemptUsers_Correct if { PolicyId := "MS.AAD.1.1v1" Output := tests with input as { - "conditional_access_policies": [ + "conditional_access_policies" : [ { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": [], - "ExcludeGroups": [], - "ExcludeRoles": [] + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : [], + "ExcludeGroups" : [], + "ExcludeRoles" : [] }, - "ClientAppTypes": ["other", "exchangeActiveSync"] + "ClientAppTypes" : ["other", "exchangeActiveSync"] }, - "GrantControls": { - "BuiltInControls": ["block"] + "GrantControls" : { + "BuiltInControls" : ["block"] }, - "State": "enabled", - "DisplayName": "Test block Legacy Authentication" + "State" : "enabled", + "DisplayName" : "Test block Legacy Authentication" } ], - "scuba_config": { - "Aad": { - "Policy2_1_1": { - "CapExclusions": { - "Users": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], - "Groups": [] + "scuba_config" : { + "Aad" : { + "MS.AAD.1.1v1" : { + "CapExclusions" : { + "Users" : ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], + "Groups" : [] } } - } - } } @@ -321,36 +319,35 @@ test_UserExclusionsConditions_Correct if { PolicyId := "MS.AAD.1.1v1" Output := tests with input as { - "conditional_access_policies": [ + "conditional_access_policies" : [ { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], - "ExcludeGroups": [], - "ExcludeRoles": [] + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], + "ExcludeGroups" : [], + "ExcludeRoles" : [] }, - "ClientAppTypes": ["other", "exchangeActiveSync"] + "ClientAppTypes" : ["other", "exchangeActiveSync"] }, - "GrantControls": { - "BuiltInControls": ["block"] + "GrantControls" : { + "BuiltInControls" : ["block"] }, - "State": "enabled", - "DisplayName": "Test block Legacy Authentication" + "State" : "enabled", + "DisplayName" : "Test block Legacy Authentication" } ], - "scuba_config": { - "Aad": { - "Policy2_1_1": { - "CapExclusions": { - "Users": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], - "Groups": [] + "scuba_config" : { + "Aad" : { + "MS.AAD.1.1v1" : { + "CapExclusions" : { + "Users" : ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], + "Groups" : [] } } - } } } @@ -366,38 +363,36 @@ test_MultiUserExclusionsConditions_Correct if { PolicyId := "MS.AAD.1.1v1" Output := tests with input as { - "conditional_access_policies": [ + "conditional_access_policies" : [ { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3", "df269963-a081-4315-b7de-172755221504"], - "ExcludeGroups": [], - "ExcludeRoles": [] + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3", "df269963-a081-4315-b7de-172755221504"], + "ExcludeGroups" : [], + "ExcludeRoles" : [] }, - "ClientAppTypes": ["other", "exchangeActiveSync"] + "ClientAppTypes" : ["other", "exchangeActiveSync"] }, - "GrantControls": { - "BuiltInControls": ["block"] + "GrantControls" : { + "BuiltInControls" : ["block"] }, - "State": "enabled", - "DisplayName": "Test block Legacy Authentication" + "State" : "enabled", + "DisplayName" : "Test block Legacy Authentication" } ], - "scuba_config": { - "Aad": { - "Policy2_1_1": { - "CapExclusions": { - "Users": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3", "df269963-a081-4315-b7de-172755221504"], - "Groups": [] + "scuba_config" : { + "Aad" : { + "MS.AAD.1.1v1" : { + "CapExclusions" : { + "Users" : ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3", "df269963-a081-4315-b7de-172755221504"], + "Groups" : [] } } - } - } } @@ -412,27 +407,28 @@ test_UserExclusionNoExempt_Incorrect if { PolicyId := "MS.AAD.1.1v1" Output := tests with input as { - "conditional_access_policies": [ + "conditional_access_policies" : [ { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], - "ExcludeGroups": [], + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], + "ExcludeGroups" : [], }, - "ClientAppTypes": ["other", "exchangeActiveSync"] + "ClientAppTypes" : ["other", "exchangeActiveSync"] }, - "GrantControls": { - "BuiltInControls": ["block"] + "GrantControls" : { + "BuiltInControls" : ["block"] }, - "State": "enabled", - "DisplayName": "Test block Legacy Authentication" + "State" : "enabled", + "DisplayName" : "Test block Legacy Authentication" } ] } + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 @@ -444,39 +440,39 @@ test_UserExclusionsSingleExempt_Incorrect if { PolicyId := "MS.AAD.1.1v1" Output := tests with input as { - "conditional_access_policies": [ + "conditional_access_policies" : [ { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3", "df269963-a081-4315-b7de-172755221504"], - "ExcludeGroups": [], - "ExcludeRoles": [] + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3", "df269963-a081-4315-b7de-172755221504"], + "ExcludeGroups" : [], + "ExcludeRoles" : [] }, - "ClientAppTypes": ["other", "exchangeActiveSync"] + "ClientAppTypes" : ["other", "exchangeActiveSync"] }, - "GrantControls": { - "BuiltInControls": ["block"] + "GrantControls" : { + "BuiltInControls" : ["block"] }, - "State": "enabled", - "DisplayName": "Test block Legacy Authentication" + "State" : "enabled", + "DisplayName" : "Test block Legacy Authentication" } ], - "scuba_config": { - "Aad": { - "Policy2_1_1": { - "CapExclusions": { - "Users": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], - "Groups": [] + "scuba_config" : { + "Aad" : { + "MS.AAD.1.1v1" : { + "CapExclusions" : { + "Users" : ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], + "Groups" : [] } } - } } } + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 @@ -488,38 +484,38 @@ test_UserExclusionsNoExempt_Incorrect if { PolicyId := "MS.AAD.1.1v1" Output := tests with input as { - "conditional_access_policies": [ + "conditional_access_policies" : [ { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3", "df269963-a081-4315-b7de-172755221504"], - "ExcludeGroups": [], + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3", "df269963-a081-4315-b7de-172755221504"], + "ExcludeGroups" : [], }, - "ClientAppTypes": ["other", "exchangeActiveSync"] + "ClientAppTypes" : ["other", "exchangeActiveSync"] }, - "GrantControls": { - "BuiltInControls": ["block"] + "GrantControls" : { + "BuiltInControls" : ["block"] }, - "State": "enabled", - "DisplayName": "Test block Legacy Authentication" + "State" : "enabled", + "DisplayName" : "Test block Legacy Authentication" } ], - "scuba_config": { - "Aad": { - "Policy2_1_1": { - "CapExclusions": { - "Users": [], - "Groups": [] + "scuba_config" : { + "Aad" : { + "MS.AAD.1.1v1" : { + "CapExclusions" : { + "Users" : [], + "Groups" : [] } } - } } } + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 @@ -531,39 +527,38 @@ test_UserExclusionsIncludeApplications_Incorrect if { PolicyId := "MS.AAD.1.1v1" Output := tests with input as { - "conditional_access_policies": [ + "conditional_access_policies" : [ { - "Conditions": { - "Applications": { - "IncludeApplications": ["Office365"] + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["Office365"] }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], - "ExcludeGroups": [], + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], + "ExcludeGroups" : [], }, - "ClientAppTypes": ["other", "exchangeActiveSync"] + "ClientAppTypes" : ["other", "exchangeActiveSync"] }, - "GrantControls": { - "BuiltInControls": ["block"] + "GrantControls" : { + "BuiltInControls" : ["block"] }, - "State": "enabled", - "DisplayName": "Test block Legacy Authentication" + "State" : "enabled", + "DisplayName" : "Test block Legacy Authentication" } ], - "scuba_config": { - "Aad": { - "Policy2_1_1": { - "CapExclusions": { - "Users": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], - "Groups": [] + "scuba_config" : { + "Aad" : { + "MS.AAD.1.1v1" : { + "CapExclusions" : { + "Users" : ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], + "Groups" : [] } } - } - } } + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 @@ -575,39 +570,38 @@ test_UserExclusionsIncludeUsers_Incorrect if { PolicyId := "MS.AAD.1.1v1" Output := tests with input as { - "conditional_access_policies": [ + "conditional_access_policies" : [ { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] }, - "Users": { - "IncludeUsers": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], - "ExcludeUsers": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], - "ExcludeGroups": [], + "Users" : { + "IncludeUsers" : ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], + "ExcludeUsers" : ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], + "ExcludeGroups" : [], }, - "ClientAppTypes": ["other", "exchangeActiveSync"] + "ClientAppTypes" : ["other", "exchangeActiveSync"] }, - "GrantControls": { - "BuiltInControls": ["block"] + "GrantControls" : { + "BuiltInControls" : ["block"] }, - "State": "enabled", - "DisplayName": "Test block Legacy Authentication" + "State" : "enabled", + "DisplayName" : "Test block Legacy Authentication" } ], - "scuba_config": { - "Aad": { - "Policy2_1_1": { - "CapExclusions": { - "Users": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], - "Groups": [] + "scuba_config" : { + "Aad" : { + "MS.AAD.1.1v1" : { + "CapExclusions" : { + "Users" : ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], + "Groups" : [] } } - } - } } + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 @@ -619,32 +613,32 @@ test_UserExclusionsExcludeGroups_Incorrect if { PolicyId := "MS.AAD.1.1v1" Output := tests with input as { - "conditional_access_policies": [ + "conditional_access_policies" : [ { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], - "ExcludeGroups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"] + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], + "ExcludeGroups" : ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"] }, - "ClientAppTypes": ["other", "exchangeActiveSync"] + "ClientAppTypes" : ["other", "exchangeActiveSync"] }, - "GrantControls": { - "BuiltInControls": ["block"] + "GrantControls" : { + "BuiltInControls" : ["block"] }, - "State": "enabled", - "DisplayName": "Test block Legacy Authentication" + "State" : "enabled", + "DisplayName" : "Test block Legacy Authentication" } ], - "scuba_config": { - "Aad": { - "Policy2_1_1": { - "CapExclusions": { - "Users": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], - "Groups": [] + "scuba_config" : { + "Aad" : { + "MS.AAD.1.1v1" : { + "CapExclusions" : { + "Users" : ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], + "Groups" : [] } } } @@ -662,37 +656,35 @@ test_UserExclusionsClientAppTypes_Incorrect if { PolicyId := "MS.AAD.1.1v1" Output := tests with input as { - "conditional_access_policies": [ + "conditional_access_policies" : [ { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], - "ExcludeGroups": [], + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], + "ExcludeGroups" : [], }, - "ClientAppTypes": [""] + "ClientAppTypes" : [""] }, - "GrantControls": { - "BuiltInControls": ["block"] + "GrantControls" : { + "BuiltInControls" : ["block"] }, - "State": "enabled", - "DisplayName": "Test block Legacy Authentication" + "State" : "enabled", + "DisplayName" : "Test block Legacy Authentication" } ], - "scuba_config": { - "Aad": { - "Policy2_1_1": { - "CapExclusions": { - "Users": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], - "Groups": [] + "scuba_config" : { + "Aad" : { + "MS.AAD.1.1v1" : { + "CapExclusions" : { + "Users" : ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], + "Groups" : [] } } - } - } } @@ -707,37 +699,35 @@ test_UserExclusionsBuiltInControls_Incorrect if { PolicyId := "MS.AAD.1.1v1" Output := tests with input as { - "conditional_access_policies": [ + "conditional_access_policies" : [ { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], - "ExcludeGroups": [], + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], + "ExcludeGroups" : [], }, - "ClientAppTypes": ["other", "exchangeActiveSync"] + "ClientAppTypes" : ["other", "exchangeActiveSync"] }, - "GrantControls": { - "BuiltInControls": null + "GrantControls" : { + "BuiltInControls" : null }, - "State": "enabled", - "DisplayName": "Test block Legacy Authentication" + "State" : "enabled", + "DisplayName" : "Test block Legacy Authentication" } ], - "scuba_config": { - "Aad": { - "Policy2_1_1": { - "CapExclusions": { - "Users": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], - "Groups": [] + "scuba_config" : { + "Aad" : { + "MS.AAD.1.1v1" : { + "CapExclusions" : { + "Users" : ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], + "Groups" : [] } } - } - } } @@ -752,41 +742,38 @@ test_UserExclusionsState_Incorrect if { PolicyId := "MS.AAD.1.1v1" Output := tests with input as { - "conditional_access_policies": [ + "conditional_access_policies" : [ { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], - "ExcludeGroups": [], + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], + "ExcludeGroups" : [], }, - "ClientAppTypes": ["other", "exchangeActiveSync"] + "ClientAppTypes" : ["other", "exchangeActiveSync"] }, - "GrantControls": { - "BuiltInControls": ["block"] + "GrantControls" : { + "BuiltInControls" : ["block"] }, - "State": "disabled", - "DisplayName": "Test block Legacy Authentication" + "State" : "disabled", + "DisplayName" : "Test block Legacy Authentication" } ], - "scuba_config": { - "Aad": { - "Policy2_1_1": { - "CapExclusions": { - "Users": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], - "Groups": [] + "scuba_config" : { + "Aad" : { + "MS.AAD.1.1v1" : { + "CapExclusions" : { + "Users" : ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], + "Groups" : [] } } - } - } } - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 @@ -794,43 +781,41 @@ test_UserExclusionsState_Incorrect if { RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." } -#--tests for group exclusions and no user exclusions +# tests for group exclusions and no user exclusions # test_NoExclusionsExemptGroups_Correct if { PolicyId := "MS.AAD.1.1v1" Output := tests with input as { - "conditional_access_policies": [ + "conditional_access_policies" : [ { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": [], - "ExcludeGroups": [], - "ExcludeRoles": [] + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : [], + "ExcludeGroups" : [], + "ExcludeRoles" : [] }, - "ClientAppTypes": ["other", "exchangeActiveSync"] + "ClientAppTypes" : ["other", "exchangeActiveSync"] }, - "GrantControls": { - "BuiltInControls": ["block"] + "GrantControls" : { + "BuiltInControls" : ["block"] }, - "State": "enabled", - "DisplayName": "Test block Legacy Authentication" + "State" : "enabled", + "DisplayName" : "Test block Legacy Authentication" } ], - "scuba_config": { - "Aad": { - "Policy2_1_1": { - "CapExclusions": { - "Users": [], - "Groups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"] + "scuba_config" : { + "Aad" : { + "MS.AAD.1.1v1" : { + "CapExclusions" : { + "Users" : [], + "Groups" : ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"] } } - } - } } @@ -845,38 +830,36 @@ test_GroupExclusionNoExempt_Incorrect if { PolicyId := "MS.AAD.1.1v1" Output := tests with input as { - "conditional_access_policies": [ + "conditional_access_policies" : [ { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": [], - "ExcludeGroups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"], - "ExcludeRoles": [] + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : [], + "ExcludeGroups" : ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"], + "ExcludeRoles" : [] }, - "ClientAppTypes": ["other", "exchangeActiveSync"] + "ClientAppTypes" : ["other", "exchangeActiveSync"] }, - "GrantControls": { - "BuiltInControls": ["block"] + "GrantControls" : { + "BuiltInControls" : ["block"] }, - "State": "enabled", - "DisplayName": "Test block Legacy Authentication" + "State" : "enabled", + "DisplayName" : "Test block Legacy Authentication" } ], - "scuba_config": { - "Aad": { - "Policy2_1_1": { - "CapExclusions": { - "Users": [], - "Groups": [] + "scuba_config" : { + "Aad" : { + "MS.AAD.1.1v1" : { + "CapExclusions" : { + "Users" : [], + "Groups" : [] } } - } - } } @@ -891,37 +874,35 @@ test_GroupExclusionsNoExempt_Incorrect if { PolicyId := "MS.AAD.1.1v1" Output := tests with input as { - "conditional_access_policies": [ + "conditional_access_policies" : [ { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": [], - "ExcludeGroups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423", "65fea286-22d3-42f9-b4ca-93a6f75817d4"] + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : [], + "ExcludeGroups" : ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423", "65fea286-22d3-42f9-b4ca-93a6f75817d4"] }, - "ClientAppTypes": ["other", "exchangeActiveSync"] + "ClientAppTypes" : ["other", "exchangeActiveSync"] }, - "GrantControls": { - "BuiltInControls": ["block"] + "GrantControls" : { + "BuiltInControls" : ["block"] }, - "State": "enabled", - "DisplayName": "Test block Legacy Authentication" + "State" : "enabled", + "DisplayName" : "Test block Legacy Authentication" } ], - "scuba_config": { - "Aad": { - "Policy2_1_1": { - "CapExclusions": { - "Users": [], - "Groups": [] + "scuba_config" : { + "Aad" : { + "MS.AAD.1.1v1" : { + "CapExclusions" : { + "Users" : [], + "Groups" : [] } } - } - } } @@ -936,37 +917,35 @@ test_GroupExclusionsSingleExempt_Incorrect if { PolicyId := "MS.AAD.1.1v1" Output := tests with input as { - "conditional_access_policies": [ + "conditional_access_policies" : [ { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": [], - "ExcludeGroups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423", "65fea286-22d3-42f9-b4ca-93a6f75817d4"] + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : [], + "ExcludeGroups" : ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423", "65fea286-22d3-42f9-b4ca-93a6f75817d4"] }, - "ClientAppTypes": ["other", "exchangeActiveSync"] + "ClientAppTypes" : ["other", "exchangeActiveSync"] }, - "GrantControls": { - "BuiltInControls": ["block"] + "GrantControls" : { + "BuiltInControls" : ["block"] }, - "State": "enabled", - "DisplayName": "Test block Legacy Authentication" + "State" : "enabled", + "DisplayName" : "Test block Legacy Authentication" } ], - "scuba_config": { - "Aad": { - "Policy2_1_1": { - "CapExclusions": { - "Users": [], - "Groups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"] + "scuba_config" : { + "Aad" : { + "MS.AAD.1.1v1" : { + "CapExclusions" : { + "Users" : [], + "Groups" : ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"] } } - } - } } @@ -981,38 +960,36 @@ test_GroupExclusionConditions_Correct if { PolicyId := "MS.AAD.1.1v1" Output := tests with input as { - "conditional_access_policies": [ + "conditional_access_policies" : [ { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": [], - "ExcludeGroups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"], - "ExcludeRoles": [] + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : [], + "ExcludeGroups" : ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"], + "ExcludeRoles" : [] }, - "ClientAppTypes": ["other", "exchangeActiveSync"] + "ClientAppTypes" : ["other", "exchangeActiveSync"] }, - "GrantControls": { - "BuiltInControls": ["block"] + "GrantControls" : { + "BuiltInControls" : ["block"] }, - "State": "enabled", - "DisplayName": "Test block Legacy Authentication" + "State" : "enabled", + "DisplayName" : "Test block Legacy Authentication" } ], - "scuba_config": { - "Aad": { - "Policy2_1_1": { - "CapExclusions": { - "Users": [], - "Groups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"] + "scuba_config" : { + "Aad" : { + "MS.AAD.1.1v1" : { + "CapExclusions" : { + "Users" : [], + "Groups" : ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"] } } - } - } } @@ -1027,38 +1004,36 @@ test_MultiGroupExclusionsConditions_Correct if { PolicyId := "MS.AAD.1.1v1" Output := tests with input as { - "conditional_access_policies": [ + "conditional_access_policies" : [ { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": [], - "ExcludeGroups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423", "65fea286-22d3-42f9-b4ca-93a6f75817d4"], - "ExcludeRoles": [] + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : [], + "ExcludeGroups" : ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423", "65fea286-22d3-42f9-b4ca-93a6f75817d4"], + "ExcludeRoles" : [] }, - "ClientAppTypes": ["other", "exchangeActiveSync"] + "ClientAppTypes" : ["other", "exchangeActiveSync"] }, - "GrantControls": { - "BuiltInControls": ["block"] + "GrantControls" : { + "BuiltInControls" : ["block"] }, - "State": "enabled", - "DisplayName": "Test block Legacy Authentication" + "State" : "enabled", + "DisplayName" : "Test block Legacy Authentication" } ], - "scuba_config": { - "Aad": { - "Policy2_1_1": { - "CapExclusions": { - "Users": [], - "Groups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423", "65fea286-22d3-42f9-b4ca-93a6f75817d4"] + "scuba_config" : { + "Aad" : { + "MS.AAD.1.1v1" : { + "CapExclusions" : { + "Users" : [], + "Groups" : ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423", "65fea286-22d3-42f9-b4ca-93a6f75817d4"] } } - } - } } @@ -1069,43 +1044,41 @@ test_MultiGroupExclusionsConditions_Correct if { RuleOutput[0].ReportDetails == "1 conditional access policy(s) found that meet(s) all requirements:
Test block Legacy Authentication. View all CA policies." } -#--tests when both group and user exclusions present +# tests when both group and user exclusions present # test_UserGroupExclusionConditions_Correct if { PolicyId := "MS.AAD.1.1v1" Output := tests with input as { - "conditional_access_policies": [ + "conditional_access_policies" : [ { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], - "ExcludeGroups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"], - "ExcludeRoles": [] + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], + "ExcludeGroups" : ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"], + "ExcludeRoles" : [] }, - "ClientAppTypes": ["other", "exchangeActiveSync"] + "ClientAppTypes" : ["other", "exchangeActiveSync"] }, - "GrantControls": { - "BuiltInControls": ["block"] + "GrantControls" : { + "BuiltInControls" : ["block"] }, - "State": "enabled", - "DisplayName": "Test block Legacy Authentication" + "State" : "enabled", + "DisplayName" : "Test block Legacy Authentication" } ], - "scuba_config": { - "Aad": { - "Policy2_1_1": { - "CapExclusions": { - "Users": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], - "Groups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"] + "scuba_config" : { + "Aad" : { + "MS.AAD.1.1v1" : { + "CapExclusions" : { + "Users" : ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], + "Groups" : ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"] } } - } - } } @@ -1120,25 +1093,25 @@ test_UserGroupExclusionNoExempt_Incorrect if { PolicyId := "MS.AAD.1.1v1" Output := tests with input as { - "conditional_access_policies": [ + "conditional_access_policies" : [ { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], - "ExcludeGroups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"], - "ExcludeRoles": [] + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], + "ExcludeGroups" : ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"], + "ExcludeRoles" : [] }, - "ClientAppTypes": ["other", "exchangeActiveSync"] + "ClientAppTypes" : ["other", "exchangeActiveSync"] }, - "GrantControls": { - "BuiltInControls": ["block"] + "GrantControls" : { + "BuiltInControls" : ["block"] }, - "State": "enabled", - "DisplayName": "Test block Legacy Authentication" + "State" : "enabled", + "DisplayName" : "Test block Legacy Authentication" } ] } @@ -1154,38 +1127,36 @@ test_UserGroupExclusionUserExemptOnly_Incorrect if { PolicyId := "MS.AAD.1.1v1" Output := tests with input as { - "conditional_access_policies": [ + "conditional_access_policies" : [ { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], - "ExcludeGroups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"], - "ExcludeRoles": [] + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], + "ExcludeGroups" : ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"], + "ExcludeRoles" : [] }, - "ClientAppTypes": ["other", "exchangeActiveSync"] + "ClientAppTypes" : ["other", "exchangeActiveSync"] }, - "GrantControls": { - "BuiltInControls": ["block"] + "GrantControls" : { + "BuiltInControls" : ["block"] }, - "State": "enabled", - "DisplayName": "Test block Legacy Authentication" + "State" : "enabled", + "DisplayName" : "Test block Legacy Authentication" } ], - "scuba_config": { - "Aad": { - "Policy2_1_1": { - "CapExclusions": { - "Users": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], - "Groups": [] + "scuba_config" : { + "Aad" : { + "MS.AAD.1.1v1" : { + "CapExclusions" : { + "Users" : ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], + "Groups" : [] } } - } - } } @@ -1200,38 +1171,36 @@ test_UserGroupExclusionGroupExemptOnly_Incorrect if { PolicyId := "MS.AAD.1.1v1" Output := tests with input as { - "conditional_access_policies": [ + "conditional_access_policies" : [ { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], - "ExcludeGroups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"], - "ExcludeRoles": [] + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], + "ExcludeGroups" : ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"], + "ExcludeRoles" : [] }, - "ClientAppTypes": ["other", "exchangeActiveSync"] + "ClientAppTypes" : ["other", "exchangeActiveSync"] }, - "GrantControls": { - "BuiltInControls": ["block"] + "GrantControls" : { + "BuiltInControls" : ["block"] }, - "State": "enabled", - "DisplayName": "Test block Legacy Authentication" + "State" : "enabled", + "DisplayName" : "Test block Legacy Authentication" } ], - "scuba_config": { - "Aad": { - "Policy2_1_1": { - "CapExclusions": { - "Users": [], - "Groups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"] + "scuba_config" : { + "Aad" : { + "MS.AAD.1.1v1" : { + "CapExclusions" : { + "Users" : [], + "Groups" : ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"] } } - } - } } @@ -1246,38 +1215,36 @@ test_UserGroupExclusionTooFewUserExempts_Incorrect if { PolicyId := "MS.AAD.1.1v1" Output := tests with input as { - "conditional_access_policies": [ + "conditional_access_policies" : [ { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3", "df269963-a081-4315-b7de-172755221504"], - "ExcludeGroups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"], - "ExcludeRoles": [] + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3", "df269963-a081-4315-b7de-172755221504"], + "ExcludeGroups" : ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"], + "ExcludeRoles" : [] }, - "ClientAppTypes": ["other", "exchangeActiveSync"] + "ClientAppTypes" : ["other", "exchangeActiveSync"] }, - "GrantControls": { - "BuiltInControls": ["block"] + "GrantControls" : { + "BuiltInControls" : ["block"] }, - "State": "enabled", - "DisplayName": "Test block Legacy Authentication" + "State" : "enabled", + "DisplayName" : "Test block Legacy Authentication" } ], - "scuba_config": { - "Aad": { - "Policy2_1_1": { - "CapExclusions": { - "Users": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], - "Groups": [] + "scuba_config" : { + "Aad" : { + "MS.AAD.1.1v1" : { + "CapExclusions" : { + "Users" : ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], + "Groups" : [] } } - } - } } @@ -1286,4 +1253,5 @@ test_UserGroupExclusionTooFewUserExempts_Incorrect if { count(RuleOutput) == 1 not RuleOutput[0].RequirementMet RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." -} \ No newline at end of file +} +#-- \ No newline at end of file diff --git a/Testing/Unit/Rego/AAD/AADConfig_02_test.rego b/Testing/Unit/Rego/AAD/AADConfig_02_test.rego index aa826a04ff..3f14fee98c 100644 --- a/Testing/Unit/Rego/AAD/AADConfig_02_test.rego +++ b/Testing/Unit/Rego/AAD/AADConfig_02_test.rego @@ -4,45 +4,45 @@ import data.report.utils.NotCheckedDetails # -# Policy 1 +# MS.AAD.2.1v1 #-- - -test_NoExclusionsConditions_Correct if { +test_NoExclusionsConditions_Correct_V1 if { PolicyId := "MS.AAD.2.1v1" Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : [], + "ExcludeGroups" : [], + "ExcludeRoles" : [] + }, + "UserRiskLevels" : ["high"] }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": [], - "ExcludeGroups": [], - "ExcludeRoles": [] + "GrantControls" : { + "BuiltInControls" : ["block"] }, - "UserRiskLevels": ["high"] - }, - "GrantControls": { - "BuiltInControls": ["block"] - }, - "State": "enabled", - "DisplayName": "Test name" - } + "State" : "enabled", + "DisplayName" : "Test name" + } ], - "service_plans": [ - { - "ServicePlanName": "EXCHANGE_S_FOUNDATION", - "ServicePlanId": "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" - }, - { - "ServicePlanName": "AAD_PREMIUM_P2", - "ServicePlanId": "c7d91867-e1ce-4402-8d4f-22188b44b6c2" - } + "service_plans" : [ + { + "ServicePlanName" : "EXCHANGE_S_FOUNDATION", + "ServicePlanId" : "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" + }, + { + "ServicePlanName" : "AAD_PREMIUM_P2", + "ServicePlanId" : "c7d91867-e1ce-4402-8d4f-22188b44b6c2" + } ] } + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 @@ -50,54 +50,53 @@ test_NoExclusionsConditions_Correct if { RuleOutput[0].ReportDetails == "1 conditional access policy(s) found that meet(s) all requirements:
Test name. View all CA policies." } -test_NoExclusionsExemptUsers_Correct if { +test_NoExclusionsExemptUsers_Correct_V1 if { PolicyId := "MS.AAD.2.1v1" Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : [], + "ExcludeGroups" : [], + "ExcludeRoles" : [] + }, + "UserRiskLevels" : ["high"] }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": [], - "ExcludeGroups": [], - "ExcludeRoles": [] + "GrantControls" : { + "BuiltInControls" : ["block"] }, - "UserRiskLevels": ["high"] - }, - "GrantControls": { - "BuiltInControls": ["block"] - }, - "State": "enabled", - "DisplayName": "Test name" - } + "State" : "enabled", + "DisplayName" : "Test name" + } ], - "service_plans": [ - { - "ServicePlanName": "EXCHANGE_S_FOUNDATION", - "ServicePlanId": "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" - }, - { - "ServicePlanName": "AAD_PREMIUM_P2", - "ServicePlanId": "c7d91867-e1ce-4402-8d4f-22188b44b6c2" - } + "service_plans" : [ + { + "ServicePlanName" : "EXCHANGE_S_FOUNDATION", + "ServicePlanId" : "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" + }, + { + "ServicePlanName" : "AAD_PREMIUM_P2", + "ServicePlanId" : "c7d91867-e1ce-4402-8d4f-22188b44b6c2" + } ], - "scuba_config": { - "Aad": { - "Policy2_2_1": { - "CapExclusions": { - "Users": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], - "Groups": [] + "scuba_config" : { + "Aad" : { + "MS.AAD.2.1v1" : { + "CapExclusions" : { + "Users" : ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], + "Groups" : [] } } - } - } } + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 @@ -105,54 +104,53 @@ test_NoExclusionsExemptUsers_Correct if { RuleOutput[0].ReportDetails == "1 conditional access policy(s) found that meet(s) all requirements:
Test name. View all CA policies." } -test_NoExclusionsExemptGroups_Correct if { +test_NoExclusionsExemptGroups_Correct_V1 if { PolicyId := "MS.AAD.2.1v1" Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : [], + "ExcludeGroups" : [], + "ExcludeRoles" : [] + }, + "UserRiskLevels" : ["high"] }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": [], - "ExcludeGroups": [], - "ExcludeRoles": [] + "GrantControls" : { + "BuiltInControls" : ["block"] }, - "UserRiskLevels": ["high"] - }, - "GrantControls": { - "BuiltInControls": ["block"] - }, - "State": "enabled", - "DisplayName": "Test name" - } + "State" : "enabled", + "DisplayName" : "Test name" + } ], - "service_plans": [ - { - "ServicePlanName": "EXCHANGE_S_FOUNDATION", - "ServicePlanId": "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" - }, - { - "ServicePlanName": "AAD_PREMIUM_P2", - "ServicePlanId": "c7d91867-e1ce-4402-8d4f-22188b44b6c2" - } + "service_plans" : [ + { + "ServicePlanName" : "EXCHANGE_S_FOUNDATION", + "ServicePlanId" : "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" + }, + { + "ServicePlanName" : "AAD_PREMIUM_P2", + "ServicePlanId" : "c7d91867-e1ce-4402-8d4f-22188b44b6c2" + } ], - "scuba_config": { - "Aad": { - "Policy2_2_1": { - "CapExclusions": { - "Users": [], - "Groups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"] + "scuba_config" : { + "Aad" : { + "MS.AAD.2.1v1" : { + "CapExclusions" : { + "Users" : [], + "Groups" : ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"] } } - } - } } + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 @@ -161,42 +159,43 @@ test_NoExclusionsExemptGroups_Correct if { } # User exclusions test -test_UserExclusionNoExempt_Incorrect if { +test_UserExclusionNoExempt_Incorrect_V1 if { PolicyId := "MS.AAD.2.1v1" Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], + "ExcludeGroups" : [], + "ExcludeRoles" : [] + }, + "UserRiskLevels" : ["high"] }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], - "ExcludeGroups": [], - "ExcludeRoles": [] + "GrantControls" : { + "BuiltInControls" : ["block"] }, - "UserRiskLevels": ["high"] - }, - "GrantControls": { - "BuiltInControls": ["block"] - }, - "State": "enabled", - "DisplayName": "Test name" - } + "State" : "enabled", + "DisplayName" : "Test name" + } ], - "service_plans": [ - { - "ServicePlanName": "EXCHANGE_S_FOUNDATION", - "ServicePlanId": "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" - }, - { - "ServicePlanName": "AAD_PREMIUM_P2", - "ServicePlanId": "c7d91867-e1ce-4402-8d4f-22188b44b6c2" - } + "service_plans" : [ + { + "ServicePlanName" : "EXCHANGE_S_FOUNDATION", + "ServicePlanId" : "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" + }, + { + "ServicePlanName" : "AAD_PREMIUM_P2", + "ServicePlanId" : "c7d91867-e1ce-4402-8d4f-22188b44b6c2" + } ] } + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 @@ -204,54 +203,53 @@ test_UserExclusionNoExempt_Incorrect if { RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." } -test_UserExclusionConditions_Correct if { +test_UserExclusionConditions_Correct_V1 if { PolicyId := "MS.AAD.2.1v1" Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], + "ExcludeGroups" : [], + "ExcludeRoles" : [] + }, + "UserRiskLevels" : ["high"] }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], - "ExcludeGroups": [], - "ExcludeRoles": [] + "GrantControls" : { + "BuiltInControls" : ["block"] }, - "UserRiskLevels": ["high"] - }, - "GrantControls": { - "BuiltInControls": ["block"] - }, - "State": "enabled", - "DisplayName": "Test name" - } + "State" : "enabled", + "DisplayName" : "Test name" + } ], - "service_plans": [ - { - "ServicePlanName": "EXCHANGE_S_FOUNDATION", - "ServicePlanId": "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" - }, - { - "ServicePlanName": "AAD_PREMIUM_P2", - "ServicePlanId": "c7d91867-e1ce-4402-8d4f-22188b44b6c2" - } + "service_plans" : [ + { + "ServicePlanName" : "EXCHANGE_S_FOUNDATION", + "ServicePlanId" : "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" + }, + { + "ServicePlanName" : "AAD_PREMIUM_P2", + "ServicePlanId" : "c7d91867-e1ce-4402-8d4f-22188b44b6c2" + } ], - "scuba_config": { - "Aad": { - "Policy2_2_1": { - "CapExclusions": { - "Users": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], - "Groups": [] + "scuba_config" : { + "Aad" : { + "MS.AAD.2.1v1" : { + "CapExclusions" : { + "Users" : ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], + "Groups" : [] } } - } - } } + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 @@ -259,42 +257,43 @@ test_UserExclusionConditions_Correct if { RuleOutput[0].ReportDetails == "1 conditional access policy(s) found that meet(s) all requirements:
Test name. View all CA policies." } -test_UserExclusionsNoExempt_Incorrect if { +test_UserExclusionsNoExempt_Incorrect_V1 if { PolicyId := "MS.AAD.2.1v1" Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3", "65fea286-22d3-42f9-b4ca-93a6f75817d4"], + "ExcludeGroups" : [], + "ExcludeRoles" : [] + }, + "UserRiskLevels" : ["high"] }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3", "65fea286-22d3-42f9-b4ca-93a6f75817d4"], - "ExcludeGroups": [], - "ExcludeRoles": [] + "GrantControls" : { + "BuiltInControls" : ["block"] }, - "UserRiskLevels": ["high"] - }, - "GrantControls": { - "BuiltInControls": ["block"] - }, - "State": "enabled", - "DisplayName": "Test name" - } + "State" : "enabled", + "DisplayName" : "Test name" + } ], - "service_plans": [ - { - "ServicePlanName": "EXCHANGE_S_FOUNDATION", - "ServicePlanId": "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" - }, - { - "ServicePlanName": "AAD_PREMIUM_P2", - "ServicePlanId": "c7d91867-e1ce-4402-8d4f-22188b44b6c2" - } + "service_plans" : [ + { + "ServicePlanName" : "EXCHANGE_S_FOUNDATION", + "ServicePlanId" : "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" + }, + { + "ServicePlanName" : "AAD_PREMIUM_P2", + "ServicePlanId" : "c7d91867-e1ce-4402-8d4f-22188b44b6c2" + } ] } + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 @@ -302,54 +301,53 @@ test_UserExclusionsNoExempt_Incorrect if { RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." } -test_UserExclusionsSingleExempt_Incorrect if { +test_UserExclusionsSingleExempt_Incorrect_V1 if { PolicyId := "MS.AAD.2.1v1" Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3", "65fea286-22d3-42f9-b4ca-93a6f75817d4"], + "ExcludeGroups" : [], + "ExcludeRoles" : [] + }, + "UserRiskLevels" : ["high"] }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3", "65fea286-22d3-42f9-b4ca-93a6f75817d4"], - "ExcludeGroups": [], - "ExcludeRoles": [] + "GrantControls" : { + "BuiltInControls" : ["block"] }, - "UserRiskLevels": ["high"] - }, - "GrantControls": { - "BuiltInControls": ["block"] - }, - "State": "enabled", - "DisplayName": "Test name" - } + "State" : "enabled", + "DisplayName" : "Test name" + } ], - "service_plans": [ - { - "ServicePlanName": "EXCHANGE_S_FOUNDATION", - "ServicePlanId": "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" - }, - { - "ServicePlanName": "AAD_PREMIUM_P2", - "ServicePlanId": "c7d91867-e1ce-4402-8d4f-22188b44b6c2" - } + "service_plans" : [ + { + "ServicePlanName" : "EXCHANGE_S_FOUNDATION", + "ServicePlanId" : "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" + }, + { + "ServicePlanName" : "AAD_PREMIUM_P2", + "ServicePlanId" : "c7d91867-e1ce-4402-8d4f-22188b44b6c2" + } ], - "scuba_config": { - "Aad": { - "Policy2_2_1": { - "CapExclusions": { - "Users": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], - "Groups": [] + "scuba_config" : { + "Aad" : { + "MS.AAD.2.1v1" : { + "CapExclusions" : { + "Users" : ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], + "Groups" : [] } } - } - } } + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 @@ -357,54 +355,53 @@ test_UserExclusionsSingleExempt_Incorrect if { RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." } -test_MultiUserExclusionsConditions_Correct if { +test_MultiUserExclusionsConditions_Correct_V1 if { PolicyId := "MS.AAD.2.1v1" Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3", "65fea286-22d3-42f9-b4ca-93a6f75817d4"], + "ExcludeGroups" : [], + "ExcludeRoles" : [] + }, + "UserRiskLevels" : ["high"] }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3", "65fea286-22d3-42f9-b4ca-93a6f75817d4"], - "ExcludeGroups": [], - "ExcludeRoles": [] + "GrantControls" : { + "BuiltInControls" : ["block"] }, - "UserRiskLevels": ["high"] - }, - "GrantControls": { - "BuiltInControls": ["block"] - }, - "State": "enabled", - "DisplayName": "Test name" - } + "State" : "enabled", + "DisplayName" : "Test name" + } ], - "service_plans": [ - { - "ServicePlanName": "EXCHANGE_S_FOUNDATION", - "ServicePlanId": "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" - }, - { - "ServicePlanName": "AAD_PREMIUM_P2", - "ServicePlanId": "c7d91867-e1ce-4402-8d4f-22188b44b6c2" - } + "service_plans" : [ + { + "ServicePlanName" : "EXCHANGE_S_FOUNDATION", + "ServicePlanId" : "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" + }, + { + "ServicePlanName" : "AAD_PREMIUM_P2", + "ServicePlanId" : "c7d91867-e1ce-4402-8d4f-22188b44b6c2" + } ], - "scuba_config": { - "Aad": { - "Policy2_2_1": { - "CapExclusions": { - "Users": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3", "65fea286-22d3-42f9-b4ca-93a6f75817d4"], - "Groups": [] + "scuba_config" : { + "Aad" : { + "MS.AAD.2.1v1" : { + "CapExclusions" : { + "Users" : ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3", "65fea286-22d3-42f9-b4ca-93a6f75817d4"], + "Groups" : [] } } - } - } } + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 @@ -412,43 +409,44 @@ test_MultiUserExclusionsConditions_Correct if { RuleOutput[0].ReportDetails == "1 conditional access policy(s) found that meet(s) all requirements:
Test name. View all CA policies." } -# Group Exclusion tests -test_GroupExclusionNoExempt_Incorrect if { +# Group Exclusion tests # +test_GroupExclusionNoExempt_Incorrect_V1 if { PolicyId := "MS.AAD.2.1v1" Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : [], + "ExcludeGroups" : ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], + "ExcludeRoles" : [] + }, + "UserRiskLevels" : ["high"] }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": [], - "ExcludeGroups": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], - "ExcludeRoles": [] + "GrantControls" : { + "BuiltInControls" : ["block"] }, - "UserRiskLevels": ["high"] - }, - "GrantControls": { - "BuiltInControls": ["block"] - }, - "State": "enabled", - "DisplayName": "Test name" - } + "State" : "enabled", + "DisplayName" : "Test name" + } ], - "service_plans": [ - { - "ServicePlanName": "EXCHANGE_S_FOUNDATION", - "ServicePlanId": "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" - }, - { - "ServicePlanName": "AAD_PREMIUM_P2", - "ServicePlanId": "c7d91867-e1ce-4402-8d4f-22188b44b6c2" - } + "service_plans" : [ + { + "ServicePlanName" : "EXCHANGE_S_FOUNDATION", + "ServicePlanId" : "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" + }, + { + "ServicePlanName" : "AAD_PREMIUM_P2", + "ServicePlanId" : "c7d91867-e1ce-4402-8d4f-22188b44b6c2" + } ] } + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 @@ -456,53 +454,53 @@ test_GroupExclusionNoExempt_Incorrect if { RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." } -test_GroupExclusionsConditions_Correct if { +test_GroupExclusionsConditions_Correct_V1 if { PolicyId := "MS.AAD.2.1v1" Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : [], + "ExcludeGroups" : ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"], + "ExcludeRoles" : [] + }, + "UserRiskLevels" : ["high"] }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": [], - "ExcludeGroups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"], - "ExcludeRoles": [] + "GrantControls" : { + "BuiltInControls" : ["block"] }, - "UserRiskLevels": ["high"] - }, - "GrantControls": { - "BuiltInControls": ["block"] - }, - "State": "enabled", - "DisplayName": "Test name" - } + "State" : "enabled", + "DisplayName" : "Test name" + } ], - "service_plans": [ - { - "ServicePlanName": "EXCHANGE_S_FOUNDATION", - "ServicePlanId": "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" - }, - { - "ServicePlanName": "AAD_PREMIUM_P2", - "ServicePlanId": "c7d91867-e1ce-4402-8d4f-22188b44b6c2" - } + "service_plans" : [ + { + "ServicePlanName" : "EXCHANGE_S_FOUNDATION", + "ServicePlanId" : "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" + }, + { + "ServicePlanName" : "AAD_PREMIUM_P2", + "ServicePlanId" : "c7d91867-e1ce-4402-8d4f-22188b44b6c2" + } ], - "scuba_config": { - "Aad": { - "Policy2_2_1": { - "CapExclusions": { - "Users": [], - "Groups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"] + "scuba_config" : { + "Aad" : { + "MS.AAD.2.1v1" : { + "CapExclusions" : { + "Users" : [], + "Groups" : ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"] } } - } } } + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 @@ -510,42 +508,43 @@ test_GroupExclusionsConditions_Correct if { RuleOutput[0].ReportDetails == "1 conditional access policy(s) found that meet(s) all requirements:
Test name. View all CA policies." } -test_GroupExclusionsNoExempt_Incorrect if { +test_GroupExclusionsNoExempt_Incorrect_V1 if { PolicyId := "MS.AAD.2.1v1" Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : [], + "ExcludeGroups" : ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3", "65fea286-22d3-42f9-b4ca-93a6f75817d4"], + "ExcludeRoles" : [] + }, + "UserRiskLevels" : ["high"] }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": [], - "ExcludeGroups": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3", "65fea286-22d3-42f9-b4ca-93a6f75817d4"], - "ExcludeRoles": [] + "GrantControls" : { + "BuiltInControls" : ["block"] }, - "UserRiskLevels": ["high"] - }, - "GrantControls": { - "BuiltInControls": ["block"] - }, - "State": "enabled", - "DisplayName": "Test name" - } + "State" : "enabled", + "DisplayName" : "Test name" + } ], - "service_plans": [ - { - "ServicePlanName": "EXCHANGE_S_FOUNDATION", - "ServicePlanId": "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" - }, - { - "ServicePlanName": "AAD_PREMIUM_P2", - "ServicePlanId": "c7d91867-e1ce-4402-8d4f-22188b44b6c2" - } + "service_plans" : [ + { + "ServicePlanName" : "EXCHANGE_S_FOUNDATION", + "ServicePlanId" : "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" + }, + { + "ServicePlanName" : "AAD_PREMIUM_P2", + "ServicePlanId" : "c7d91867-e1ce-4402-8d4f-22188b44b6c2" + } ] } + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 @@ -553,53 +552,53 @@ test_GroupExclusionsNoExempt_Incorrect if { RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." } -test_GroupExclusionsSingleExempt_Incorrect if { +test_GroupExclusionsSingleExempt_Incorrect_V1 if { PolicyId := "MS.AAD.2.1v1" Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : [], + "ExcludeGroups" : ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3", "65fea286-22d3-42f9-b4ca-93a6f75817d4"], + "ExcludeRoles" : [] + }, + "UserRiskLevels" : ["high"] }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": [], - "ExcludeGroups": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3", "65fea286-22d3-42f9-b4ca-93a6f75817d4"], - "ExcludeRoles": [] + "GrantControls" : { + "BuiltInControls" : ["block"] }, - "UserRiskLevels": ["high"] - }, - "GrantControls": { - "BuiltInControls": ["block"] - }, - "State": "enabled", - "DisplayName": "Test name" - } + "State" : "enabled", + "DisplayName" : "Test name" + } ], - "service_plans": [ - { - "ServicePlanName": "EXCHANGE_S_FOUNDATION", - "ServicePlanId": "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" - }, - { - "ServicePlanName": "AAD_PREMIUM_P2", - "ServicePlanId": "c7d91867-e1ce-4402-8d4f-22188b44b6c2" - } + "service_plans" : [ + { + "ServicePlanName" : "EXCHANGE_S_FOUNDATION", + "ServicePlanId" : "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" + }, + { + "ServicePlanName" : "AAD_PREMIUM_P2", + "ServicePlanId" : "c7d91867-e1ce-4402-8d4f-22188b44b6c2" + } ], - "scuba_config": { - "Aad": { - "Policy2_2_1": { - "CapExclusions": { - "Users": [], - "Groups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"] + "scuba_config" : { + "Aad" : { + "MS.AAD.2.1v1" : { + "CapExclusions" : { + "Users" : [], + "Groups" : ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"] } } - } } } + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 @@ -607,53 +606,53 @@ test_GroupExclusionsSingleExempt_Incorrect if { RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." } -test_MultiGroupExclusionsConditions_Correct if { +test_MultiGroupExclusionsConditions_Correct_V1 if { PolicyId := "MS.AAD.2.1v1" Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : [], + "ExcludeGroups" : ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423", "65fea286-22d3-42f9-b4ca-93a6f75817d4"], + "ExcludeRoles" : [] + }, + "UserRiskLevels" : ["high"] }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": [], - "ExcludeGroups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423", "65fea286-22d3-42f9-b4ca-93a6f75817d4"], - "ExcludeRoles": [] + "GrantControls" : { + "BuiltInControls" : ["block"] }, - "UserRiskLevels": ["high"] - }, - "GrantControls": { - "BuiltInControls": ["block"] - }, - "State": "enabled", - "DisplayName": "Test name" - } + "State" : "enabled", + "DisplayName" : "Test name" + } ], - "service_plans": [ - { - "ServicePlanName": "EXCHANGE_S_FOUNDATION", - "ServicePlanId": "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" - }, - { - "ServicePlanName": "AAD_PREMIUM_P2", - "ServicePlanId": "c7d91867-e1ce-4402-8d4f-22188b44b6c2" - } + "service_plans" : [ + { + "ServicePlanName" : "EXCHANGE_S_FOUNDATION", + "ServicePlanId" : "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" + }, + { + "ServicePlanName" : "AAD_PREMIUM_P2", + "ServicePlanId" : "c7d91867-e1ce-4402-8d4f-22188b44b6c2" + } ], - "scuba_config": { - "Aad": { - "Policy2_2_1": { - "CapExclusions": { - "Users": [], - "Groups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423", "65fea286-22d3-42f9-b4ca-93a6f75817d4"] + "scuba_config" : { + "Aad" : { + "MS.AAD.2.1v1" : { + "CapExclusions" : { + "Users" : [], + "Groups" : ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423", "65fea286-22d3-42f9-b4ca-93a6f75817d4"] } } - } } } + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 @@ -662,52 +661,53 @@ test_MultiGroupExclusionsConditions_Correct if { } # User and group exclusions tests -test_UserGroupExclusionConditions_Correct if { +test_UserGroupExclusionConditions_Correct_V1 if { PolicyId := "MS.AAD.2.1v1" Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], + "ExcludeGroups" : ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"], + "ExcludeRoles" : [] + }, + "UserRiskLevels" : ["high"] }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], - "ExcludeGroups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"], - "ExcludeRoles": [] + "GrantControls" : { + "BuiltInControls" : ["block"] }, - "UserRiskLevels": ["high"] - }, - "GrantControls": { - "BuiltInControls": ["block"] - }, - "State": "enabled", - "DisplayName": "Test name" - } + "State" : "enabled", + "DisplayName" : "Test name" + } ], - "service_plans": [ - { - "ServicePlanName": "EXCHANGE_S_FOUNDATION", - "ServicePlanId": "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" - }, - { - "ServicePlanName": "AAD_PREMIUM_P2", - "ServicePlanId": "c7d91867-e1ce-4402-8d4f-22188b44b6c2" - } + "service_plans" : [ + { + "ServicePlanName" : "EXCHANGE_S_FOUNDATION", + "ServicePlanId" : "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" + }, + { + "ServicePlanName" : "AAD_PREMIUM_P2", + "ServicePlanId" : "c7d91867-e1ce-4402-8d4f-22188b44b6c2" + } ], - "scuba_config": { - "Aad": { - "Policy2_2_1": { - "CapExclusions": { - "Users": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], - "Groups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"] + "scuba_config" : { + "Aad" : { + "MS.AAD.2.1v1" : { + "CapExclusions" : { + "Users" : ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], + "Groups" : ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"] } } } } } + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 @@ -715,42 +715,43 @@ test_UserGroupExclusionConditions_Correct if { RuleOutput[0].ReportDetails == "1 conditional access policy(s) found that meet(s) all requirements:
Test name. View all CA policies." } -test_UserGroupExclusionNoExempt_Incorrect if { +test_UserGroupExclusionNoExempt_Incorrect_V1 if { PolicyId := "MS.AAD.2.1v1" Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], + "ExcludeGroups" : ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"], + "ExcludeRoles" : [] + }, + "UserRiskLevels" : ["high"] }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], - "ExcludeGroups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"], - "ExcludeRoles": [] + "GrantControls" : { + "BuiltInControls" : ["block"] }, - "UserRiskLevels": ["high"] - }, - "GrantControls": { - "BuiltInControls": ["block"] - }, - "State": "enabled", - "DisplayName": "Test name" - } + "State" : "enabled", + "DisplayName" : "Test name" + } ], - "service_plans": [ - { - "ServicePlanName": "EXCHANGE_S_FOUNDATION", - "ServicePlanId": "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" - }, - { - "ServicePlanName": "AAD_PREMIUM_P2", - "ServicePlanId": "c7d91867-e1ce-4402-8d4f-22188b44b6c2" - } + "service_plans" : [ + { + "ServicePlanName" : "EXCHANGE_S_FOUNDATION", + "ServicePlanId" : "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" + }, + { + "ServicePlanName" : "AAD_PREMIUM_P2", + "ServicePlanId" : "c7d91867-e1ce-4402-8d4f-22188b44b6c2" + } ] } + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 @@ -758,52 +759,53 @@ test_UserGroupExclusionNoExempt_Incorrect if { RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." } -test_UserGroupExclusionUserExemptOnly_Incorrect if { +test_UserGroupExclusionUserExemptOnly_Incorrect_V1 if { PolicyId := "MS.AAD.2.1v1" Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], + "ExcludeGroups" : ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"], + "ExcludeRoles" : [] + }, + "UserRiskLevels" : ["high"] }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], - "ExcludeGroups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"], - "ExcludeRoles": [] + "GrantControls" : { + "BuiltInControls" : ["block"] }, - "UserRiskLevels": ["high"] - }, - "GrantControls": { - "BuiltInControls": ["block"] - }, - "State": "enabled", - "DisplayName": "Test name" - } + "State" : "enabled", + "DisplayName" : "Test name" + } ], - "service_plans": [ - { - "ServicePlanName": "EXCHANGE_S_FOUNDATION", - "ServicePlanId": "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" - }, - { - "ServicePlanName": "AAD_PREMIUM_P2", - "ServicePlanId": "c7d91867-e1ce-4402-8d4f-22188b44b6c2" - } + "service_plans" : [ + { + "ServicePlanName" : "EXCHANGE_S_FOUNDATION", + "ServicePlanId" : "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" + }, + { + "ServicePlanName" : "AAD_PREMIUM_P2", + "ServicePlanId" : "c7d91867-e1ce-4402-8d4f-22188b44b6c2" + } ], - "scuba_config": { - "Aad": { - "Policy2_2_1": { - "CapExclusions": { - "Users": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], - "Groups": [] + "scuba_config" : { + "Aad" : { + "MS.AAD.2.1v1" : { + "CapExclusions" : { + "Users" : ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], + "Groups" : [] } } } } } + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 @@ -811,52 +813,53 @@ test_UserGroupExclusionUserExemptOnly_Incorrect if { RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." } -test_UserGroupExclusionGroupExemptOnly_Incorrect if { +test_UserGroupExclusionGroupExemptOnly_Incorrect_V1 if { PolicyId := "MS.AAD.2.1v1" Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], + "ExcludeGroups" : ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"], + "ExcludeRoles" : [] + }, + "UserRiskLevels" : ["high"] }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], - "ExcludeGroups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"], - "ExcludeRoles": [] + "GrantControls" : { + "BuiltInControls" : ["block"] }, - "UserRiskLevels": ["high"] - }, - "GrantControls": { - "BuiltInControls": ["block"] - }, - "State": "enabled", - "DisplayName": "Test name" - } + "State" : "enabled", + "DisplayName" : "Test name" + } ], - "service_plans": [ - { - "ServicePlanName": "EXCHANGE_S_FOUNDATION", - "ServicePlanId": "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" - }, - { - "ServicePlanName": "AAD_PREMIUM_P2", - "ServicePlanId": "c7d91867-e1ce-4402-8d4f-22188b44b6c2" - } + "service_plans" : [ + { + "ServicePlanName" : "EXCHANGE_S_FOUNDATION", + "ServicePlanId" : "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" + }, + { + "ServicePlanName" : "AAD_PREMIUM_P2", + "ServicePlanId" : "c7d91867-e1ce-4402-8d4f-22188b44b6c2" + } ], - "scuba_config": { - "Aad": { - "Policy2_2_1": { - "CapExclusions": { - "Users": [], - "Groups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"] + "scuba_config" : { + "Aad" : { + "MS.AAD.2.1v1" : { + "CapExclusions" : { + "Users" : [], + "Groups" : ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"] } } } } } + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 @@ -864,52 +867,53 @@ test_UserGroupExclusionGroupExemptOnly_Incorrect if { RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." } -test_UserGroupExclusionTooFewUserExempts_Incorrect if { +test_UserGroupExclusionTooFewUserExempts_Incorrect_V1 if { PolicyId := "MS.AAD.2.1v1" Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423", "65fea286-22d3-42f9-b4ca-93a6f75817d4"], + "ExcludeGroups" : ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"], + "ExcludeRoles" : [] + }, + "UserRiskLevels" : ["high"] }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423", "65fea286-22d3-42f9-b4ca-93a6f75817d4"], - "ExcludeGroups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"], - "ExcludeRoles": [] + "GrantControls" : { + "BuiltInControls" : ["block"] }, - "UserRiskLevels": ["high"] - }, - "GrantControls": { - "BuiltInControls": ["block"] - }, - "State": "enabled", - "DisplayName": "Test name" - } + "State" : "enabled", + "DisplayName" : "Test name" + } ], - "service_plans": [ - { - "ServicePlanName": "EXCHANGE_S_FOUNDATION", - "ServicePlanId": "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" - }, - { - "ServicePlanName": "AAD_PREMIUM_P2", - "ServicePlanId": "c7d91867-e1ce-4402-8d4f-22188b44b6c2" - } + "service_plans" : [ + { + "ServicePlanName" : "EXCHANGE_S_FOUNDATION", + "ServicePlanId" : "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" + }, + { + "ServicePlanName" : "AAD_PREMIUM_P2", + "ServicePlanId" : "c7d91867-e1ce-4402-8d4f-22188b44b6c2" + } ], - "scuba_config": { - "Aad": { - "Policy2_2_1": { - "CapExclusions": { - "Users": ["65fea286-22d3-42f9-b4ca-93a6f75817d4"], - "Groups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"] + "scuba_config" : { + "Aad" : { + "MS.AAD.2.1v1" : { + "CapExclusions" : { + "Users" : ["65fea286-22d3-42f9-b4ca-93a6f75817d4"], + "Groups" : ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"] } } } } } + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 @@ -918,40 +922,40 @@ test_UserGroupExclusionTooFewUserExempts_Incorrect if { } # Other Conditions tests -test_IncludeApplications_Incorrect if { +test_IncludeApplications_Incorrect_V1 if { PolicyId := "MS.AAD.2.1v1" Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["Office365"] + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["Office365"] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : [], + "ExcludeGroups" : [], + "ExcludeRoles" : [] + }, + "UserRiskLevels" : ["high"] }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": [], - "ExcludeGroups": [], - "ExcludeRoles": [] + "GrantControls" : { + "BuiltInControls" : ["block"] }, - "UserRiskLevels": ["high"] - }, - "GrantControls": { - "BuiltInControls": ["block"] - }, - "State": "enabled", - "DisplayName": "Test name" - } + "State" : "enabled", + "DisplayName" : "Test name" + } ], - "service_plans": [ - { - "ServicePlanName": "EXCHANGE_S_FOUNDATION", - "ServicePlanId": "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" - }, - { - "ServicePlanName": "AAD_PREMIUM_P2", - "ServicePlanId": "c7d91867-e1ce-4402-8d4f-22188b44b6c2" - } + "service_plans" : [ + { + "ServicePlanName" : "EXCHANGE_S_FOUNDATION", + "ServicePlanId" : "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" + }, + { + "ServicePlanName" : "AAD_PREMIUM_P2", + "ServicePlanId" : "c7d91867-e1ce-4402-8d4f-22188b44b6c2" + } ] } @@ -962,40 +966,40 @@ test_IncludeApplications_Incorrect if { RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." } -test_IncludeUsers_Incorrect if { +test_IncludeUsers_Incorrect_V1 if { PolicyId := "MS.AAD.2.1v1" Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeUsers" : ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"], + "ExcludeUsers" : [], + "ExcludeGroups" : [], + "ExcludeRoles" : [] + }, + "UserRiskLevels" : ["high"] }, - "Users": { - "IncludeUsers": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"], - "ExcludeUsers": [], - "ExcludeGroups": [], - "ExcludeRoles": [] + "GrantControls" : { + "BuiltInControls" : ["block"] }, - "UserRiskLevels": ["high"] - }, - "GrantControls": { - "BuiltInControls": ["block"] - }, - "State": "enabled", - "DisplayName": "Test name" - } + "State" : "enabled", + "DisplayName" : "Test name" + } ], - "service_plans": [ - { - "ServicePlanName": "EXCHANGE_S_FOUNDATION", - "ServicePlanId": "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" - }, - { - "ServicePlanName": "AAD_PREMIUM_P2", - "ServicePlanId": "c7d91867-e1ce-4402-8d4f-22188b44b6c2" - } + "service_plans" : [ + { + "ServicePlanName" : "EXCHANGE_S_FOUNDATION", + "ServicePlanId" : "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" + }, + { + "ServicePlanName" : "AAD_PREMIUM_P2", + "ServicePlanId" : "c7d91867-e1ce-4402-8d4f-22188b44b6c2" + } ] } @@ -1006,40 +1010,40 @@ test_IncludeUsers_Incorrect if { RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." } -test_ExcludeUsers_Incorrect if { +test_ExcludeUsers_Incorrect_V1 if { PolicyId := "MS.AAD.2.1v1" Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : ["8bc7c6ee-39a2-42a5-a31b-f77fb51db652"], + "ExcludeGroups" : [], + "ExcludeRoles" : [] + }, + "UserRiskLevels" : ["high"] }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": ["8bc7c6ee-39a2-42a5-a31b-f77fb51db652"], - "ExcludeGroups": [], - "ExcludeRoles": [] + "GrantControls" : { + "BuiltInControls" : ["block"] }, - "UserRiskLevels": ["high"] - }, - "GrantControls": { - "BuiltInControls": ["block"] - }, - "State": "enabled", - "DisplayName": "Test name" - } + "State" : "enabled", + "DisplayName" : "Test name" + } ], - "service_plans": [ - { - "ServicePlanName": "EXCHANGE_S_FOUNDATION", - "ServicePlanId": "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" - }, - { - "ServicePlanName": "AAD_PREMIUM_P2", - "ServicePlanId": "c7d91867-e1ce-4402-8d4f-22188b44b6c2" - } + "service_plans" : [ + { + "ServicePlanName" : "EXCHANGE_S_FOUNDATION", + "ServicePlanId" : "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" + }, + { + "ServicePlanName" : "AAD_PREMIUM_P2", + "ServicePlanId" : "c7d91867-e1ce-4402-8d4f-22188b44b6c2" + } ] } @@ -1050,40 +1054,40 @@ test_ExcludeUsers_Incorrect if { RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." } -test_ExcludeGroups_Incorrect if { +test_ExcludeGroups_Incorrect_V1 if { PolicyId := "MS.AAD.2.1v1" Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : [], + "ExcludeGroups" : ["8bc7c6ee-39a2-42a5-a31b-f77fb51db652"], + "ExcludeRoles" : [] + }, + "UserRiskLevels" : ["high"] }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": [], - "ExcludeGroups": ["8bc7c6ee-39a2-42a5-a31b-f77fb51db652"], - "ExcludeRoles": [] + "GrantControls" : { + "BuiltInControls" : ["block"] }, - "UserRiskLevels": ["high"] - }, - "GrantControls": { - "BuiltInControls": ["block"] - }, - "State": "enabled", - "DisplayName": "Test name" - } + "State" : "enabled", + "DisplayName" : "Test name" + } ], - "service_plans": [ - { - "ServicePlanName": "EXCHANGE_S_FOUNDATION", - "ServicePlanId": "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" - }, - { - "ServicePlanName": "AAD_PREMIUM_P2", - "ServicePlanId": "c7d91867-e1ce-4402-8d4f-22188b44b6c2" - } + "service_plans" : [ + { + "ServicePlanName" : "EXCHANGE_S_FOUNDATION", + "ServicePlanId" : "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" + }, + { + "ServicePlanName" : "AAD_PREMIUM_P2", + "ServicePlanId" : "c7d91867-e1ce-4402-8d4f-22188b44b6c2" + } ] } @@ -1094,40 +1098,40 @@ test_ExcludeGroups_Incorrect if { RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." } -test_ExcludeRoles_Incorrect if { +test_ExcludeRoles_Incorrect_V1 if { PolicyId := "MS.AAD.2.1v1" Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : [], + "ExcludeGroups" : [], + "ExcludeRoles" : ["8bc7c6ee-39a2-42a5-a31b-f77fb51db652"] + }, + "UserRiskLevels" : ["high"] }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": [], - "ExcludeGroups": [], - "ExcludeRoles": ["8bc7c6ee-39a2-42a5-a31b-f77fb51db652"] + "GrantControls" : { + "BuiltInControls" : ["block"] }, - "UserRiskLevels": ["high"] - }, - "GrantControls": { - "BuiltInControls": ["block"] - }, - "State": "enabled", - "DisplayName": "Test name" - } + "State" : "enabled", + "DisplayName" : "Test name" + } ], - "service_plans": [ - { - "ServicePlanName": "EXCHANGE_S_FOUNDATION", - "ServicePlanId": "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" - }, - { - "ServicePlanName": "AAD_PREMIUM_P2", - "ServicePlanId": "c7d91867-e1ce-4402-8d4f-22188b44b6c2" - } + "service_plans" : [ + { + "ServicePlanName" : "EXCHANGE_S_FOUNDATION", + "ServicePlanId" : "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" + }, + { + "ServicePlanName" : "AAD_PREMIUM_P2", + "ServicePlanId" : "c7d91867-e1ce-4402-8d4f-22188b44b6c2" + } ] } @@ -1138,40 +1142,40 @@ test_ExcludeRoles_Incorrect if { RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." } -test_BuiltInControls_Incorrect if { +test_BuiltInControls_Incorrect_V1 if { PolicyId := "MS.AAD.2.1v1" Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : [], + "ExcludeGroups" : [], + "ExcludeRoles" : [] + }, + "UserRiskLevels" : ["high"] }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": [], - "ExcludeGroups": [], - "ExcludeRoles": [] + "GrantControls" : { + "BuiltInControls" : [""] }, - "UserRiskLevels": ["high"] - }, - "GrantControls": { - "BuiltInControls": [""] - }, - "State": "enabled", - "DisplayName": "Test name" - } + "State" : "enabled", + "DisplayName" : "Test name" + } ], - "service_plans": [ - { - "ServicePlanName": "EXCHANGE_S_FOUNDATION", - "ServicePlanId": "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" - }, - { - "ServicePlanName": "AAD_PREMIUM_P2", - "ServicePlanId": "c7d91867-e1ce-4402-8d4f-22188b44b6c2" - } + "service_plans" : [ + { + "ServicePlanName" : "EXCHANGE_S_FOUNDATION", + "ServicePlanId" : "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" + }, + { + "ServicePlanName" : "AAD_PREMIUM_P2", + "ServicePlanId" : "c7d91867-e1ce-4402-8d4f-22188b44b6c2" + } ] } @@ -1182,40 +1186,40 @@ test_BuiltInControls_Incorrect if { RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." } -test_State_Incorrect if { +test_State_Incorrect_V1 if { PolicyId := "MS.AAD.2.1v1" Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : [], + "ExcludeGroups" : [], + "ExcludeRoles" : [] + }, + "UserRiskLevels" : ["high"] }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": [], - "ExcludeGroups": [], - "ExcludeRoles": [] + "GrantControls" : { + "BuiltInControls" : ["block"] }, - "UserRiskLevels": ["high"] - }, - "GrantControls": { - "BuiltInControls": ["block"] - }, - "State": "disabled", - "DisplayName": "Test name" - } + "State" : "disabled", + "DisplayName" : "Test name" + } ], - "service_plans": [ - { - "ServicePlanName": "EXCHANGE_S_FOUNDATION", - "ServicePlanId": "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" - }, - { - "ServicePlanName": "AAD_PREMIUM_P2", - "ServicePlanId": "c7d91867-e1ce-4402-8d4f-22188b44b6c2" - } + "service_plans" : [ + { + "ServicePlanName" : "EXCHANGE_S_FOUNDATION", + "ServicePlanId" : "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" + }, + { + "ServicePlanName" : "AAD_PREMIUM_P2", + "ServicePlanId" : "c7d91867-e1ce-4402-8d4f-22188b44b6c2" + } ] } @@ -1230,36 +1234,36 @@ test_UserRiskLevels_Incorrect if { PolicyId := "MS.AAD.2.1v1" Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : [], + "ExcludeGroups" : [], + "ExcludeRoles" : [] + }, + "UserRiskLevels" : [""] }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": [], - "ExcludeGroups": [], - "ExcludeRoles": [] + "GrantControls" : { + "BuiltInControls" : ["block"] }, - "UserRiskLevels": [""] - }, - "GrantControls": { - "BuiltInControls": ["block"] - }, - "State": "enabled", - "DisplayName": "Test name" - } + "State" : "enabled", + "DisplayName" : "Test name" + } ], - "service_plans": [ - { - "ServicePlanName": "EXCHANGE_S_FOUNDATION", - "ServicePlanId": "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" - }, - { - "ServicePlanName": "AAD_PREMIUM_P2", - "ServicePlanId": "c7d91867-e1ce-4402-8d4f-22188b44b6c2" - } + "service_plans" : [ + { + "ServicePlanName" : "EXCHANGE_S_FOUNDATION", + "ServicePlanId" : "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" + }, + { + "ServicePlanName" : "AAD_PREMIUM_P2", + "ServicePlanId" : "c7d91867-e1ce-4402-8d4f-22188b44b6c2" + } ] } @@ -1274,32 +1278,32 @@ test_ServicePlans_Incorrect if { PolicyId := "MS.AAD.2.1v1" Output := tests with input as { - "conditional_access_policies": [ + "conditional_access_policies" : [ { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": [], - "ExcludeGroups": [], - "ExcludeRoles": [] + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : [], + "ExcludeGroups" : [], + "ExcludeRoles" : [] }, - "UserRiskLevels": [""] + "UserRiskLevels" : [""] }, - "GrantControls": { - "BuiltInControls": ["block"] + "GrantControls" : { + "BuiltInControls" : ["block"] }, - "State": "enabled", - "DisplayName": "Test name" + "State" : "enabled", + "DisplayName" : "Test name" } ], - "service_plans": [ - { - "ServicePlanName": "EXCHANGE_S_FOUNDATION", - "ServicePlanId": "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" - } + "service_plans" : [ + { + "ServicePlanName" : "EXCHANGE_S_FOUNDATION", + "ServicePlanId" : "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" + } ] } @@ -1309,9 +1313,10 @@ test_ServicePlans_Incorrect if { not RuleOutput[0].RequirementMet RuleOutput[0].ReportDetails == "**NOTE: Your tenant does not have an Azure AD Premium P2 license, which is required for this feature**" } +#-- # -# Policy 2 +# MS.AAD.2.2v1 #-- test_NotImplemented_Correct if { PolicyId := "MS.AAD.2.2v1" @@ -1323,4 +1328,1321 @@ test_NotImplemented_Correct if { count(RuleOutput) == 1 not RuleOutput[0].RequirementMet RuleOutput[0].ReportDetails == NotCheckedDetails(PolicyId) -} \ No newline at end of file +} +#-- + +# +# MS.AAD.2.3v1 +#-- +test_NoExclusionsConditions_Correct_V2 if { + PolicyId := "MS.AAD.2.3v1" + + Output := tests with input as { + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : [], + "ExcludeGroups" : [], + "ExcludeRoles" : [] + }, + "SignInRiskLevels" : ["high"] + }, + "GrantControls" : { + "BuiltInControls" : ["block"] + }, + "State" : "enabled", + "DisplayName" : "Test name" + } + ], + "service_plans" : [ + { + "ServicePlanName" : "EXCHANGE_S_FOUNDATION", + "ServicePlanId" : "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" + }, + { + "ServicePlanName" : "AAD_PREMIUM_P2", + "ServicePlanId" : "c7d91867-e1ce-4402-8d4f-22188b44b6c2" + } + ] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "1 conditional access policy(s) found that meet(s) all requirements:
Test name. View all CA policies." +} + +test_NoExclusionsExemptUsers_Correct_V2 if { + PolicyId := "MS.AAD.2.3v1" + + Output := tests with input as { + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : [], + "ExcludeGroups" : [], + "ExcludeRoles" : [] + }, + "SignInRiskLevels" : ["high"] + }, + "GrantControls" : { + "BuiltInControls" : ["block"] + }, + "State" : "enabled", + "DisplayName" : "Test name" + } + ], + "service_plans" : [ + { + "ServicePlanName" : "EXCHANGE_S_FOUNDATION", + "ServicePlanId" : "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" + }, + { + "ServicePlanName" : "AAD_PREMIUM_P2", + "ServicePlanId" : "c7d91867-e1ce-4402-8d4f-22188b44b6c2" + } + ], + "scuba_config" : { + "Aad" : { + "MS.AAD.2.3v1" : { + "CapExclusions" : { + "Users" : ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], + "Groups" : [] + } + } + } + } + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "1 conditional access policy(s) found that meet(s) all requirements:
Test name. View all CA policies." +} + +test_NoExclusionsExemptGroups_Correct_V2 if { + PolicyId := "MS.AAD.2.3v1" + + Output := tests with input as { + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : [], + "ExcludeGroups" : [], + "ExcludeRoles" : [] + }, + "SignInRiskLevels" : ["high"] + }, + "GrantControls" : { + "BuiltInControls" : ["block"] + }, + "State" : "enabled", + "DisplayName" : "Test name" + } + ], + "service_plans" : [ + { + "ServicePlanName" : "EXCHANGE_S_FOUNDATION", + "ServicePlanId" : "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" + }, + { + "ServicePlanName" : "AAD_PREMIUM_P2", + "ServicePlanId" : "c7d91867-e1ce-4402-8d4f-22188b44b6c2" + } + ], + "scuba_config" : { + "Aad" : { + "MS.AAD.2.3v1" : { + "CapExclusions" : { + "Users" : [], + "Groups" : ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"] + } + } + } + } + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "1 conditional access policy(s) found that meet(s) all requirements:
Test name. View all CA policies." +} + +# User exclusions test +test_UserExclusionNoExempt_Incorrect_V2 if { + PolicyId := "MS.AAD.2.3v1" + + Output := tests with input as { + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], + "ExcludeGroups" : [], + "ExcludeRoles" : [] + }, + "SignInRiskLevels" : ["high"] + }, + "GrantControls" : { + "BuiltInControls" : ["block"] + }, + "State" : "enabled", + "DisplayName" : "Test name" + } + ], + "service_plans" : [ + { + "ServicePlanName" : "EXCHANGE_S_FOUNDATION", + "ServicePlanId" : "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" + }, + { + "ServicePlanName" : "AAD_PREMIUM_P2", + "ServicePlanId" : "c7d91867-e1ce-4402-8d4f-22188b44b6c2" + } + ] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." +} + +test_UserExclusionConditions_Correct_V2 if { + PolicyId := "MS.AAD.2.3v1" + + Output := tests with input as { + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], + "ExcludeGroups" : [], + "ExcludeRoles" : [] + }, + "SignInRiskLevels" : ["high"] + }, + "GrantControls" : { + "BuiltInControls" : ["block"] + }, + "State" : "enabled", + "DisplayName" : "Test name" + } + ], + "service_plans" : [ + { + "ServicePlanName" : "EXCHANGE_S_FOUNDATION", + "ServicePlanId" : "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" + }, + { + "ServicePlanName" : "AAD_PREMIUM_P2", + "ServicePlanId" : "c7d91867-e1ce-4402-8d4f-22188b44b6c2" + } + ], + "scuba_config" : { + "Aad" : { + "MS.AAD.2.3v1" : { + "CapExclusions" : { + "Users" : ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], + "Groups" : [] + } + } + } + } + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "1 conditional access policy(s) found that meet(s) all requirements:
Test name. View all CA policies." +} + +test_UserExclusionsNoExempt_Incorrect_V2 if { + PolicyId := "MS.AAD.2.3v1" + + Output := tests with input as { + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3", "65fea286-22d3-42f9-b4ca-93a6f75817d4"], + "ExcludeGroups" : [], + "ExcludeRoles" : [] + }, + "SignInRiskLevels" : ["high"] + }, + "GrantControls" : { + "BuiltInControls" : ["block"] + }, + "State" : "enabled", + "DisplayName" : "Test name" + } + ], + "service_plans" : [ + { + "ServicePlanName" : "EXCHANGE_S_FOUNDATION", + "ServicePlanId" : "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" + }, + { + "ServicePlanName" : "AAD_PREMIUM_P2", + "ServicePlanId" : "c7d91867-e1ce-4402-8d4f-22188b44b6c2" + } + ] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." +} + +test_UserExclusionsSingleExempt_Incorrect_V2 if { + PolicyId := "MS.AAD.2.3v1" + + Output := tests with input as { + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3", "65fea286-22d3-42f9-b4ca-93a6f75817d4"], + "ExcludeGroups" : [], + "ExcludeRoles" : [] + }, + "SignInRiskLevels" : ["high"] + }, + "GrantControls" : { + "BuiltInControls" : ["block"] + }, + "State" : "enabled", + "DisplayName" : "Test name" + } + ], + "service_plans" : [ + { + "ServicePlanName" : "EXCHANGE_S_FOUNDATION", + "ServicePlanId" : "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" + }, + { + "ServicePlanName" : "AAD_PREMIUM_P2", + "ServicePlanId" : "c7d91867-e1ce-4402-8d4f-22188b44b6c2" + } + ], + "scuba_config" : { + "Aad" : { + "MS.AAD.2.3v1" : { + "CapExclusions" : { + "Users" : ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], + "Groups" : [] + } + } + } + } + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." +} + +test_MultiUserExclusionsConditions_Correct_V2 if { + PolicyId := "MS.AAD.2.3v1" + + Output := tests with input as { + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3", "65fea286-22d3-42f9-b4ca-93a6f75817d4"], + "ExcludeGroups" : [], + "ExcludeRoles" : [] + }, + "SignInRiskLevels" : ["high"] + }, + "GrantControls" : { + "BuiltInControls" : ["block"] + }, + "State" : "enabled", + "DisplayName" : "Test name" + } + ], + "service_plans" : [ + { + "ServicePlanName" : "EXCHANGE_S_FOUNDATION", + "ServicePlanId" : "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" + }, + { + "ServicePlanName" : "AAD_PREMIUM_P2", + "ServicePlanId" : "c7d91867-e1ce-4402-8d4f-22188b44b6c2" + } + ], + "scuba_config" : { + "Aad" : { + "MS.AAD.2.3v1" : { + "CapExclusions" : { + "Users" : ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3", "65fea286-22d3-42f9-b4ca-93a6f75817d4"], + "Groups" : [] + } + } + } + } + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "1 conditional access policy(s) found that meet(s) all requirements:
Test name. View all CA policies." +} + +# Group Exclusion tests +test_GroupExclusionNoExempt_Incorrect_V2 if { + PolicyId := "MS.AAD.2.3v1" + + Output := tests with input as { + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : [], + "ExcludeGroups" : ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], + "ExcludeRoles" : [] + }, + "SignInRiskLevels" : ["high"] + }, + "GrantControls" : { + "BuiltInControls" : ["block"] + }, + "State" : "enabled", + "DisplayName" : "Test name" + } + ], + "service_plans" : [ + { + "ServicePlanName" : "EXCHANGE_S_FOUNDATION", + "ServicePlanId" : "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" + }, + { + "ServicePlanName" : "AAD_PREMIUM_P2", + "ServicePlanId" : "c7d91867-e1ce-4402-8d4f-22188b44b6c2" + } + ] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." +} + +test_GroupExclusionsConditions_Correct_V2 if { + PolicyId := "MS.AAD.2.3v1" + + Output := tests with input as { + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : [], + "ExcludeGroups" : ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"], + "ExcludeRoles" : [] + }, + "SignInRiskLevels" : ["high"] + }, + "GrantControls" : { + "BuiltInControls" : ["block"] + }, + "State" : "enabled", + "DisplayName" : "Test name" + } + ], + "service_plans" : [ + { + "ServicePlanName" : "EXCHANGE_S_FOUNDATION", + "ServicePlanId" : "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" + }, + { + "ServicePlanName" : "AAD_PREMIUM_P2", + "ServicePlanId" : "c7d91867-e1ce-4402-8d4f-22188b44b6c2" + } + ], + "scuba_config" : { + "Aad" : { + "MS.AAD.2.3v1" : { + "CapExclusions" : { + "Users" : [], + "Groups" : ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"] + } + } + } + } + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "1 conditional access policy(s) found that meet(s) all requirements:
Test name. View all CA policies." +} + +test_GroupExclusionsNoExempt_Incorrect_V2 if { + PolicyId := "MS.AAD.2.3v1" + + Output := tests with input as { + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : [], + "ExcludeGroups" : ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3", "65fea286-22d3-42f9-b4ca-93a6f75817d4"], + "ExcludeRoles" : [] + }, + "SignInRiskLevels" : ["high"] + }, + "GrantControls" : { + "BuiltInControls" : ["block"] + }, + "State" : "enabled", + "DisplayName" : "Test name" + } + ], + "service_plans" : [ + { + "ServicePlanName" : "EXCHANGE_S_FOUNDATION", + "ServicePlanId" : "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" + }, + { + "ServicePlanName" : "AAD_PREMIUM_P2", + "ServicePlanId" : "c7d91867-e1ce-4402-8d4f-22188b44b6c2" + } + ] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." +} + +test_GroupExclusionsSingleExempt_Incorrect_V2 if { + PolicyId := "MS.AAD.2.3v1" + + Output := tests with input as { + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : [], + "ExcludeGroups" : ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3", "65fea286-22d3-42f9-b4ca-93a6f75817d4"], + "ExcludeRoles" : [] + }, + "SignInRiskLevels" : ["high"] + }, + "GrantControls" : { + "BuiltInControls" : ["block"] + }, + "State" : "enabled", + "DisplayName" : "Test name" + } + ], + "service_plans" : [ + { + "ServicePlanName" : "EXCHANGE_S_FOUNDATION", + "ServicePlanId" : "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" + }, + { + "ServicePlanName" : "AAD_PREMIUM_P2", + "ServicePlanId" : "c7d91867-e1ce-4402-8d4f-22188b44b6c2" + } + ], + "scuba_config" : { + "Aad" : { + "MS.AAD.2.3v1" : { + "CapExclusions" : { + "Users" : [], + "Groups" : ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"] + } + } + } + } + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." +} + +test_MultiGroupExclusionsConditions_Correct_V2 if { + PolicyId := "MS.AAD.2.3v1" + + Output := tests with input as { + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : [], + "ExcludeGroups" : ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423", "65fea286-22d3-42f9-b4ca-93a6f75817d4"], + "ExcludeRoles" : [] + }, + "SignInRiskLevels" : ["high"] + }, + "GrantControls" : { + "BuiltInControls" : ["block"] + }, + "State" : "enabled", + "DisplayName" : "Test name" + } + ], + "service_plans" : [ + { + "ServicePlanName" : "EXCHANGE_S_FOUNDATION", + "ServicePlanId" : "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" + }, + { + "ServicePlanName" : "AAD_PREMIUM_P2", + "ServicePlanId" : "c7d91867-e1ce-4402-8d4f-22188b44b6c2" + } + ], + "scuba_config" : { + "Aad" : { + "MS.AAD.2.3v1" : { + "CapExclusions" : { + "Users" : [], + "Groups" : ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423", "65fea286-22d3-42f9-b4ca-93a6f75817d4"] + } + } + } + } + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "1 conditional access policy(s) found that meet(s) all requirements:
Test name. View all CA policies." +} + +# User and group exclusions tests +test_UserGroupExclusionConditions_Correct_V2 if { + PolicyId := "MS.AAD.2.3v1" + + Output := tests with input as { + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], + "ExcludeGroups" : ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"], + "ExcludeRoles" : [] + }, + "SignInRiskLevels" : ["high"] + }, + "GrantControls" : { + "BuiltInControls" : ["block"] + }, + "State" : "enabled", + "DisplayName" : "Test name" + } + ], + "service_plans" : [ + { + "ServicePlanName" : "EXCHANGE_S_FOUNDATION", + "ServicePlanId" : "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" + }, + { + "ServicePlanName" : "AAD_PREMIUM_P2", + "ServicePlanId" : "c7d91867-e1ce-4402-8d4f-22188b44b6c2" + } + ], + "scuba_config" : { + "Aad" : { + "MS.AAD.2.3v1" : { + "CapExclusions" : { + "Users" : ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], + "Groups" : ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"] + } + } + } + } + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "1 conditional access policy(s) found that meet(s) all requirements:
Test name. View all CA policies." +} + +test_UserGroupExclusionNoExempt_Incorrect_V2 if { + PolicyId := "MS.AAD.2.3v1" + + Output := tests with input as { + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], + "ExcludeGroups" : ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"], + "ExcludeRoles" : [] + }, + "SignInRiskLevels" : ["high"] + }, + "GrantControls" : { + "BuiltInControls" : ["block"] + }, + "State" : "enabled", + "DisplayName" : "Test name" + } + ], + "service_plans" : [ + { + "ServicePlanName" : "EXCHANGE_S_FOUNDATION", + "ServicePlanId" : "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" + }, + { + "ServicePlanName" : "AAD_PREMIUM_P2", + "ServicePlanId" : "c7d91867-e1ce-4402-8d4f-22188b44b6c2" + } + ] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." +} + +test_UserGroupExclusionUserExemptOnly_Incorrect_V2 if { + PolicyId := "MS.AAD.2.3v1" + + Output := tests with input as { + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], + "ExcludeGroups" : ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"], + "ExcludeRoles" : [] + }, + "SignInRiskLevels" : ["high"] + }, + "GrantControls" : { + "BuiltInControls" : ["block"] + }, + "State" : "enabled", + "DisplayName" : "Test name" + } + ], + "service_plans" : [ + { + "ServicePlanName" : "EXCHANGE_S_FOUNDATION", + "ServicePlanId" : "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" + }, + { + "ServicePlanName" : "AAD_PREMIUM_P2", + "ServicePlanId" : "c7d91867-e1ce-4402-8d4f-22188b44b6c2" + } + ], + "scuba_config" : { + "Aad" : { + "MS.AAD.2.3v1" : { + "CapExclusions" : { + "Users" : ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], + "Groups" : [] + } + } + } + } + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." +} + +test_UserGroupExclusionGroupExemptOnly_Incorrect_V2 if { + PolicyId := "MS.AAD.2.3v1" + + Output := tests with input as { + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], + "ExcludeGroups" : ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"], + "ExcludeRoles" : [] + }, + "SignInRiskLevels" : ["high"] + }, + "GrantControls" : { + "BuiltInControls" : ["block"] + }, + "State" : "enabled", + "DisplayName" : "Test name" + } + ], + "service_plans" : [ + { + "ServicePlanName" : "EXCHANGE_S_FOUNDATION", + "ServicePlanId" : "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" + }, + { + "ServicePlanName" : "AAD_PREMIUM_P2", + "ServicePlanId" : "c7d91867-e1ce-4402-8d4f-22188b44b6c2" + } + ], + "scuba_config" : { + "Aad" : { + "MS.AAD.2.3v1" : { + "CapExclusions" : { + "Users" : [], + "Groups" : ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"] + } + } + } + } + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." +} + +test_UserGroupExclusionTooFewUserExempts_Incorrect_V2 if { + PolicyId := "MS.AAD.2.3v1" + + Output := tests with input as { + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423", "65fea286-22d3-42f9-b4ca-93a6f75817d4"], + "ExcludeGroups" : ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"], + "ExcludeRoles" : [] + }, + "SignInRiskLevels" : ["high"] + }, + "GrantControls" : { + "BuiltInControls" : ["block"] + }, + "State" : "enabled", + "DisplayName" : "Test name" + } + ], + "service_plans" : [ + { + "ServicePlanName" : "EXCHANGE_S_FOUNDATION", + "ServicePlanId" : "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" + }, + { + "ServicePlanName" : "AAD_PREMIUM_P2", + "ServicePlanId" : "c7d91867-e1ce-4402-8d4f-22188b44b6c2" + } + ], + "scuba_config" : { + "Aad" : { + "MS.AAD.2.3v1" : { + "CapExclusions" : { + "Users" : ["65fea286-22d3-42f9-b4ca-93a6f75817d4"], + "Groups" : ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"] + } + } + } + } + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." +} + +# Other Conditions +test_Conditions_Correct if { + PolicyId := "MS.AAD.2.3v1" + + Output := tests with input as { + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : [], + "ExcludeGroups" : [], + "ExcludeRoles" : [] + }, + "SignInRiskLevels" : ["high"] + }, + "GrantControls" : { + "BuiltInControls" : ["block"] + }, + "State" : "enabled", + "DisplayName" : "Test name" + } + ], + "service_plans" : [ + { + "ServicePlanName" : "EXCHANGE_S_FOUNDATION", + "ServicePlanId" : "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" + }, + { + "ServicePlanName" : "AAD_PREMIUM_P2", + "ServicePlanId" : "c7d91867-e1ce-4402-8d4f-22188b44b6c2" + } + ] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "1 conditional access policy(s) found that meet(s) all requirements:
Test name. View all CA policies." +} + +test_IncludeApplications_Incorrect_V2 if { + PolicyId := "MS.AAD.2.3v1" + + Output := tests with input as { + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["Office365"] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : [], + "ExcludeGroups" : [], + "ExcludeRoles" : [] + }, + "SignInRiskLevels" : ["high"] + }, + "GrantControls" : { + "BuiltInControls" : ["block"] + }, + "State" : "enabled", + "DisplayName" : "Test name" + } + ], + "service_plans" : [ + { + "ServicePlanName" : "EXCHANGE_S_FOUNDATION", + "ServicePlanId" : "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" + }, + { + "ServicePlanName" : "AAD_PREMIUM_P2", + "ServicePlanId" : "c7d91867-e1ce-4402-8d4f-22188b44b6c2" + } + ] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." +} + +test_IncludeUsers_Incorrect_V2 if { + PolicyId := "MS.AAD.2.3v1" + + Output := tests with input as { + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeUsers" : ["8bc7c6ee-39a2-42a5-a31b-f77fb51db652"], + "ExcludeUsers" : [], + "ExcludeGroups" : [], + "ExcludeRoles" : [] + }, + "SignInRiskLevels" : ["high"] + }, + "GrantControls" : { + "BuiltInControls" : ["block"] + }, + "State" : "enabled", + "DisplayName" : "Test name" + } + ], + "service_plans" : [ + { + "ServicePlanName" : "EXCHANGE_S_FOUNDATION", + "ServicePlanId" : "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" + }, + { + "ServicePlanName" : "AAD_PREMIUM_P2", + "ServicePlanId" : "c7d91867-e1ce-4402-8d4f-22188b44b6c2" + } + ] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." +} + +test_ExcludeUsers_Incorrect_V2 if { + PolicyId := "MS.AAD.2.3v1" + + Output := tests with input as { + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : ["8bc7c6ee-39a2-42a5-a31b-f77fb51db652"], + "ExcludeGroups" : [], + "ExcludeRoles" : [] + }, + "SignInRiskLevels" : ["high"] + }, + "GrantControls" : { + "BuiltInControls" : ["block"] + }, + "State" : "enabled", + "DisplayName" : "Test name" + } + ], + "service_plans" : [ + { + "ServicePlanName" : "EXCHANGE_S_FOUNDATION", + "ServicePlanId" : "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" + }, + { + "ServicePlanName" : "AAD_PREMIUM_P2", + "ServicePlanId" : "c7d91867-e1ce-4402-8d4f-22188b44b6c2" + } + ] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." +} + +test_ExcludeGroups_Incorrect_V2 if { + PolicyId := "MS.AAD.2.3v1" + + Output := tests with input as { + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : [], + "ExcludeGroups" : ["8bc7c6ee-39a2-42a5-a31b-f77fb51db652"], + "ExcludeRoles" : [] + }, + "SignInRiskLevels" : ["high"] + }, + "GrantControls" : { + "BuiltInControls" : ["block"] + }, + "State" : "enabled", + "DisplayName" : "Test name" + } + ], + "service_plans" : [ + { + "ServicePlanName" : "EXCHANGE_S_FOUNDATION", + "ServicePlanId" : "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" + }, + { + "ServicePlanName" : "AAD_PREMIUM_P2", + "ServicePlanId" : "c7d91867-e1ce-4402-8d4f-22188b44b6c2" + } + ] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." +} + +test_ExcludeRoles_Incorrect_V2 if { + PolicyId := "MS.AAD.2.3v1" + + Output := tests with input as { + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : [], + "ExcludeGroups" : [], + "ExcludeRoles" : ["8bc7c6ee-39a2-42a5-a31b-f77fb51db652"] + }, + "SignInRiskLevels" : ["high"] + }, + "GrantControls" : { + "BuiltInControls" : ["block"] + }, + "State" : "enabled", + "DisplayName" : "Test name" + } + ], + "service_plans" : [ + { + "ServicePlanName" : "EXCHANGE_S_FOUNDATION", + "ServicePlanId" : "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" + }, + { + "ServicePlanName" : "AAD_PREMIUM_P2", + "ServicePlanId" : "c7d91867-e1ce-4402-8d4f-22188b44b6c2" + } + ] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." +} + +test_SignInRiskLevels_Incorrect if { + PolicyId := "MS.AAD.2.3v1" + + Output := tests with input as { + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : [], + "ExcludeGroups" : [], + "ExcludeRoles" : [] + }, + "SignInRiskLevels" : [""] + }, + "GrantControls" : { + "BuiltInControls" : ["block"] + }, + "State" : "enabled", + "DisplayName" : "Test name" + } + ], + "service_plans" : [ + { + "ServicePlanName" : "EXCHANGE_S_FOUNDATION", + "ServicePlanId" : "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" + }, + { + "ServicePlanName" : "AAD_PREMIUM_P2", + "ServicePlanId" : "c7d91867-e1ce-4402-8d4f-22188b44b6c2" + } + ] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." +} + +test_BuiltInControls_Incorrect_V2 if { + PolicyId := "MS.AAD.2.3v1" + + Output := tests with input as { + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : [], + "ExcludeGroups" : [], + "ExcludeRoles" : [] + }, + "SignInRiskLevels" : ["high"] + }, + "GrantControls" : { + "BuiltInControls" : [""] + }, + "State" : "enabled", + "DisplayName" : "Test name" + } + ], + "service_plans" : [ + { + "ServicePlanName" : "EXCHANGE_S_FOUNDATION", + "ServicePlanId" : "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" + }, + { + "ServicePlanName" : "AAD_PREMIUM_P2", + "ServicePlanId" : "c7d91867-e1ce-4402-8d4f-22188b44b6c2" + } + ] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." +} + +test_State_Incorrect_V2 if { + PolicyId := "MS.AAD.2.3v1" + + Output := tests with input as { + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : [], + "ExcludeGroups" : [], + "ExcludeRoles" : [] + }, + "SignInRiskLevels" : ["high"] + }, + "GrantControls" : { + "BuiltInControls" : ["block"] + }, + "State" : "disabled", + "DisplayName" : "Test name" + } + ], + "service_plans" : [ + { + "ServicePlanName" : "EXCHANGE_S_FOUNDATION", + "ServicePlanId" : "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" + }, + { + "ServicePlanName" : "AAD_PREMIUM_P2", + "ServicePlanId" : "c7d91867-e1ce-4402-8d4f-22188b44b6c2" + } + ] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." +} +#-- \ No newline at end of file diff --git a/Testing/Unit/Rego/AAD/AADConfig_03_test.rego b/Testing/Unit/Rego/AAD/AADConfig_03_test.rego index e9987c0489..add2a1986b 100644 --- a/Testing/Unit/Rego/AAD/AADConfig_03_test.rego +++ b/Testing/Unit/Rego/AAD/AADConfig_03_test.rego @@ -1,47 +1,53 @@ package aad import future.keywords +import data.report.utils.NotCheckedDetails # -# Policy 1 +# MS.AAD.3.1v1 +#-- +test_NotImplemented_Correct_V1 if { + PolicyId := "MS.AAD.3.1v1" + + Output := tests with input as { } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == NotCheckedDetails(PolicyId) +} #-- +# +# MS.AAD.3.2v1 +#-- test_NoExclusionsConditions_Correct if { - PolicyId := "MS.AAD.3.1v1" + PolicyId := "MS.AAD.3.2v1" Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": [], - "ExcludeGroups": [], - "ExcludeRoles": [] - }, - "SignInRiskLevels": ["high"] - }, - "GrantControls": { - "BuiltInControls": ["block"] - }, - "State": "enabled", - "DisplayName": "Test name" - } - ], - "service_plans": [ - { - "ServicePlanName": "EXCHANGE_S_FOUNDATION", - "ServicePlanId": "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" - }, - { - "ServicePlanName": "AAD_PREMIUM_P2", - "ServicePlanId": "c7d91867-e1ce-4402-8d4f-22188b44b6c2" - } + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : [], + "ExcludeGroups" : [], + "ExcludeRoles" : [] + } + }, + "GrantControls" : { + "BuiltInControls" : ["mfa"] + }, + "State" : "enabled", + "DisplayName" : "Test name" + } ] } + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 @@ -50,53 +56,41 @@ test_NoExclusionsConditions_Correct if { } test_NoExclusionsExemptUsers_Correct if { - PolicyId := "MS.AAD.3.1v1" + PolicyId := "MS.AAD.3.2v1" Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": [], - "ExcludeGroups": [], - "ExcludeRoles": [] - }, - "SignInRiskLevels": ["high"] - }, - "GrantControls": { - "BuiltInControls": ["block"] - }, - "State": "enabled", - "DisplayName": "Test name" - } - ], - "service_plans": [ - { - "ServicePlanName": "EXCHANGE_S_FOUNDATION", - "ServicePlanId": "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" - }, - { - "ServicePlanName": "AAD_PREMIUM_P2", - "ServicePlanId": "c7d91867-e1ce-4402-8d4f-22188b44b6c2" - } + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : [], + "ExcludeGroups" : [], + "ExcludeRoles" : [] + } + }, + "GrantControls" : { + "BuiltInControls" : ["mfa"] + }, + "State" : "enabled", + "DisplayName" : "Test name" + } ], - "scuba_config": { - "Aad": { - "Policy2_3_1": { - "CapExclusions": { - "Users": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], - "Groups": [] + "scuba_config" : { + "Aad" : { + "MS.AAD.3.2v1" : { + "CapExclusions" : { + "Users" : ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], + "Groups" : [] } } - } - } } + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 @@ -105,53 +99,41 @@ test_NoExclusionsExemptUsers_Correct if { } test_NoExclusionsExemptGroups_Correct if { - PolicyId := "MS.AAD.3.1v1" + PolicyId := "MS.AAD.3.2v1" Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": [], - "ExcludeGroups": [], - "ExcludeRoles": [] - }, - "SignInRiskLevels": ["high"] - }, - "GrantControls": { - "BuiltInControls": ["block"] - }, - "State": "enabled", - "DisplayName": "Test name" - } - ], - "service_plans": [ - { - "ServicePlanName": "EXCHANGE_S_FOUNDATION", - "ServicePlanId": "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" - }, - { - "ServicePlanName": "AAD_PREMIUM_P2", - "ServicePlanId": "c7d91867-e1ce-4402-8d4f-22188b44b6c2" - } + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : [], + "ExcludeGroups" : [], + "ExcludeRoles" : [] + } + }, + "GrantControls" : { + "BuiltInControls" : ["mfa"] + }, + "State" : "enabled", + "DisplayName" : "Test name" + } ], - "scuba_config": { - "Aad": { - "Policy2_3_1": { - "CapExclusions": { - "Users": [], - "Groups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"] + "scuba_config" : { + "Aad" : { + "MS.AAD.3.2v1" : { + "CapExclusions" : { + "Users" : [], + "Groups" : ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"] } } - } - } } + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 @@ -161,41 +143,31 @@ test_NoExclusionsExemptGroups_Correct if { # User exclusions test test_UserExclusionNoExempt_Incorrect if { - PolicyId := "MS.AAD.3.1v1" + PolicyId := "MS.AAD.3.2v1" Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], - "ExcludeGroups": [], - "ExcludeRoles": [] - }, - "SignInRiskLevels": ["high"] - }, - "GrantControls": { - "BuiltInControls": ["block"] - }, - "State": "enabled", - "DisplayName": "Test name" - } - ], - "service_plans": [ - { - "ServicePlanName": "EXCHANGE_S_FOUNDATION", - "ServicePlanId": "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" - }, - { - "ServicePlanName": "AAD_PREMIUM_P2", - "ServicePlanId": "c7d91867-e1ce-4402-8d4f-22188b44b6c2" - } + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], + "ExcludeGroups" : [], + "ExcludeRoles" : [] + } + }, + "GrantControls" : { + "BuiltInControls" : ["mfa"] + }, + "State" : "enabled", + "DisplayName" : "Test name" + } ] } + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 @@ -204,53 +176,41 @@ test_UserExclusionNoExempt_Incorrect if { } test_UserExclusionConditions_Correct if { - PolicyId := "MS.AAD.3.1v1" + PolicyId := "MS.AAD.3.2v1" Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], - "ExcludeGroups": [], - "ExcludeRoles": [] - }, - "SignInRiskLevels": ["high"] - }, - "GrantControls": { - "BuiltInControls": ["block"] - }, - "State": "enabled", - "DisplayName": "Test name" - } - ], - "service_plans": [ - { - "ServicePlanName": "EXCHANGE_S_FOUNDATION", - "ServicePlanId": "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" - }, - { - "ServicePlanName": "AAD_PREMIUM_P2", - "ServicePlanId": "c7d91867-e1ce-4402-8d4f-22188b44b6c2" - } + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], + "ExcludeGroups" : [], + "ExcludeRoles" : [] + } + }, + "GrantControls" : { + "BuiltInControls" : ["mfa"] + }, + "State" : "enabled", + "DisplayName" : "Test name" + } ], - "scuba_config": { - "Aad": { - "Policy2_3_1": { - "CapExclusions": { - "Users": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], - "Groups": [] + "scuba_config" : { + "Aad" : { + "MS.AAD.3.2v1" : { + "CapExclusions" : { + "Users" : ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], + "Groups" : [] } } - } - } } + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 @@ -259,41 +219,31 @@ test_UserExclusionConditions_Correct if { } test_UserExclusionsNoExempt_Incorrect if { - PolicyId := "MS.AAD.3.1v1" + PolicyId := "MS.AAD.3.2v1" Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3", "65fea286-22d3-42f9-b4ca-93a6f75817d4"], - "ExcludeGroups": [], - "ExcludeRoles": [] - }, - "SignInRiskLevels": ["high"] - }, - "GrantControls": { - "BuiltInControls": ["block"] - }, - "State": "enabled", - "DisplayName": "Test name" - } - ], - "service_plans": [ - { - "ServicePlanName": "EXCHANGE_S_FOUNDATION", - "ServicePlanId": "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" - }, - { - "ServicePlanName": "AAD_PREMIUM_P2", - "ServicePlanId": "c7d91867-e1ce-4402-8d4f-22188b44b6c2" - } + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3", "65fea286-22d3-42f9-b4ca-93a6f75817d4"], + "ExcludeGroups" : [], + "ExcludeRoles" : [] + } + }, + "GrantControls" : { + "BuiltInControls" : ["mfa"] + }, + "State" : "enabled", + "DisplayName" : "Test name" + } ] } + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 @@ -302,53 +252,41 @@ test_UserExclusionsNoExempt_Incorrect if { } test_UserExclusionsSingleExempt_Incorrect if { - PolicyId := "MS.AAD.3.1v1" + PolicyId := "MS.AAD.3.2v1" Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3", "65fea286-22d3-42f9-b4ca-93a6f75817d4"], - "ExcludeGroups": [], - "ExcludeRoles": [] - }, - "SignInRiskLevels": ["high"] - }, - "GrantControls": { - "BuiltInControls": ["block"] - }, - "State": "enabled", - "DisplayName": "Test name" - } - ], - "service_plans": [ - { - "ServicePlanName": "EXCHANGE_S_FOUNDATION", - "ServicePlanId": "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" - }, - { - "ServicePlanName": "AAD_PREMIUM_P2", - "ServicePlanId": "c7d91867-e1ce-4402-8d4f-22188b44b6c2" - } + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3", "65fea286-22d3-42f9-b4ca-93a6f75817d4"], + "ExcludeGroups" : [], + "ExcludeRoles" : [] + } + }, + "GrantControls" : { + "BuiltInControls" : ["mfa"] + }, + "State" : "enabled", + "DisplayName" : "Test name" + } ], - "scuba_config": { - "Aad": { - "Policy2_3_1": { - "CapExclusions": { - "Users": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], - "Groups": [] + "scuba_config" : { + "Aad" : { + "MS.AAD.3.2v1" : { + "CapExclusions" : { + "Users" : ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], + "Groups" : [] } } - } - } } + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 @@ -357,53 +295,41 @@ test_UserExclusionsSingleExempt_Incorrect if { } test_MultiUserExclusionsConditions_Correct if { - PolicyId := "MS.AAD.3.1v1" + PolicyId := "MS.AAD.3.2v1" Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3", "65fea286-22d3-42f9-b4ca-93a6f75817d4"], - "ExcludeGroups": [], - "ExcludeRoles": [] - }, - "SignInRiskLevels": ["high"] - }, - "GrantControls": { - "BuiltInControls": ["block"] - }, - "State": "enabled", - "DisplayName": "Test name" - } - ], - "service_plans": [ - { - "ServicePlanName": "EXCHANGE_S_FOUNDATION", - "ServicePlanId": "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" - }, - { - "ServicePlanName": "AAD_PREMIUM_P2", - "ServicePlanId": "c7d91867-e1ce-4402-8d4f-22188b44b6c2" - } + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3", "65fea286-22d3-42f9-b4ca-93a6f75817d4"], + "ExcludeGroups" : [], + "ExcludeRoles" : [] + } + }, + "GrantControls" : { + "BuiltInControls" : ["mfa"] + }, + "State" : "enabled", + "DisplayName" : "Test name" + } ], - "scuba_config": { - "Aad": { - "Policy2_3_1": { - "CapExclusions": { - "Users": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3", "65fea286-22d3-42f9-b4ca-93a6f75817d4"], - "Groups": [] + "scuba_config" : { + "Aad" : { + "MS.AAD.3.2v1" : { + "CapExclusions" : { + "Users" : ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3", "65fea286-22d3-42f9-b4ca-93a6f75817d4"], + "Groups" : [] } } - } - } } + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 @@ -413,41 +339,31 @@ test_MultiUserExclusionsConditions_Correct if { # Group Exclusion tests test_GroupExclusionNoExempt_Incorrect if { - PolicyId := "MS.AAD.3.1v1" + PolicyId := "MS.AAD.3.2v1" Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": [], - "ExcludeGroups": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], - "ExcludeRoles": [] - }, - "SignInRiskLevels": ["high"] - }, - "GrantControls": { - "BuiltInControls": ["block"] - }, - "State": "enabled", - "DisplayName": "Test name" - } - ], - "service_plans": [ - { - "ServicePlanName": "EXCHANGE_S_FOUNDATION", - "ServicePlanId": "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" - }, - { - "ServicePlanName": "AAD_PREMIUM_P2", - "ServicePlanId": "c7d91867-e1ce-4402-8d4f-22188b44b6c2" - } + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : [], + "ExcludeGroups" : ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], + "ExcludeRoles" : [] + } + }, + "GrantControls" : { + "BuiltInControls" : ["mfa"] + }, + "State" : "enabled", + "DisplayName" : "Test name" + } ] } + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 @@ -456,52 +372,41 @@ test_GroupExclusionNoExempt_Incorrect if { } test_GroupExclusionsConditions_Correct if { - PolicyId := "MS.AAD.3.1v1" + PolicyId := "MS.AAD.3.2v1" Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": [], - "ExcludeGroups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"], - "ExcludeRoles": [] - }, - "SignInRiskLevels": ["high"] - }, - "GrantControls": { - "BuiltInControls": ["block"] - }, - "State": "enabled", - "DisplayName": "Test name" - } - ], - "service_plans": [ - { - "ServicePlanName": "EXCHANGE_S_FOUNDATION", - "ServicePlanId": "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" - }, - { - "ServicePlanName": "AAD_PREMIUM_P2", - "ServicePlanId": "c7d91867-e1ce-4402-8d4f-22188b44b6c2" - } + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : [], + "ExcludeGroups" : ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"], + "ExcludeRoles" : [] + } + }, + "GrantControls" : { + "BuiltInControls" : ["mfa"] + }, + "State" : "enabled", + "DisplayName" : "Test name" + } ], - "scuba_config": { - "Aad": { - "Policy2_3_1": { - "CapExclusions": { - "Users": [], - "Groups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"] + "scuba_config" : { + "Aad" : { + "MS.AAD.3.2v1" : { + "CapExclusions" : { + "Users" : [], + "Groups" : ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"] } } - } } } + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 @@ -510,41 +415,31 @@ test_GroupExclusionsConditions_Correct if { } test_GroupExclusionsNoExempt_Incorrect if { - PolicyId := "MS.AAD.3.1v1" + PolicyId := "MS.AAD.3.2v1" Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": [], - "ExcludeGroups": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3", "65fea286-22d3-42f9-b4ca-93a6f75817d4"], - "ExcludeRoles": [] - }, - "SignInRiskLevels": ["high"] - }, - "GrantControls": { - "BuiltInControls": ["block"] - }, - "State": "enabled", - "DisplayName": "Test name" - } - ], - "service_plans": [ - { - "ServicePlanName": "EXCHANGE_S_FOUNDATION", - "ServicePlanId": "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" - }, - { - "ServicePlanName": "AAD_PREMIUM_P2", - "ServicePlanId": "c7d91867-e1ce-4402-8d4f-22188b44b6c2" - } + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : [], + "ExcludeGroups" : ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3", "65fea286-22d3-42f9-b4ca-93a6f75817d4"], + "ExcludeRoles" : [] + } + }, + "GrantControls" : { + "BuiltInControls" : ["mfa"] + }, + "State" : "enabled", + "DisplayName" : "Test name" + } ] } + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 @@ -553,52 +448,41 @@ test_GroupExclusionsNoExempt_Incorrect if { } test_GroupExclusionsSingleExempt_Incorrect if { - PolicyId := "MS.AAD.3.1v1" + PolicyId := "MS.AAD.3.2v1" Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": [], - "ExcludeGroups": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3", "65fea286-22d3-42f9-b4ca-93a6f75817d4"], - "ExcludeRoles": [] - }, - "SignInRiskLevels": ["high"] - }, - "GrantControls": { - "BuiltInControls": ["block"] - }, - "State": "enabled", - "DisplayName": "Test name" - } - ], - "service_plans": [ - { - "ServicePlanName": "EXCHANGE_S_FOUNDATION", - "ServicePlanId": "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" - }, - { - "ServicePlanName": "AAD_PREMIUM_P2", - "ServicePlanId": "c7d91867-e1ce-4402-8d4f-22188b44b6c2" - } + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : [], + "ExcludeGroups" : ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3", "65fea286-22d3-42f9-b4ca-93a6f75817d4"], + "ExcludeRoles" : [] + } + }, + "GrantControls" : { + "BuiltInControls" : ["mfa"] + }, + "State" : "enabled", + "DisplayName" : "Test name" + } ], - "scuba_config": { - "Aad": { - "Policy2_3_1": { - "CapExclusions": { - "Users": [], - "Groups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"] + "scuba_config" : { + "Aad" : { + "MS.AAD.3.2v1" : { + "CapExclusions" : { + "Users" : [], + "Groups" : ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"] } } - } } } + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 @@ -607,52 +491,41 @@ test_GroupExclusionsSingleExempt_Incorrect if { } test_MultiGroupExclusionsConditions_Correct if { - PolicyId := "MS.AAD.3.1v1" + PolicyId := "MS.AAD.3.2v1" Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": [], - "ExcludeGroups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423", "65fea286-22d3-42f9-b4ca-93a6f75817d4"], - "ExcludeRoles": [] - }, - "SignInRiskLevels": ["high"] - }, - "GrantControls": { - "BuiltInControls": ["block"] - }, - "State": "enabled", - "DisplayName": "Test name" - } - ], - "service_plans": [ - { - "ServicePlanName": "EXCHANGE_S_FOUNDATION", - "ServicePlanId": "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" - }, - { - "ServicePlanName": "AAD_PREMIUM_P2", - "ServicePlanId": "c7d91867-e1ce-4402-8d4f-22188b44b6c2" - } + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : [], + "ExcludeGroups" : ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423", "65fea286-22d3-42f9-b4ca-93a6f75817d4"], + "ExcludeRoles" : [] + } + }, + "GrantControls" : { + "BuiltInControls" : ["mfa"] + }, + "State" : "enabled", + "DisplayName" : "Test name" + } ], - "scuba_config": { - "Aad": { - "Policy2_3_1": { - "CapExclusions": { - "Users": [], - "Groups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423", "65fea286-22d3-42f9-b4ca-93a6f75817d4"] + "scuba_config" : { + "Aad" : { + "MS.AAD.3.2v1" : { + "CapExclusions" : { + "Users" : [], + "Groups" : ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423", "65fea286-22d3-42f9-b4ca-93a6f75817d4"] } } - } } } + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 @@ -662,51 +535,41 @@ test_MultiGroupExclusionsConditions_Correct if { # User and group exclusions tests test_UserGroupExclusionConditions_Correct if { - PolicyId := "MS.AAD.3.1v1" + PolicyId := "MS.AAD.3.2v1" Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], - "ExcludeGroups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"], - "ExcludeRoles": [] - }, - "SignInRiskLevels": ["high"] - }, - "GrantControls": { - "BuiltInControls": ["block"] - }, - "State": "enabled", - "DisplayName": "Test name" - } - ], - "service_plans": [ - { - "ServicePlanName": "EXCHANGE_S_FOUNDATION", - "ServicePlanId": "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" - }, - { - "ServicePlanName": "AAD_PREMIUM_P2", - "ServicePlanId": "c7d91867-e1ce-4402-8d4f-22188b44b6c2" - } + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], + "ExcludeGroups" : ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"], + "ExcludeRoles" : [] + } + }, + "GrantControls" : { + "BuiltInControls" : ["mfa"] + }, + "State" : "enabled", + "DisplayName" : "Test name" + } ], - "scuba_config": { - "Aad": { - "Policy2_3_1": { - "CapExclusions": { - "Users": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], - "Groups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"] + "scuba_config" : { + "Aad" : { + "MS.AAD.3.2v1" : { + "CapExclusions" : { + "Users" : ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], + "Groups" : ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"] } } } } } + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 @@ -715,41 +578,31 @@ test_UserGroupExclusionConditions_Correct if { } test_UserGroupExclusionNoExempt_Incorrect if { - PolicyId := "MS.AAD.3.1v1" + PolicyId := "MS.AAD.3.2v1" Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], - "ExcludeGroups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"], - "ExcludeRoles": [] - }, - "SignInRiskLevels": ["high"] - }, - "GrantControls": { - "BuiltInControls": ["block"] - }, - "State": "enabled", - "DisplayName": "Test name" - } - ], - "service_plans": [ - { - "ServicePlanName": "EXCHANGE_S_FOUNDATION", - "ServicePlanId": "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" - }, - { - "ServicePlanName": "AAD_PREMIUM_P2", - "ServicePlanId": "c7d91867-e1ce-4402-8d4f-22188b44b6c2" - } + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], + "ExcludeGroups" : ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"], + "ExcludeRoles" : [] + } + }, + "GrantControls" : { + "BuiltInControls" : ["mfa"] + }, + "State" : "enabled", + "DisplayName" : "Test name" + } ] } + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 @@ -758,51 +611,41 @@ test_UserGroupExclusionNoExempt_Incorrect if { } test_UserGroupExclusionUserExemptOnly_Incorrect if { - PolicyId := "MS.AAD.3.1v1" + PolicyId := "MS.AAD.3.2v1" Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], - "ExcludeGroups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"], - "ExcludeRoles": [] - }, - "SignInRiskLevels": ["high"] - }, - "GrantControls": { - "BuiltInControls": ["block"] - }, - "State": "enabled", - "DisplayName": "Test name" - } - ], - "service_plans": [ - { - "ServicePlanName": "EXCHANGE_S_FOUNDATION", - "ServicePlanId": "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" - }, - { - "ServicePlanName": "AAD_PREMIUM_P2", - "ServicePlanId": "c7d91867-e1ce-4402-8d4f-22188b44b6c2" - } + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], + "ExcludeGroups" : ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"], + "ExcludeRoles" : [] + } + }, + "GrantControls" : { + "BuiltInControls" : ["mfa"] + }, + "State" : "enabled", + "DisplayName" : "Test name" + } ], - "scuba_config": { - "Aad": { - "Policy2_3_1": { - "CapExclusions": { - "Users": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], - "Groups": [] + "scuba_config" : { + "Aad" : { + "MS.AAD.3.2v1" : { + "CapExclusions" : { + "Users" : ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], + "Groups" : [] } } } } } + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 @@ -811,51 +654,41 @@ test_UserGroupExclusionUserExemptOnly_Incorrect if { } test_UserGroupExclusionGroupExemptOnly_Incorrect if { - PolicyId := "MS.AAD.3.1v1" + PolicyId := "MS.AAD.3.2v1" Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], - "ExcludeGroups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"], - "ExcludeRoles": [] - }, - "SignInRiskLevels": ["high"] - }, - "GrantControls": { - "BuiltInControls": ["block"] - }, - "State": "enabled", - "DisplayName": "Test name" - } - ], - "service_plans": [ - { - "ServicePlanName": "EXCHANGE_S_FOUNDATION", - "ServicePlanId": "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" - }, - { - "ServicePlanName": "AAD_PREMIUM_P2", - "ServicePlanId": "c7d91867-e1ce-4402-8d4f-22188b44b6c2" - } + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], + "ExcludeGroups" : ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"], + "ExcludeRoles" : [] + } + }, + "GrantControls" : { + "BuiltInControls" : ["mfa"] + }, + "State" : "enabled", + "DisplayName" : "Test name" + } ], - "scuba_config": { - "Aad": { - "Policy2_3_1": { - "CapExclusions": { - "Users": [], - "Groups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"] + "scuba_config" : { + "Aad" : { + "MS.AAD.3.2v1" : { + "CapExclusions" : { + "Users" : [], + "Groups" : ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"] } } } } } + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 @@ -864,51 +697,41 @@ test_UserGroupExclusionGroupExemptOnly_Incorrect if { } test_UserGroupExclusionTooFewUserExempts_Incorrect if { - PolicyId := "MS.AAD.3.1v1" + PolicyId := "MS.AAD.3.2v1" Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423", "65fea286-22d3-42f9-b4ca-93a6f75817d4"], - "ExcludeGroups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"], - "ExcludeRoles": [] - }, - "SignInRiskLevels": ["high"] - }, - "GrantControls": { - "BuiltInControls": ["block"] - }, - "State": "enabled", - "DisplayName": "Test name" - } - ], - "service_plans": [ - { - "ServicePlanName": "EXCHANGE_S_FOUNDATION", - "ServicePlanId": "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" - }, - { - "ServicePlanName": "AAD_PREMIUM_P2", - "ServicePlanId": "c7d91867-e1ce-4402-8d4f-22188b44b6c2" - } + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423", "65fea286-22d3-42f9-b4ca-93a6f75817d4"], + "ExcludeGroups" : ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"], + "ExcludeRoles" : [] + } + }, + "GrantControls" : { + "BuiltInControls" : ["mfa"] + }, + "State" : "enabled", + "DisplayName" : "Test name" + } ], - "scuba_config": { - "Aad": { - "Policy2_3_1": { - "CapExclusions": { - "Users": ["65fea286-22d3-42f9-b4ca-93a6f75817d4"], - "Groups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"] + "scuba_config" : { + "Aad" : { + "MS.AAD.3.2v1" : { + "CapExclusions" : { + "Users" : ["65fea286-22d3-42f9-b4ca-93a6f75817d4"], + "Groups" : ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"] } } } } } + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 @@ -916,41 +739,30 @@ test_UserGroupExclusionTooFewUserExempts_Incorrect if { RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." } -# Other Conditions -test_Conditions_Correct if { - PolicyId := "MS.AAD.3.1v1" +# Other conditions +test_ConditionalAccessPolicies_Correct_V1 if { + PolicyId := "MS.AAD.3.2v1" Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": [], - "ExcludeGroups": [], - "ExcludeRoles": [] + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : [], + "ExcludeGroups" : [], + "ExcludeRoles" : [] + } }, - "SignInRiskLevels": ["high"] - }, - "GrantControls": { - "BuiltInControls": ["block"] - }, - "State": "enabled", - "DisplayName": "Test name" - } - ], - "service_plans": [ - { - "ServicePlanName": "EXCHANGE_S_FOUNDATION", - "ServicePlanId": "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" - }, - { - "ServicePlanName": "AAD_PREMIUM_P2", - "ServicePlanId": "c7d91867-e1ce-4402-8d4f-22188b44b6c2" - } + "GrantControls" : { + "BuiltInControls" : ["mfa"] + }, + "State" : "enabled", + "DisplayName" : "Test Policy require MFA for All Users" + } ] } @@ -958,43 +770,32 @@ test_Conditions_Correct if { count(RuleOutput) == 1 RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "1 conditional access policy(s) found that meet(s) all requirements:
Test name. View all CA policies." + RuleOutput[0].ReportDetails == "1 conditional access policy(s) found that meet(s) all requirements:
Test Policy require MFA for All Users. View all CA policies." } -test_IncludeApplications_Incorrect if { - PolicyId := "MS.AAD.3.1v1" +test_IncludeApplications_Incorrect_V1 if { + PolicyId := "MS.AAD.3.2v1" Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["Office365"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": [], - "ExcludeGroups": [], - "ExcludeRoles": [] - }, - "SignInRiskLevels": ["high"] - }, - "GrantControls": { - "BuiltInControls": ["block"] - }, - "State": "enabled", - "DisplayName": "Test name" - } - ], - "service_plans": [ - { - "ServicePlanName": "EXCHANGE_S_FOUNDATION", - "ServicePlanId": "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" - }, - { - "ServicePlanName": "AAD_PREMIUM_P2", - "ServicePlanId": "c7d91867-e1ce-4402-8d4f-22188b44b6c2" - } + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["Office365"] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : [], + "ExcludeGroups" : [], + "ExcludeRoles" : [] + } + }, + "GrantControls" : { + "BuiltInControls" : ["mfa"] + }, + "State" : "enabled", + "DisplayName" : "Test Policy require MFA for All Users, but not all Apps" + } ] } @@ -1005,40 +806,29 @@ test_IncludeApplications_Incorrect if { RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." } -test_IncludeUsers_Incorrect if { - PolicyId := "MS.AAD.3.1v1" +test_IncludeUsers_Incorrect_V1 if { + PolicyId := "MS.AAD.3.2v1" Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["8bc7c6ee-39a2-42a5-a31b-f77fb51db652"], - "ExcludeUsers": [], - "ExcludeGroups": [], - "ExcludeRoles": [] - }, - "SignInRiskLevels": ["high"] - }, - "GrantControls": { - "BuiltInControls": ["block"] - }, - "State": "enabled", - "DisplayName": "Test name" - } - ], - "service_plans": [ - { - "ServicePlanName": "EXCHANGE_S_FOUNDATION", - "ServicePlanId": "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" - }, - { - "ServicePlanName": "AAD_PREMIUM_P2", - "ServicePlanId": "c7d91867-e1ce-4402-8d4f-22188b44b6c2" - } + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeUsers" : ["8bc7c6ee-39a2-42a5-a31b-f77fb51db652"], + "ExcludeUsers" : [], + "ExcludeGroups" : [], + "ExcludeRoles" : [] + } + }, + "GrantControls" : { + "BuiltInControls" : ["mfa"] + }, + "State" : "enabled", + "DisplayName" : "Test Policy require MFA for All Apps, but not All Users" + } ] } @@ -1050,39 +840,28 @@ test_IncludeUsers_Incorrect if { } test_ExcludeUsers_Incorrect if { - PolicyId := "MS.AAD.3.1v1" + PolicyId := "MS.AAD.3.2v1" Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": ["8bc7c6ee-39a2-42a5-a31b-f77fb51db652"], - "ExcludeGroups": [], - "ExcludeRoles": [] - }, - "SignInRiskLevels": ["high"] - }, - "GrantControls": { - "BuiltInControls": ["block"] - }, - "State": "enabled", - "DisplayName": "Test name" - } - ], - "service_plans": [ - { - "ServicePlanName": "EXCHANGE_S_FOUNDATION", - "ServicePlanId": "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" - }, - { - "ServicePlanName": "AAD_PREMIUM_P2", - "ServicePlanId": "c7d91867-e1ce-4402-8d4f-22188b44b6c2" - } + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : ["8bc7c6ee-39a2-42a5-a31b-f77fb51db652"], + "ExcludeGroups" : [], + "ExcludeRoles" : [] + } + }, + "GrantControls" : { + "BuiltInControls" : ["mfa"] + }, + "State" : "enabled", + "DisplayName" : "Test Policy require MFA for All Apps, but not All Users" + } ] } @@ -1094,40 +873,61 @@ test_ExcludeUsers_Incorrect if { } test_ExcludeGroups_Incorrect if { - PolicyId := "MS.AAD.3.1v1" + PolicyId := "MS.AAD.3.2v1" Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : [], + "ExcludeGroups" : ["8bc7c6ee-39a2-42a5-a31b-f77fb51db652"], + "ExcludeRoles" : [] + } }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": [], - "ExcludeGroups": ["8bc7c6ee-39a2-42a5-a31b-f77fb51db652"], - "ExcludeRoles": [] + "GrantControls" : { + "BuiltInControls" : ["mfa"] + }, + "State" : "enabled", + "DisplayName" : "Test Policy require MFA for All Apps, but not All Users" + } + ] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." +} + +test_ExcludeRoles_Incorrect_V1 if { + PolicyId := "MS.AAD.3.2v1" + Output := tests with input as { + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : [], + "ExcludeGroups" : [], + "ExcludeRoles" : ["8bc7c6ee-39a2-42a5-a31b-f77fb51db652"] + } }, - "SignInRiskLevels": ["high"] - }, - "GrantControls": { - "BuiltInControls": ["block"] - }, - "State": "enabled", - "DisplayName": "Test name" - } - ], - "service_plans": [ - { - "ServicePlanName": "EXCHANGE_S_FOUNDATION", - "ServicePlanId": "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" - }, - { - "ServicePlanName": "AAD_PREMIUM_P2", - "ServicePlanId": "c7d91867-e1ce-4402-8d4f-22188b44b6c2" - } + "GrantControls" : { + "BuiltInControls" : ["mfa"] + }, + "State" : "enabled", + "DisplayName" : "Test Policy require MFA for All Apps, but not All Users" + } ] } @@ -1138,41 +938,62 @@ test_ExcludeGroups_Incorrect if { RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." } -test_ExcludeRoles_Incorrect if { - PolicyId := "MS.AAD.3.1v1" +test_BuiltInControls_Incorrect_V1 if { + PolicyId := "MS.AAD.3.2v1" Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : [], + "ExcludeGroups" : [], + "ExcludeRoles" : [] + } + }, + "GrantControls" : { + "BuiltInControls" : [""] }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": [], - "ExcludeGroups": [], - "ExcludeRoles": ["8bc7c6ee-39a2-42a5-a31b-f77fb51db652"] + "State" : "enabled", + "DisplayName" : "Test Policy does not require MFA" + } + ] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." +} +test_State_Incorrect_V1 if { + PolicyId := "MS.AAD.3.2v1" + + Output := tests with input as { + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : [], + "ExcludeGroups" : [], + "ExcludeRoles" : [] + } }, - "SignInRiskLevels": ["high"] - }, - "GrantControls": { - "BuiltInControls": ["block"] - }, - "State": "enabled", - "DisplayName": "Test name" - } - ], - "service_plans": [ - { - "ServicePlanName": "EXCHANGE_S_FOUNDATION", - "ServicePlanId": "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" - }, - { - "ServicePlanName": "AAD_PREMIUM_P2", - "ServicePlanId": "c7d91867-e1ce-4402-8d4f-22188b44b6c2" - } + "GrantControls" : { + "BuiltInControls" : ["mfa"] + }, + "State" : "disabled", + "DisplayName" : "Test Policy is correct, but not enabled" + } ] } @@ -1182,41 +1003,172 @@ test_ExcludeRoles_Incorrect if { not RuleOutput[0].RequirementMet RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." } +#-- -test_SignInRiskLevels_Incorrect if { - PolicyId := "MS.AAD.3.1v1" +# +# MS.AAD.3.3v1 +#-- +test_NotImplemented_Correct_V2 if { + PolicyId := "MS.AAD.3.3v1" + + Output := tests with input as { } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == NotCheckedDetails(PolicyId) +} +#-- + +# +# MS.AAD.3.4v1 +#-- +test_NotImplemented_Correct_V3 if { + PolicyId := "MS.AAD.3.4v1" + + Output := tests with input as { } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == NotCheckedDetails(PolicyId) +} +#-- + +# +# MS.AAD.3.5v1 +#-- +test_NotImplemented_Correct_V4 if { + PolicyId := "MS.AAD.3.5v1" + + Output := tests with input as { } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == NotCheckedDetails(PolicyId) +} +#-- + +# +# MS.AAD.3.6v1 +#-- +test_ConditionalAccessPolicies_Correct_V2 if { + PolicyId := "MS.AAD.3.6v1" Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": [], - "ExcludeGroups": [], - "ExcludeRoles": [] - }, - "SignInRiskLevels": [""] + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeRoles" : ["Role1", "Role2" ], + "ExcludeRoles" : [] + } + }, + "GrantControls" : { + "BuiltInControls" : ["mfa"] + }, + "State" : "enabled", + "DisplayName" : "MFA required for all highly Privileged Roles Policy" + } + ], + "privileged_roles" : [ + { + "RoleTemplateId" : "Role1", + "DisplayName" : "Global Administrator" }, - "GrantControls": { - "BuiltInControls": ["block"] + { + "RoleTemplateId" : "Role2", + "DisplayName" : "Privileged Role Administrator" + } + ] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "1 conditional access policy(s) found that meet(s) all requirements:
MFA required for all highly Privileged Roles Policy. View all CA policies." +} + +test_IncludeApplications_Incorrect_V2 if { + PolicyId := "MS.AAD.3.6v1" + + Output := tests with input as { + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : [""] + }, + "Users" : { + "IncludeRoles" : ["Role1", "Role2" ], + "ExcludeRoles" : [] + } + }, + "GrantControls" : { + "BuiltInControls" : ["mfa"] + }, + "State" : "enabled", + "DisplayName" : {"MFA required for all highly Privileged Roles Policy"} + } + ], + "privileged_roles" : [ + { + "RoleTemplateId" : "Role1", + "DisplayName" : "Global Administrator" }, - "State": "enabled", - "DisplayName": "Test name" - } + { + "RoleTemplateId" : "Role2", + "DisplayName" : "Privileged Role Administrator" + } + ] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." +} + +test_BuiltInControls_Incorrect_V2 if { + PolicyId := "MS.AAD.3.6v1" + + Output := tests with input as { + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeRoles" : ["Role1", "Role2" ], + "ExcludeRoles" : [] + } + }, + "GrantControls" : { + "BuiltInControls" : [""] + }, + "State" : "enabled", + "DisplayName" : {"MFA required for all highly Privileged Roles Policy"} + } ], - "service_plans": [ - { - "ServicePlanName": "EXCHANGE_S_FOUNDATION", - "ServicePlanId": "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" - }, - { - "ServicePlanName": "AAD_PREMIUM_P2", - "ServicePlanId": "c7d91867-e1ce-4402-8d4f-22188b44b6c2" - } + "privileged_roles" : [ + { + "RoleTemplateId" : "Role1", + "DisplayName" : "Global Administrator" + }, + { + "RoleTemplateId" : "Role2", + "DisplayName" : "Privileged Role Administrator" + } ] } @@ -1227,40 +1179,115 @@ test_SignInRiskLevels_Incorrect if { RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." } -test_BuiltInControls_Incorrect if { - PolicyId := "MS.AAD.3.1v1" +test_State_Incorrect_V2 if { + PolicyId := "MS.AAD.3.6v1" Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": [], - "ExcludeGroups": [], - "ExcludeRoles": [] - }, - "SignInRiskLevels": ["high"] + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeRoles" : ["Role1", "Role2" ], + "ExcludeRoles" : [] + } + }, + "GrantControls" : { + "BuiltInControls" : ["mfa"] + }, + "State" : "disabled", + "DisplayName" : {"MFA required for all highly Privileged Roles Policy"} + } + ], + "privileged_roles" : [ + { + "RoleTemplateId" : "Role1", + "DisplayName" : "Global Administrator" }, - "GrantControls": { - "BuiltInControls": [""] + { + "RoleTemplateId" : "Role2", + "DisplayName" : "Privileged Role Administrator" + } + ] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." +} + +test_IncludeRoles_Incorrect_V1 if { + PolicyId := "MS.AAD.3.6v1" + + Output := tests with input as { + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeRoles" : ["Role1"], + "ExcludeRoles" : [] + } + }, + "GrantControls" : { + "BuiltInControls" : ["mfa"] + }, + "State" : "enabled", + "DisplayName" : {"MFA required for all highly Privileged Roles Policy"} + } + ], + "privileged_roles" : [ + { + "RoleTemplateId" : "Role1", + "DisplayName" : "Global Administrator" }, - "State": "enabled", - "DisplayName": "Test name" - } + { + "RoleTemplateId" : "Role2", + "DisplayName" : "Privileged Role Administrator" + } + ] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." +} + +test_IncludeRoles_Incorrect_V3 if { + PolicyId := "MS.AAD.3.6v1" + + Output := tests with input as { + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeRoles" : ["Role2"], + "ExcludeRoles" : [] + } + }, + "GrantControls" : { + "BuiltInControls" : ["mfa"] + }, + "State" : "enabled", + "DisplayName" : {"MFA required for all highly Privileged Roles Policy"} + } ], - "service_plans": [ - { - "ServicePlanName": "EXCHANGE_S_FOUNDATION", - "ServicePlanId": "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" - }, - { - "ServicePlanName": "AAD_PREMIUM_P2", - "ServicePlanId": "c7d91867-e1ce-4402-8d4f-22188b44b6c2" - } + "privileged_roles" : [ + { + "RoleTemplateId" : "Role1", + "DisplayName" : "Global Administrator" + } ] } @@ -1271,40 +1298,157 @@ test_BuiltInControls_Incorrect if { RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." } -test_State_Incorrect if { - PolicyId := "MS.AAD.3.1v1" +test_ExcludeRoles_Incorrect_V2 if { + PolicyId := "MS.AAD.3.6v1" Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": [], - "ExcludeGroups": [], - "ExcludeRoles": [] - }, - "SignInRiskLevels": ["high"] - }, - "GrantControls": { - "BuiltInControls": ["block"] - }, - "State": "disabled", - "DisplayName": "Test name" - } + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeRoles" : ["Role1", "Role2"], + "ExcludeRoles" : ["Role1"] + } + }, + "GrantControls" : { + "BuiltInControls" : ["mfa"] + }, + "State" : "enabled", + "DisplayName" : {"MFA required for all highly Privileged Roles Policy"} + } ], - "service_plans": [ - { - "ServicePlanName": "EXCHANGE_S_FOUNDATION", - "ServicePlanId": "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" - }, - { - "ServicePlanName": "AAD_PREMIUM_P2", - "ServicePlanId": "c7d91867-e1ce-4402-8d4f-22188b44b6c2" - } + "privileged_roles" : [ + { + "RoleTemplateId" : "Role1", + "DisplayName" : "Global Administrator" + } + ] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." +} +#-- + +# +# MS.AAD.3.7v1 +#-- +test_ConditionalAccessPolicies_Correct_V3 if { + PolicyId := "MS.AAD.3.7v1" + + Output := tests with input as { + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeUsers" : ["All"] + } + }, + "GrantControls" : { + "BuiltInControls" : ["domainJoinedDevice"] + }, + "State" : "enabled", + "DisplayName" : "AD Joined Device Authentication Policy" + } + ] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "1 conditional access policy(s) found that meet(s) all requirements:
AD Joined Device Authentication Policy. View all CA policies." +} + +test_BuiltInControls_Correct if { + PolicyId := "MS.AAD.3.7v1" + + Output := tests with input as { + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeUsers" : ["All"] + } + }, + "GrantControls" : { + "BuiltInControls" : ["compliantDevice"] + }, + "State" : "enabled", + "DisplayName" : "AD Joined Device Authentication Policy" + } + ] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "1 conditional access policy(s) found that meet(s) all requirements:
AD Joined Device Authentication Policy. View all CA policies." +} + +test_IncludeApplications_Incorrect_V3 if { + PolicyId := "MS.AAD.3.7v1" + + Output := tests with input as { + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : [""] + }, + "Users" : { + "IncludeUsers" : ["All"] + } + }, + "GrantControls" : { + "BuiltInControls" : ["compliantDevice"] + }, + "State" : "enabled", + "DisplayName" : "AD Joined Device Authentication Policy" + } + ] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." +} + +test_IncludeUsers_Incorrect_V2 if { + PolicyId := "MS.AAD.3.7v1" + + Output := tests with input as { + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeUsers" : [""] + } + }, + "GrantControls" : { + "BuiltInControls" : ["compliantDevice"] + }, + "State" : "enabled", + "DisplayName" : "AD Joined Device Authentication Policy" + } ] } @@ -1313,4 +1457,81 @@ test_State_Incorrect if { count(RuleOutput) == 1 not RuleOutput[0].RequirementMet RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." -} \ No newline at end of file +} + +test_BuiltInControls_Incorrect_V3 if { + PolicyId := "MS.AAD.3.7v1" + + Output := tests with input as { + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeUsers" : ["All"] + } + }, + "GrantControls" : { + "BuiltInControls" : [""] + }, + "State" : "enabled", + "DisplayName" : "AD Joined Device Authentication Policy" + } + ] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." +} + +test_State_Incorrect_V3 if { + PolicyId := "MS.AAD.3.7v1" + + Output := tests with input as { + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"] + }, + "Users" : { + "IncludeUsers" : ["All"] + } + }, + "GrantControls" : { + "BuiltInControls" : ["compliantDevice"] + }, + "State" : "disabled", + "DisplayName" : "AD Joined Device Authentication Policy" + } + ] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." +} +#-- + +# +# MS.AAD.3.8v1 +#-- +test_NotImplemented_Correct_V5 if { + PolicyId := "MS.AAD.3.8v1" + + Output := tests with input as { } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == NotCheckedDetails(PolicyId) +} +#-- \ No newline at end of file diff --git a/Testing/Unit/Rego/AAD/AADConfig_04_test.rego b/Testing/Unit/Rego/AAD/AADConfig_04_test.rego index d28d58ecca..4a0668fa58 100644 --- a/Testing/Unit/Rego/AAD/AADConfig_04_test.rego +++ b/Testing/Unit/Rego/AAD/AADConfig_04_test.rego @@ -3,1008 +3,11 @@ import future.keywords import data.report.utils.NotCheckedDetails # -# Policy 1 +# MS.AAD.4.1v1 #-- - -test_NoExclusionsConditions_Correct if { - PolicyId := "MS.AAD.4.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": [], - "ExcludeGroups": [], - "ExcludeRoles": [] - } - }, - "GrantControls": { - "BuiltInControls": ["mfa"] - }, - "State": "enabled", - "DisplayName": "Test name" - } - ] - } - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "1 conditional access policy(s) found that meet(s) all requirements:
Test name. View all CA policies." -} - -test_NoExclusionsExemptUsers_Correct if { - PolicyId := "MS.AAD.4.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": [], - "ExcludeGroups": [], - "ExcludeRoles": [] - } - }, - "GrantControls": { - "BuiltInControls": ["mfa"] - }, - "State": "enabled", - "DisplayName": "Test name" - } - ], - "scuba_config": { - "Aad": { - "Policy2_4_1": { - "CapExclusions": { - "Users": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], - "Groups": [] - } - } - - } - - } - } - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "1 conditional access policy(s) found that meet(s) all requirements:
Test name. View all CA policies." -} - -test_NoExclusionsExemptGroups_Correct if { - PolicyId := "MS.AAD.4.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": [], - "ExcludeGroups": [], - "ExcludeRoles": [] - } - }, - "GrantControls": { - "BuiltInControls": ["mfa"] - }, - "State": "enabled", - "DisplayName": "Test name" - } - ], - "scuba_config": { - "Aad": { - "Policy2_4_1": { - "CapExclusions": { - "Users": [], - "Groups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"] - } - } - - } - - } - } - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "1 conditional access policy(s) found that meet(s) all requirements:
Test name. View all CA policies." -} - -# User exclusions test -test_UserExclusionNoExempt_Incorrect if { - PolicyId := "MS.AAD.4.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], - "ExcludeGroups": [], - "ExcludeRoles": [] - } - }, - "GrantControls": { - "BuiltInControls": ["mfa"] - }, - "State": "enabled", - "DisplayName": "Test name" - } - ] - } - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." -} - -test_UserExclusionConditions_Correct if { - PolicyId := "MS.AAD.4.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], - "ExcludeGroups": [], - "ExcludeRoles": [] - } - }, - "GrantControls": { - "BuiltInControls": ["mfa"] - }, - "State": "enabled", - "DisplayName": "Test name" - } - ], - "scuba_config": { - "Aad": { - "Policy2_4_1": { - "CapExclusions": { - "Users": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], - "Groups": [] - } - } - - } - - } - } - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "1 conditional access policy(s) found that meet(s) all requirements:
Test name. View all CA policies." -} - -test_UserExclusionsNoExempt_Incorrect if { +test_NotImplemented_Correct if { PolicyId := "MS.AAD.4.1v1" - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3", "65fea286-22d3-42f9-b4ca-93a6f75817d4"], - "ExcludeGroups": [], - "ExcludeRoles": [] - } - }, - "GrantControls": { - "BuiltInControls": ["mfa"] - }, - "State": "enabled", - "DisplayName": "Test name" - } - ] - } - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." -} - -test_UserExclusionsSingleExempt_Incorrect if { - PolicyId := "MS.AAD.4.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3", "65fea286-22d3-42f9-b4ca-93a6f75817d4"], - "ExcludeGroups": [], - "ExcludeRoles": [] - } - }, - "GrantControls": { - "BuiltInControls": ["mfa"] - }, - "State": "enabled", - "DisplayName": "Test name" - } - ], - "scuba_config": { - "Aad": { - "Policy2_4_1": { - "CapExclusions": { - "Users": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], - "Groups": [] - } - } - - } - - } - } - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." -} - -test_MultiUserExclusionsConditions_Correct if { - PolicyId := "MS.AAD.4.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3", "65fea286-22d3-42f9-b4ca-93a6f75817d4"], - "ExcludeGroups": [], - "ExcludeRoles": [] - } - }, - "GrantControls": { - "BuiltInControls": ["mfa"] - }, - "State": "enabled", - "DisplayName": "Test name" - } - ], - "scuba_config": { - "Aad": { - "Policy2_4_1": { - "CapExclusions": { - "Users": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3", "65fea286-22d3-42f9-b4ca-93a6f75817d4"], - "Groups": [] - } - } - - } - - } - } - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "1 conditional access policy(s) found that meet(s) all requirements:
Test name. View all CA policies." -} - -# Group Exclusion tests -test_GroupExclusionNoExempt_Incorrect if { - PolicyId := "MS.AAD.4.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": [], - "ExcludeGroups": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], - "ExcludeRoles": [] - } - }, - "GrantControls": { - "BuiltInControls": ["mfa"] - }, - "State": "enabled", - "DisplayName": "Test name" - } - ] - } - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." -} - -test_GroupExclusionsConditions_Correct if { - PolicyId := "MS.AAD.4.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": [], - "ExcludeGroups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"], - "ExcludeRoles": [] - } - }, - "GrantControls": { - "BuiltInControls": ["mfa"] - }, - "State": "enabled", - "DisplayName": "Test name" - } - ], - "scuba_config": { - "Aad": { - "Policy2_4_1": { - "CapExclusions": { - "Users": [], - "Groups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"] - } - } - - } - } - } - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "1 conditional access policy(s) found that meet(s) all requirements:
Test name. View all CA policies." -} - -test_GroupExclusionsNoExempt_Incorrect if { - PolicyId := "MS.AAD.4.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": [], - "ExcludeGroups": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3", "65fea286-22d3-42f9-b4ca-93a6f75817d4"], - "ExcludeRoles": [] - } - }, - "GrantControls": { - "BuiltInControls": ["mfa"] - }, - "State": "enabled", - "DisplayName": "Test name" - } - ] - } - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." -} - -test_GroupExclusionsSingleExempt_Incorrect if { - PolicyId := "MS.AAD.4.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": [], - "ExcludeGroups": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3", "65fea286-22d3-42f9-b4ca-93a6f75817d4"], - "ExcludeRoles": [] - } - }, - "GrantControls": { - "BuiltInControls": ["mfa"] - }, - "State": "enabled", - "DisplayName": "Test name" - } - ], - "scuba_config": { - "Aad": { - "Policy2_4_1": { - "CapExclusions": { - "Users": [], - "Groups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"] - } - } - - } - } - } - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." -} - -test_MultiGroupExclusionsConditions_Correct if { - PolicyId := "MS.AAD.4.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": [], - "ExcludeGroups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423", "65fea286-22d3-42f9-b4ca-93a6f75817d4"], - "ExcludeRoles": [] - } - }, - "GrantControls": { - "BuiltInControls": ["mfa"] - }, - "State": "enabled", - "DisplayName": "Test name" - } - ], - "scuba_config": { - "Aad": { - "Policy2_4_1": { - "CapExclusions": { - "Users": [], - "Groups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423", "65fea286-22d3-42f9-b4ca-93a6f75817d4"] - } - } - - } - } - } - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "1 conditional access policy(s) found that meet(s) all requirements:
Test name. View all CA policies." -} - -# User and group exclusions tests -test_UserGroupExclusionConditions_Correct if { - PolicyId := "MS.AAD.4.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], - "ExcludeGroups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"], - "ExcludeRoles": [] - } - }, - "GrantControls": { - "BuiltInControls": ["mfa"] - }, - "State": "enabled", - "DisplayName": "Test name" - } - ], - "scuba_config": { - "Aad": { - "Policy2_4_1": { - "CapExclusions": { - "Users": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], - "Groups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"] - } - } - } - } - } - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "1 conditional access policy(s) found that meet(s) all requirements:
Test name. View all CA policies." -} - -test_UserGroupExclusionNoExempt_Incorrect if { - PolicyId := "MS.AAD.4.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], - "ExcludeGroups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"], - "ExcludeRoles": [] - } - }, - "GrantControls": { - "BuiltInControls": ["mfa"] - }, - "State": "enabled", - "DisplayName": "Test name" - } - ] - } - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." -} - -test_UserGroupExclusionUserExemptOnly_Incorrect if { - PolicyId := "MS.AAD.4.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], - "ExcludeGroups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"], - "ExcludeRoles": [] - } - }, - "GrantControls": { - "BuiltInControls": ["mfa"] - }, - "State": "enabled", - "DisplayName": "Test name" - } - ], - "scuba_config": { - "Aad": { - "Policy2_4_1": { - "CapExclusions": { - "Users": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], - "Groups": [] - } - } - } - } - } - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." -} - -test_UserGroupExclusionGroupExemptOnly_Incorrect if { - PolicyId := "MS.AAD.4.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], - "ExcludeGroups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"], - "ExcludeRoles": [] - } - }, - "GrantControls": { - "BuiltInControls": ["mfa"] - }, - "State": "enabled", - "DisplayName": "Test name" - } - ], - "scuba_config": { - "Aad": { - "Policy2_4_1": { - "CapExclusions": { - "Users": [], - "Groups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"] - } - } - } - } - } - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." -} - -test_UserGroupExclusionTooFewUserExempts_Incorrect if { - PolicyId := "MS.AAD.4.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423", "65fea286-22d3-42f9-b4ca-93a6f75817d4"], - "ExcludeGroups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"], - "ExcludeRoles": [] - } - }, - "GrantControls": { - "BuiltInControls": ["mfa"] - }, - "State": "enabled", - "DisplayName": "Test name" - } - ], - "scuba_config": { - "Aad": { - "Policy2_4_1": { - "CapExclusions": { - "Users": ["65fea286-22d3-42f9-b4ca-93a6f75817d4"], - "Groups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"] - } - } - } - } - } - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." -} - -# Other conditions -test_ConditionalAccessPolicies_Correct if { - PolicyId := "MS.AAD.4.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": [], - "ExcludeGroups": [], - "ExcludeRoles": [] - } - }, - "GrantControls": { - "BuiltInControls": ["mfa"] - }, - "State": "enabled", - "DisplayName": "Test Policy require MFA for All Users" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput)>= 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "1 conditional access policy(s) found that meet(s) all requirements:
Test Policy require MFA for All Users. View all CA policies." -} - -test_IncludeApplications_Incorrect if { - PolicyId := "MS.AAD.4.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["Office365"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": [], - "ExcludeGroups": [], - "ExcludeRoles": [] - } - }, - "GrantControls": { - "BuiltInControls": ["mfa"] - }, - "State": "enabled", - "DisplayName": "Test Policy require MFA for All Users, but not all Apps" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." -} - -test_IncludeUsers_Incorrect if { - PolicyId := "MS.AAD.4.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["8bc7c6ee-39a2-42a5-a31b-f77fb51db652"], - "ExcludeUsers": [], - "ExcludeGroups": [], - "ExcludeRoles": [] - } - }, - "GrantControls": { - "BuiltInControls": ["mfa"] - }, - "State": "enabled", - "DisplayName": "Test Policy require MFA for All Apps, but not All Users" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." -} - -test_ExcludeUsers_Incorrect if { - PolicyId := "MS.AAD.4.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": ["8bc7c6ee-39a2-42a5-a31b-f77fb51db652"], - "ExcludeGroups": [], - "ExcludeRoles": [] - } - }, - "GrantControls": { - "BuiltInControls": ["mfa"] - }, - "State": "enabled", - "DisplayName": "Test Policy require MFA for All Apps, but not All Users" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." -} - -test_ExcludeGroups_Incorrect if { - PolicyId := "MS.AAD.4.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": [], - "ExcludeGroups": ["8bc7c6ee-39a2-42a5-a31b-f77fb51db652"], - "ExcludeRoles": [] - } - }, - "GrantControls": { - "BuiltInControls": ["mfa"] - }, - "State": "enabled", - "DisplayName": "Test Policy require MFA for All Apps, but not All Users" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." -} - -test_ExcludeRoles_Incorrect if { - PolicyId := "MS.AAD.4.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": [], - "ExcludeGroups": [], - "ExcludeRoles": ["8bc7c6ee-39a2-42a5-a31b-f77fb51db652"] - } - }, - "GrantControls": { - "BuiltInControls": ["mfa"] - }, - "State": "enabled", - "DisplayName": "Test Policy require MFA for All Apps, but not All Users" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." -} - -test_BuiltInControls_Incorrect if { - PolicyId := "MS.AAD.4.1v1" - - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": [], - "ExcludeGroups": [], - "ExcludeRoles": [] - } - }, - "GrantControls": { - "BuiltInControls": [""] - }, - "State": "enabled", - "DisplayName": "Test Policy does not require MFA" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." -} - -test_State_Incorrect if { - PolicyId := "MS.AAD.4.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": [], - "ExcludeGroups": [], - "ExcludeRoles": [] - } - }, - "GrantControls": { - "BuiltInControls": ["mfa"] - }, - "State": "disabled", - "DisplayName": "Test Policy is correct, but not enabled" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." -} - -# -# Policy 2 -#-- -test_NotImplemented_Correct_V1 if { - PolicyId := "MS.AAD.4.2v1" - - Output := tests with input as { } - - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == NotCheckedDetails(PolicyId) -} - -# -# Policy 3 -#-- -test_NotImplemented_Correct_V2 if { - PolicyId := "MS.AAD.4.3v1" - Output := tests with input as { } RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] @@ -1013,18 +16,4 @@ test_NotImplemented_Correct_V2 if { not RuleOutput[0].RequirementMet RuleOutput[0].ReportDetails == NotCheckedDetails(PolicyId) } - -# -# Policy 4 -#-- -test_NotImplemented_Correct_V3 if { - PolicyId := "MS.AAD.4.4v1" - - Output := tests with input as { } - - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == NotCheckedDetails(PolicyId) -} \ No newline at end of file +#-- \ No newline at end of file diff --git a/Testing/Unit/Rego/AAD/AADConfig_05_test.rego b/Testing/Unit/Rego/AAD/AADConfig_05_test.rego index a6dc3b0e18..23e65f312d 100644 --- a/Testing/Unit/Rego/AAD/AADConfig_05_test.rego +++ b/Testing/Unit/Rego/AAD/AADConfig_05_test.rego @@ -1,29 +1,234 @@ package aad import future.keywords -import data.report.utils.NotCheckedDetails +# +# MS.AAD.5.1v1 #-- -test_NotImplemented_Correct_V1 if { +test_AllowedToCreateApps_Correct if { PolicyId := "MS.AAD.5.1v1" - Output := tests with input as { } + Output := tests with input as { + "authorization_policies" : [ + { + "DefaultUserRolePermissions" : { + "AllowedToCreateApps" : false + }, + "Id" : "authorizationPolicy" + } + ] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "0 authorization policies found that allow non-admin users to register third-party applications" +} + +test_AllowedToCreateApps_Incorrect_V1 if { + PolicyId := "MS.AAD.5.1v1" + + Output := tests with input as { + "authorization_policies" : [ + { + "DefaultUserRolePermissions" : { + "AllowedToCreateApps" : true + }, + "Id" : "Bad policy" + } + ] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "1 authorization policies found that allow non-admin users to register third-party applications:
Bad policy" +} + +test_AllowedToCreateApps_Incorrect_V2 if { + PolicyId := "MS.AAD.5.1v1" + + Output := tests with input as { + "authorization_policies" : [ + { + "DefaultUserRolePermissions" : { + "AllowedToCreateApps" : true + }, + "Id" : "Bad policy" + }, + { + "DefaultUserRolePermissions" : { + "AllowedToCreateApps" : false + }, + "Id" : "Good policy" + } + ] + } RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == NotCheckedDetails(PolicyId) + RuleOutput[0].ReportDetails == "1 authorization policies found that allow non-admin users to register third-party applications:
Bad policy" } +#-- +# +# MS.AAD.5.2v1 #-- -test_NotImplemented_Correct_V2 if { +test_PermissionGrantPolicyIdsAssignedToDefaultUserRole_Correct if { + PolicyId := "MS.AAD.5.2v1" + + Output := tests with input as { + "authorization_policies" : [ + { + "PermissionGrantPolicyIdsAssignedToDefaultUserRole" : [], + "Id" : "authorizationPolicy" + } + ] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "0 authorization policies found that allow non-admin users to consent to third-party applications" +} + +test_PermissionGrantPolicyIdsAssignedToDefaultUserRole_Incorrect_V1 if { + PolicyId := "MS.AAD.5.2v1" + + Output := tests with input as { + "authorization_policies" : [ + { + "PermissionGrantPolicyIdsAssignedToDefaultUserRole" : ["Test user"], + "Id" : "authorizationPolicy" + } + ] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "1 authorization policies found that allow non-admin users to consent to third-party applications:
authorizationPolicy" +} + +test_PermissionGrantPolicyIdsAssignedToDefaultUserRole_Incorrect_V2 if { + PolicyId := "MS.AAD.5.2v1" + + Output := tests with input as { + "authorization_policies" : [ + { + "PermissionGrantPolicyIdsAssignedToDefaultUserRole" : [], + "Id" : "Good policy" + }, + { + "PermissionGrantPolicyIdsAssignedToDefaultUserRole" : ["Test user"], + "Id" : "Bad policy" + } + ] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "1 authorization policies found that allow non-admin users to consent to third-party applications:
Bad policy" +} +#-- + +# +# MS.AAD.5.3v1 +#-- +test_IsEnabled_Correct if { + PolicyId := "MS.AAD.5.3v1" + + Output := tests with input as { + "admin_consent_policies" : [ + { + "IsEnabled" : true, + "Id" : "policy ID" + } + ] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "Requirement met" +} + +test_IsEnabled_Incorrect if { + PolicyId := "MS.AAD.5.3v1" + + Output := tests with input as { + "admin_consent_policies" : [ + { + "IsEnabled" : false, + "Id" : null + } + ] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "Requirement not met" +} +#-- + +# +# MS.AAD.5.4v1 +#-- +test_Value_Correct if { PolicyId := "MS.AAD.5.4v1" - Output := tests with input as { } + Output := tests with input as { + "directory_settings" : [ + { + "DisplayName" : "Setting display name", + "Values" : [ + { + "Name" : "EnableGroupSpecificConsent", + "Value" : "false" + } + ] + } + ] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "Requirement met" +} + +test_Value_Incorrect if { + PolicyId := "MS.AAD.5.4v1" + + Output := tests with input as { + "directory_settings" : [ + { + "DisplayName" : "Setting display name", + "Values" : [ + { + "Name" : "EnableGroupSpecificConsent", + "Value" : "true" + } + ] + } + ] + } RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == NotCheckedDetails(PolicyId) -} \ No newline at end of file + RuleOutput[0].ReportDetails == "Requirement not met" +} +#-- \ No newline at end of file diff --git a/Testing/Unit/Rego/AAD/AADConfig_06_test.rego b/Testing/Unit/Rego/AAD/AADConfig_06_test.rego index 77b3ed12c7..1c557b7d01 100644 --- a/Testing/Unit/Rego/AAD/AADConfig_06_test.rego +++ b/Testing/Unit/Rego/AAD/AADConfig_06_test.rego @@ -1,78 +1,20 @@ package aad import future.keywords +import data.report.utils.NotCheckedDetails # -# Policy 1 +# MS.AAD.6.1v1 #-- -test_AllowedToCreateApps_Correct if { +test_NotImplemented_Correct if { PolicyId := "MS.AAD.6.1v1" - Output := tests with input as { - "authorization_policies": [ - { - "DefaultUserRolePermissions": { - "AllowedToCreateApps": false - }, - "Id": "authorizationPolicy" - } - ] - } - - # filter for just the output produced by the specific rule by - # checking 1) the control number and 2) the requirement string - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - # Each rule should produce exactly 1 line of output in the report - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "0 authorization policies found that allow non-admin users to register third-party applications" -} - -test_AllowedToCreateApps_Incorrect_V1 if { - PolicyId := "MS.AAD.6.1v1" - - Output := tests with input as { - "authorization_policies": [ - { - "DefaultUserRolePermissions": { - "AllowedToCreateApps": true - }, - "Id": "Bad policy" - } - ] - } + Output := tests with input as { } RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "1 authorization policies found that allow non-admin users to register third-party applications:
Bad policy" + RuleOutput[0].ReportDetails == NotCheckedDetails(PolicyId) } - -test_AllowedToCreateApps_Incorrect_V2 if { - PolicyId := "MS.AAD.6.1v1" - - Output := tests with input as { - "authorization_policies": [ - { - "DefaultUserRolePermissions": { - "AllowedToCreateApps": true - }, - "Id": "Bad policy" - }, - { - "DefaultUserRolePermissions": { - "AllowedToCreateApps": false - }, - "Id": "Good policy" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "1 authorization policies found that allow non-admin users to register third-party applications:
Bad policy" -} \ No newline at end of file +#-- \ No newline at end of file diff --git a/Testing/Unit/Rego/AAD/AADConfig_07_test.rego b/Testing/Unit/Rego/AAD/AADConfig_07_test.rego index 2084cff188..35d6c7d911 100644 --- a/Testing/Unit/Rego/AAD/AADConfig_07_test.rego +++ b/Testing/Unit/Rego/AAD/AADConfig_07_test.rego @@ -1,18 +1,221 @@ package aad import future.keywords +import data.report.utils.NotCheckedDetails # -# Policy 1 +# MS.AAD.7.1v1 #-- -test_PermissionGrantPolicyIdsAssignedToDefaultUserRole_Correct if { +test_PrivilegedUsers_Correct if { PolicyId := "MS.AAD.7.1v1" Output := tests with input as { - "authorization_policies": [ + "privileged_users" : { + "User1" : { + "DisplayName" : "Test Name1", + "roles" : ["Privileged Role Administrator", "Global Administrator"] + }, + "User2" : { + "DisplayName" : "Test Name2", + "roles" : ["Global Administrator"] + } + } + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "2 global admin(s) found:
Test Name1, Test Name2" +} + +test_PrivilegedUsers_Incorrect_V1 if { + PolicyId := "MS.AAD.7.1v1" + + Output := tests with input as { + "privileged_users" : { + "User1" : { + "DisplayName" : "Test Name1", + "roles" : ["Privileged Role Administrator", "Global Administrator"] + } + } + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "1 global admin(s) found:
Test Name1" +} + +test_PrivilegedUsers_Incorrect_V2 if { + PolicyId := "MS.AAD.7.1v1" + + Output := tests with input as { + "privileged_users" : { + "User1" : { + "DisplayName" : "Test Name1", + "roles" : ["Privileged Role Administrator", "Global Administrator"] + }, + "User2" : { + "DisplayName" : "Test Name2", + "roles" : ["Global Administrator"] + }, + "User3" : { + "DisplayName" : "Test Name3", + "roles" : ["Global Administrator"] + }, + "User4" : { + "DisplayName" : "Test Name4", + "roles" : ["Global Administrator"] + }, + "User5" : { + "DisplayName" : "Test Name5", + "roles" : ["Global Administrator"] + }, + "User6" : { + "DisplayName" : "Test Name6", + "roles" : ["Global Administrator"] + }, + "User7" : { + "DisplayName" : "Test Name7", + "roles" : ["Global Administrator"] + }, + "User8" : { + "DisplayName" : "Test Name8", + "roles" : ["Global Administrator"] + }, + "User9" : { + "DisplayName" : "Test Name9", + "roles" : ["Global Administrator"] + } + } + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "9 global admin(s) found:
Test Name1, Test Name2, Test Name3, Test Name4, Test Name5, Test Name6, Test Name7, Test Name8, Test Name9" +} +#-- + +# +# MS.AAD.7.2v1 +#-- +test_NotImplemented_Correct if { + PolicyId := "MS.AAD.7.2v1" + + Output := tests with input as { } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == NotCheckedDetails(PolicyId) +} +#-- + +# +# MS.AAD.7.3v1 +#-- +test_OnPremisesImmutableId_Correct if { + PolicyId := "MS.AAD.7.3v1" + + Output := tests with input as { + "privileged_users" : { + "User1" : { + "DisplayName" : "Alice", + "OnPremisesImmutableId" : null, + "roles" : ["Privileged Role Administrator", "Global Administrator"] + }, + "User2" : { + "DisplayName" : "Bob", + "OnPremisesImmutableId" : null, + "roles" : ["Global Administrator"] + } + } + } + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "0 admin(s) that are not cloud-only found" +} + +test_OnPremisesImmutableId_Incorrect_V1 if { + PolicyId := "MS.AAD.7.3v1" + + Output := tests with input as { + "privileged_users" : { + "User1" : { + "DisplayName" : "Alice", + "OnPremisesImmutableId" : "HelloWorld", + "roles" : ["Privileged Role Administrator", "Global Administrator"] + } + } + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "1 admin(s) that are not cloud-only found:
Alice" +} + +test_OnPremisesImmutableId_Incorrect_V2 if { + PolicyId := "MS.AAD.7.3v1" + + Output := tests with input as { + "privileged_users" : { + "User1" : { + "DisplayName" : "Alice", + "OnPremisesImmutableId" : "HelloWorld", + "roles" : ["Privileged Role Administrator", "Global Administrator"] + }, + "User2" : { + "DisplayName" : "Bob", + "OnPremisesImmutableId" : null, + "roles" : ["Global Administrator"] + } + } + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "1 admin(s) that are not cloud-only found:
Alice" +} +#-- + +# +# MS.AAD.7.4v1 +#-- +test_AdditionalProperties_Correct_V1 if { + PolicyId := "MS.AAD.7.4v1" + + Output := tests with input as { + "privileged_roles" : [ { - "PermissionGrantPolicyIdsAssignedToDefaultUserRole": [], - "Id": "authorizationPolicy" + "DisplayName" : "Global Administrator", + "Rules" : [ + { + "Id" : "Expiration_Admin_Assignment", + "AdditionalProperties" : { + "isExpirationRequired" : true, + "maximumDuration" : "P15D" + } + } + ] + } + ], + "service_plans" : [ + { "ServicePlanName" : "EXCHANGE_S_FOUNDATION", + "ServicePlanId" : "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" + }, + { "ServicePlanName" : "AAD_PREMIUM_P2", + "ServicePlanId" : "c7d91867-e1ce-4402-8d4f-22188b44b6c2" } ] } @@ -21,63 +224,273 @@ test_PermissionGrantPolicyIdsAssignedToDefaultUserRole_Correct if { count(RuleOutput) == 1 RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "0 authorization policies found that allow non-admin users to consent to third-party applications" + RuleOutput[0].ReportDetails == "0 role(s) configured to allow permanent active assignment or expiration period too long" } -test_PermissionGrantPolicyIdsAssignedToDefaultUserRole_Incorrect_V1 if { - PolicyId := "MS.AAD.7.1v1" +test_AdditionalProperties_Incorrect_V1 if { + PolicyId := "MS.AAD.7.4v1" Output := tests with input as { - "authorization_policies": [ + "privileged_roles" : [ { - "PermissionGrantPolicyIdsAssignedToDefaultUserRole": ["Test user"], - "Id": "authorizationPolicy" + "DisplayName" : "Global Administrator", + "Rules" : [ + { + "Id" : "Expiration_Admin_Assignment", + "AdditionalProperties" : { + "isExpirationRequired" : false, + "maximumDuration" : "P30D" + } + } + ] + } + ], + "service_plans" : [ + { "ServicePlanName" : "EXCHANGE_S_FOUNDATION", + "ServicePlanId" : "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" + }, + { "ServicePlanName" : "AAD_PREMIUM_P2", + "ServicePlanId" : "c7d91867-e1ce-4402-8d4f-22188b44b6c2" } ] } RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - print(RuleOutput) + count(RuleOutput) == 1 not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "1 authorization policies found that allow non-admin users to consent to third-party applications:
authorizationPolicy" + RuleOutput[0].ReportDetails == "1 role(s) configured to allow permanent active assignment or expiration period too long:
Global Administrator" } -test_PermissionGrantPolicyIdsAssignedToDefaultUserRole_Incorrect_V2 if { - PolicyId := "MS.AAD.7.1v1" +test_AdditionalProperties_Incorrect_V2 if { + PolicyId := "MS.AAD.7.4v1" + + Output := tests with input as { + "privileged_roles" : [ + { + "DisplayName" : "Global Administrator", + "Rules" : [ + { + "Id" : "Expiration_Admin_Assignment", + "AdditionalProperties" : { + "isExpirationRequired" : true, + "maximumDuration" : "P30D" + } + } + ] + } + ], + "service_plans" : [ + { "ServicePlanName" : "EXCHANGE_S_FOUNDATION", + "ServicePlanId" : "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" + }, + { "ServicePlanName" : "AAD_PREMIUM_P2", + "ServicePlanId" : "c7d91867-e1ce-4402-8d4f-22188b44b6c2" + } + ] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "1 role(s) configured to allow permanent active assignment or expiration period too long:
Global Administrator" +} +#-- + +# +# MS.AAD.7.5v1 +#-- +test_Assignments_Correct if { + PolicyId := "MS.AAD.7.5v1" Output := tests with input as { - "authorization_policies": [ + "privileged_roles" : [ { - "PermissionGrantPolicyIdsAssignedToDefaultUserRole": [], - "Id": "Good policy" + "DisplayName" : "Global Administrator", + "Assignments" : [ + { + "StartDateTime" : "/Date(1660328610000)/" + } + ], + "Rules" : [ + { + "Id" : "Expiration_Admin_Assignment", + "AdditionalProperties" : { + "isExpirationRequired" : true, + "maximumDuration" : "P30D" + } + } + ] + } + ], + "service_plans" : [ + { "ServicePlanName" : "EXCHANGE_S_FOUNDATION", + "ServicePlanId" : "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" }, + { "ServicePlanName" : "AAD_PREMIUM_P2", + "ServicePlanId" : "c7d91867-e1ce-4402-8d4f-22188b44b6c2" + } + ] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "0 role(s) assigned to users outside of PIM" +} + +test_Assignments_Incorrect if { + PolicyId := "MS.AAD.7.5v1" + + Output := tests with input as { + "privileged_roles" : [ { - "PermissionGrantPolicyIdsAssignedToDefaultUserRole": ["Test user"], - "Id": "Bad policy" + "DisplayName" : "Global Administrator", + "Assignments" : [ + { + "StartDateTime" : null + } + ], + "Rules" : [ + { + "Id" : "Expiration_Admin_Assignment", + "AdditionalProperties" : { + "isExpirationRequired" : true, + "maximumDuration" : "P30D" + } + } + ] + } + ], + "service_plans" : [ + { "ServicePlanName" : "EXCHANGE_S_FOUNDATION", + "ServicePlanId" : "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" + }, + { "ServicePlanName" : "AAD_PREMIUM_P2", + "ServicePlanId" : "c7d91867-e1ce-4402-8d4f-22188b44b6c2" } ] } RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - print(RuleOutput) + count(RuleOutput) == 1 not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "1 authorization policies found that allow non-admin users to consent to third-party applications:
Bad policy" + RuleOutput[0].ReportDetails == "1 role(s) assigned to users outside of PIM:
Global Administrator" } +#-- +# +# MS.AAD.7.6v1 +#-- +test_AdditionalProperties_Correct_V2 if { + PolicyId := "MS.AAD.7.6v1" + + Output := tests with input as { + "privileged_roles" : [ + { + "DisplayName" : "Global Administrator", + "Rules" : [ + { + "Id" : "Approval_EndUser_Assignment", + "AdditionalProperties" : { + "setting" : { + "isApprovalRequired" : true + } + } + } + ] + } + ], + "service_plans" : [ + { "ServicePlanName" : "EXCHANGE_S_FOUNDATION", + "ServicePlanId" : "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" + }, + { "ServicePlanName" : "AAD_PREMIUM_P2", + "ServicePlanId" : "c7d91867-e1ce-4402-8d4f-22188b44b6c2" + } + ] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "0 role(s) that do not require approval to activate found" +} + +test_AdditionalProperties_Incorrect_V3 if { + PolicyId := "MS.AAD.7.6v1" + + Output := tests with input as { + "privileged_roles" : [ + { + "DisplayName" : "Global Administrator", + "Rules" : [ + { + "Id" : "Approval_EndUser_Assignment", + "AdditionalProperties" : { + "setting" : { + "isApprovalRequired" : false + } + } + } + ] + } + ], + "service_plans" : [ + { "ServicePlanName" : "EXCHANGE_S_FOUNDATION", + "ServicePlanId" : "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" + }, + { "ServicePlanName" : "AAD_PREMIUM_P2", + "ServicePlanId" : "c7d91867-e1ce-4402-8d4f-22188b44b6c2" + } + ] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "1 role(s) that do not require approval to activate found:
Global Administrator" +} +#-- # -# Policy 2 +# MS.AAD.7.7v1 #-- -test_IsEnabled_Correct if { - PolicyId := "MS.AAD.7.2v1" +test_notificationRecipients_Correct if { + PolicyId := "MS.AAD.7.7v1" Output := tests with input as { - "admin_consent_policies": [ + "privileged_roles" : [ { - "IsEnabled" : true, - "Id": "policy ID" + "RoleTemplateId" : "1D2EE3F0-90D3-4764-8AF8-BE81FE9D4D71", + "DisplayName" : "Global Administrator", + "Rules" : [ + { + "Id" : "Notification_Admin_Admin_Assignment", + "AdditionalProperties" : { + "notificationRecipients" : ["test@example.com"] + } + }, + { + "Id" : "Notification_Admin_Admin_Eligibility", + "AdditionalProperties" : { + "notificationRecipients" : ["test@example.com"] + } + } + ] + } + ], + "service_plans" : [ + { "ServicePlanName" : "EXCHANGE_S_FOUNDATION", + "ServicePlanId" : "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" + }, + { "ServicePlanName" : "AAD_PREMIUM_P2", + "ServicePlanId" : "c7d91867-e1ce-4402-8d4f-22188b44b6c2" } ] } @@ -86,17 +499,39 @@ test_IsEnabled_Correct if { count(RuleOutput) == 1 RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" + RuleOutput[0].ReportDetails == "0 role(s) without notification e-mail configured for role assignments found" } -test_IsEnabled_Incorrect if { - PolicyId := "MS.AAD.7.2v1" +test_notificationRecipients_Incorrect_V1 if { + PolicyId := "MS.AAD.7.7v1" Output := tests with input as { - "admin_consent_policies": [ + "privileged_roles" : [ { - "IsEnabled" : false, - "Id": null + "RoleTemplateId" : "1D2EE3F0-90D3-4764-8AF8-BE81FE9D4D71", + "DisplayName" : "Global Administrator", + "Rules" : [ + { + "Id" : "Notification_Admin_Admin_Assignment", + "AdditionalProperties" : { + "notificationRecipients" : [] + } + }, + { + "Id" : "Notification_Admin_Admin_Eligibility", + "AdditionalProperties" : { + "notificationRecipients" : ["test@example.com"] + } + } + ] + } + ], + "service_plans" : [ + { "ServicePlanName" : "EXCHANGE_S_FOUNDATION", + "ServicePlanId" : "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" + }, + { "ServicePlanName" : "AAD_PREMIUM_P2", + "ServicePlanId" : "c7d91867-e1ce-4402-8d4f-22188b44b6c2" } ] } @@ -105,26 +540,121 @@ test_IsEnabled_Incorrect if { count(RuleOutput) == 1 not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement not met" + RuleOutput[0].ReportDetails == "1 role(s) without notification e-mail configured for role assignments found:
Global Administrator" +} + +test_notificationRecipients_Incorrect_V2 if { + PolicyId := "MS.AAD.7.7v1" + + Output := tests with input as { + "privileged_roles" : [ + { + "RoleTemplateId" : "1D2EE3F0-90D3-4764-8AF8-BE81FE9D4D71", + "DisplayName" : "Global Administrator", + "Rules" : [ + { + "Id" : "Notification_Admin_Admin_Assignment", + "AdditionalProperties" : { + "notificationRecipients" : ["test@example.com"] + } + }, + { + "Id" : "Notification_Admin_Admin_Eligibility", + "AdditionalProperties" : { + "notificationRecipients" : [] + } + } + ] + } + ], + "service_plans" : [ + { "ServicePlanName" : "EXCHANGE_S_FOUNDATION", + "ServicePlanId" : "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" + }, + { "ServicePlanName" : "AAD_PREMIUM_P2", + "ServicePlanId" : "c7d91867-e1ce-4402-8d4f-22188b44b6c2" + } + ] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "1 role(s) without notification e-mail configured for role assignments found:
Global Administrator" } +test_notificationRecipients_Incorrect_V3 if { + PolicyId := "MS.AAD.7.7v1" + + Output := tests with input as { + "privileged_roles" : [ + { + "RoleTemplateId" : "1D2EE3F0-90D3-4764-8AF8-BE81FE9D4D71", + "DisplayName" : "Global Administrator", + "Rules" : [ + { + "Id" : "Notification_Admin_Admin_Assignment", + "AdditionalProperties" : { + "notificationRecipients" : [] + } + }, + { + "Id" : "Notification_Admin_Admin_Eligibility", + "AdditionalProperties" : { + "notificationRecipients" : [] + } + } + ] + } + ], + "service_plans" : [ + { "ServicePlanName" : "EXCHANGE_S_FOUNDATION", + "ServicePlanId" : "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" + }, + { "ServicePlanName" : "AAD_PREMIUM_P2", + "ServicePlanId" : "c7d91867-e1ce-4402-8d4f-22188b44b6c2" + } + ] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "1 role(s) without notification e-mail configured for role assignments found:
Global Administrator" +} +#-- + # -# Policy 3 +# MS.AAD.7.8v1 #-- -test_Value_Correct if { - PolicyId := "MS.AAD.7.3v1" +test_Id_Correct_V1 if { + PolicyId := "MS.AAD.7.8v1" Output := tests with input as { - "directory_settings": [ + "privileged_roles" : [ { - "DisplayName" : "Setting display name", - "Values" : [ + "RoleTemplateId" : "1D2EE3F0-90D3-4764-8AF8-BE81FE9D4D71", + "DisplayName" : "Global Administrator", + "Rules" : [ { - "Name" : "EnableGroupSpecificConsent", - "Value" : "false" + "Id" : "Notification_Admin_EndUser_Assignment", + "AdditionalProperties" : { + "notificationType" : "Email", + "notificationRecipients" : ["test@example.com"] + } } ] } + ], + "service_plans" : [ + { "ServicePlanName" : "EXCHANGE_S_FOUNDATION", + "ServicePlanId" : "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" + }, + { "ServicePlanName" : "AAD_PREMIUM_P2", + "ServicePlanId" : "c7d91867-e1ce-4402-8d4f-22188b44b6c2" + } ] } @@ -135,20 +665,68 @@ test_Value_Correct if { RuleOutput[0].ReportDetails == "Requirement met" } -test_Value_Incorrect if { - PolicyId := "MS.AAD.7.3v1" +test_Id_Correct_V2 if { + PolicyId := "MS.AAD.7.8v1" + + Output := tests with input as { + "privileged_roles" : [ + { + "RoleTemplateId" : "1D2EE3F0-90D3-4764-8AF8-BE81FE9D4D71", + "DisplayName" : "Global Administrator", + "Rules" : [ + { + "Id" : "Notification_Admin_EndUser_Assignment", + "AdditionalProperties" : { + "notificationType" : "", + "notificationRecipients" : ["test@example.com"] + } + } + ] + } + ], + "service_plans" : [ + { "ServicePlanName" : "EXCHANGE_S_FOUNDATION", + "ServicePlanId" : "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" + }, + { "ServicePlanName" : "AAD_PREMIUM_P2", + "ServicePlanId" : "c7d91867-e1ce-4402-8d4f-22188b44b6c2" + } + ] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "Requirement met" +} + +test_Id_Incorrect if { + PolicyId := "MS.AAD.7.8v1" Output := tests with input as { - "directory_settings": [ + "privileged_roles" : [ { - "DisplayName" : "Setting display name", - "Values" : [ + "RoleTemplateId" : "1D2EE3F0-90D3-4764-8AF8-BE81FE9D4D71", + "DisplayName" : "Global Administrator", + "Rules" : [ { - "Name" : "EnableGroupSpecificConsent", - "Value" : "true" + "Id" : "Notification_Admin_EndUser_Assignment", + "AdditionalProperties" : { + "notificationType" : "Email", + "notificationRecipients" : [] + } } ] } + ], + "service_plans" : [ + { "ServicePlanName" : "EXCHANGE_S_FOUNDATION", + "ServicePlanId" : "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" + }, + { "ServicePlanName" : "AAD_PREMIUM_P2", + "ServicePlanId" : "c7d91867-e1ce-4402-8d4f-22188b44b6c2" + } ] } @@ -157,4 +735,82 @@ test_Value_Incorrect if { count(RuleOutput) == 1 not RuleOutput[0].RequirementMet RuleOutput[0].ReportDetails == "Requirement not met" -} \ No newline at end of file +} +#-- + +# +# MS.AAD.7.9v1 +#-- + +test_DisplayName_Correct if { + PolicyId := "MS.AAD.7.9v1" + + Output := tests with input as { + "privileged_roles" : [ + { + "RoleTemplateId" : "1D2EE3F0-90D3-4764-8AF8-BE81FE9D4D71", + "DisplayName" : "Global Administrator", + "Rules" : [ + { + "Id" : "Notification_Admin_EndUser_Assignment", + "AdditionalProperties" : { + "notificationType" : "Email", + "notificationRecipients" : [] + } + } + ] + } + ], + "service_plans" : [ + { "ServicePlanName" : "EXCHANGE_S_FOUNDATION", + "ServicePlanId" : "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" + }, + { "ServicePlanName" : "AAD_PREMIUM_P2", + "ServicePlanId" : "c7d91867-e1ce-4402-8d4f-22188b44b6c2" + } + ] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "0 role(s) without notification e-mail configured for role activations found" +} + +test_DisplayName_Incorrect if { + PolicyId := "MS.AAD.7.9v1" + + Output := tests with input as { + "privileged_roles" : [ + { + "RoleTemplateId" : "1D2EE3F0-90D3-4764-8AF8-BE81FE9D4D71", + "DisplayName" : "Cloud Administrator", + "Rules" : [ + { + "Id" : "Notification_Admin_EndUser_Assignment", + "AdditionalProperties" : { + "notificationType" : "Email", + "notificationRecipients" : [] + } + } + ] + } + ], + "service_plans" : [ + { "ServicePlanName" : "EXCHANGE_S_FOUNDATION", + "ServicePlanId" : "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" + }, + { "ServicePlanName" : "AAD_PREMIUM_P2", + "ServicePlanId" : "c7d91867-e1ce-4402-8d4f-22188b44b6c2" + } + ] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "1 role(s) without notification e-mail configured for role activations found:
Cloud Administrator" +} +#-- \ No newline at end of file diff --git a/Testing/Unit/Rego/AAD/AADConfig_08_test.rego b/Testing/Unit/Rego/AAD/AADConfig_08_test.rego index 4bb3296bc8..02ad8a0e8d 100644 --- a/Testing/Unit/Rego/AAD/AADConfig_08_test.rego +++ b/Testing/Unit/Rego/AAD/AADConfig_08_test.rego @@ -2,12 +2,156 @@ package aad import future.keywords import data.report.utils.NotCheckedDetails + # -# Policy 1 +# MS.AAD.8.1v1 #-- -test_NotImplemented_Correct if { +test_GuestUserRoleId_Correct_V1 if { + PolicyId := "MS.AAD.8.1v1" + + Output := tests with input as { + "authorization_policies" : [ + { + "GuestUserRoleId" : "2af84b1e-32c8-42b7-82bc-daa82404023b", + "Id" : "authorizationPolicy" + } + ] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "Permission level set to \"Restricted access\" (authorizationPolicy)" +} + +test_GuestUserRoleId_Correct_V2 if { + PolicyId := "MS.AAD.8.1v1" + + Output := tests with input as { + "authorization_policies" : [ + { + "GuestUserRoleId" : "10dae51f-b6af-4016-8d66-8c2a99b929b3", + "Id" : "authorizationPolicy" + } + ] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "Permission level set to \"Limited access\" (authorizationPolicy)" +} + +test_GuestUserRoleId_Incorrect_V1 if { + PolicyId := "MS.AAD.8.1v1" + + Output := tests with input as { + "authorization_policies" : [ + { + "GuestUserRoleId" : "a0b1b346-4d3e-4e8b-98f8-753987be4970", + "Id" : "authorizationPolicy" + } + ] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "Permission level set to \"Same as member users\" (authorizationPolicy)" +} + +test_GuestUserRoleId_Incorrect_V2 if { + PolicyId := "MS.AAD.8.1v1" + + Output := tests with input as { + "authorization_policies" : [ + { + "GuestUserRoleId" : "Hello world", + "Id" : "authorizationPolicy" + } + ] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "Permission level set to \"Unknown\" (authorizationPolicy)" +} + +test_GuestUserRoleId_Incorrect_V3 if { PolicyId := "MS.AAD.8.1v1" + Output := tests with input as { + "authorization_policies" : [ + { + "GuestUserRoleId" : "Hello world", + "Id" : "policy 1" + }, + { + "GuestUserRoleId" : "2af84b1e-32c8-42b7-82bc-daa82404023b", + "Id" : "policy 2" + } + ] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet +} +#-- + +# +# MS.AAD.8.2v1 +#-- +test_AllowInvitesFrom_Correct if { + PolicyId := "MS.AAD.8.2v1" + + Output := tests with input as { + "authorization_policies" : [ + { + "Id" : "authorizationPolicy", + "AllowInvitesFrom" : "adminsAndGuestInviters" + } + ] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "Permission level set to \"adminsAndGuestInviters\" (authorizationPolicy)" +} + +test_AllowInvitesFrom_Incorrect if { + PolicyId := "MS.AAD.8.2v1" + + Output := tests with input as { + "authorization_policies" : [ + { + "Id" : "authorizationPolicy", + "AllowInvitesFrom" : "Bad value" + } + ] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "Permission level set to \"Bad value\" (authorizationPolicy)" +} +#-- + +# +# MS.AAD.8.3v1 +#-- +test_NotImplemented_Correct if { + PolicyId := "MS.AAD.8.3v1" Output := tests with input as { } RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] @@ -15,4 +159,5 @@ test_NotImplemented_Correct if { count(RuleOutput) == 1 not RuleOutput[0].RequirementMet RuleOutput[0].ReportDetails == NotCheckedDetails(PolicyId) -} \ No newline at end of file +} +#-- \ No newline at end of file diff --git a/Testing/Unit/Rego/AAD/AADConfig_09_test.rego b/Testing/Unit/Rego/AAD/AADConfig_09_test.rego deleted file mode 100644 index f543240071..0000000000 --- a/Testing/Unit/Rego/AAD/AADConfig_09_test.rego +++ /dev/null @@ -1,1029 +0,0 @@ -package aad -import future.keywords - -# -# Policy 1 -#-- - -# User exclusions test -test_UserExclusionNoExempt_Incorrect if { - PolicyId := "MS.AAD.9.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], - "ExcludeGroups": [], - "ExcludeRoles": [] - } - }, - "SessionControls": { - "SignInFrequency": { - "IsEnabled" : true, - "Type" : "hours", - "Value" : 12 - } - }, - "State": "enabled", - "DisplayName": "Test name" - } - ] - } - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." -} - -test_UserExclusionConditions_Correct if { - PolicyId := "MS.AAD.9.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], - "ExcludeGroups": [], - "ExcludeRoles": [] - } - }, - "SessionControls": { - "SignInFrequency": { - "IsEnabled" : true, - "Type" : "hours", - "Value" : 12 - } - }, - "State": "enabled", - "DisplayName": "Test name" - } - ], - "scuba_config": { - "Aad": { - "Policy2_9_1": { - "CapExclusions": { - "Users": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], - "Groups": [] - } - } - - } - - } - } - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "1 conditional access policy(s) found that meet(s) all requirements:
Test name. View all CA policies." -} - -test_UserExclusionsNoExempt_Incorrect if { - PolicyId := "MS.AAD.9.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3", "65fea286-22d3-42f9-b4ca-93a6f75817d4"], - "ExcludeGroups": [], - "ExcludeRoles": [] - } - }, - "SessionControls": { - "SignInFrequency": { - "IsEnabled" : true, - "Type" : "hours", - "Value" : 12 - } - }, - "State": "enabled", - "DisplayName": "Test name" - } - ] - } - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." -} - -test_UserExclusionsSingleExempt_Incorrect if { - PolicyId := "MS.AAD.9.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3", "65fea286-22d3-42f9-b4ca-93a6f75817d4"], - "ExcludeGroups": [], - "ExcludeRoles": [] - } - }, - "SessionControls": { - "SignInFrequency": { - "IsEnabled" : true, - "Type" : "hours", - "Value" : 12 - } - }, - "State": "enabled", - "DisplayName": "Test name" - } - ], - "scuba_config": { - "Aad": { - "Policy2_9_1": { - "CapExclusions": { - "Users": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], - "Groups": [] - } - } - - } - - } - } - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." -} - -test_MultiUserExclusionsConditions_Correct if { - PolicyId := "MS.AAD.9.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3", "65fea286-22d3-42f9-b4ca-93a6f75817d4"], - "ExcludeGroups": [], - "ExcludeRoles": [] - } - }, - "SessionControls": { - "SignInFrequency": { - "IsEnabled" : true, - "Type" : "hours", - "Value" : 12 - } - }, - "State": "enabled", - "DisplayName": "Test name" - } - ], - "scuba_config": { - "Aad": { - "Policy2_9_1": { - "CapExclusions": { - "Users": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3", "65fea286-22d3-42f9-b4ca-93a6f75817d4"], - "Groups": [] - } - } - - } - - } - } - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "1 conditional access policy(s) found that meet(s) all requirements:
Test name. View all CA policies." -} - -# Group Exclusion tests -test_GroupExclusionNoExempt_Incorrect if { - PolicyId := "MS.AAD.9.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": [], - "ExcludeGroups": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], - "ExcludeRoles": [] - } - }, - "SessionControls": { - "SignInFrequency": { - "IsEnabled" : true, - "Type" : "hours", - "Value" : 12 - } - }, - "State": "enabled", - "DisplayName": "Test name" - } - ] - } - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." -} - -test_GroupExclusionsConditions_Correct if { - PolicyId := "MS.AAD.9.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": [], - "ExcludeGroups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"], - "ExcludeRoles": [] - } - }, - "SessionControls": { - "SignInFrequency": { - "IsEnabled" : true, - "Type" : "hours", - "Value" : 12 - } - }, - "State": "enabled", - "DisplayName": "Test name" - } - ], - "scuba_config": { - "Aad": { - "Policy2_9_1": { - "CapExclusions": { - "Users": [], - "Groups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"] - } - } - - } - } - } - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "1 conditional access policy(s) found that meet(s) all requirements:
Test name. View all CA policies." -} - -test_GroupExclusionsNoExempt_Incorrect if { - PolicyId := "MS.AAD.9.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": [], - "ExcludeGroups": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3", "65fea286-22d3-42f9-b4ca-93a6f75817d4"], - "ExcludeRoles": [] - } - }, - "SessionControls": { - "SignInFrequency": { - "IsEnabled" : true, - "Type" : "hours", - "Value" : 12 - } - }, - "State": "enabled", - "DisplayName": "Test name" - } - ] - } - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." -} - -test_GroupExclusionsSingleExempt_Incorrect if { - PolicyId := "MS.AAD.9.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": [], - "ExcludeGroups": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3", "65fea286-22d3-42f9-b4ca-93a6f75817d4"], - "ExcludeRoles": [] - } - }, - "SessionControls": { - "SignInFrequency": { - "IsEnabled" : true, - "Type" : "hours", - "Value" : 12 - } - }, - "State": "enabled", - "DisplayName": "Test name" - } - ], - "scuba_config": { - "Aad": { - "Policy2_9_1": { - "CapExclusions": { - "Users": [], - "Groups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"] - } - } - - } - } - } - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." -} - -test_MultiGroupExclusionsConditions_Correct if { - PolicyId := "MS.AAD.9.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": [], - "ExcludeGroups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423", "65fea286-22d3-42f9-b4ca-93a6f75817d4"], - "ExcludeRoles": [] - } - }, - "SessionControls": { - "SignInFrequency": { - "IsEnabled" : true, - "Type" : "hours", - "Value" : 12 - } - }, - "State": "enabled", - "DisplayName": "Test name" - } - ], - "scuba_config": { - "Aad": { - "Policy2_9_1": { - "CapExclusions": { - "Users": [], - "Groups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423", "65fea286-22d3-42f9-b4ca-93a6f75817d4"] - } - } - - } - } - } - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "1 conditional access policy(s) found that meet(s) all requirements:
Test name. View all CA policies." -} - -# User and group exclusions tests -test_UserGroupExclusionConditions_Correct if { - PolicyId := "MS.AAD.9.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], - "ExcludeGroups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"], - "ExcludeRoles": [] - } - }, - "SessionControls": { - "SignInFrequency": { - "IsEnabled" : true, - "Type" : "hours", - "Value" : 12 - } - }, - "State": "enabled", - "DisplayName": "Test name" - } - ], - "scuba_config": { - "Aad": { - "Policy2_9_1": { - "CapExclusions": { - "Users": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], - "Groups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"] - } - } - } - } - } - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "1 conditional access policy(s) found that meet(s) all requirements:
Test name. View all CA policies." -} - -test_UserGroupExclusionNoExempt_Incorrect if { - PolicyId := "MS.AAD.9.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], - "ExcludeGroups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"], - "ExcludeRoles": [] - } - }, - "SessionControls": { - "SignInFrequency": { - "IsEnabled" : true, - "Type" : "hours", - "Value" : 12 - } - }, - "State": "enabled", - "DisplayName": "Test name" - } - ] - } - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." -} - -test_UserGroupExclusionUserExemptOnly_Incorrect if { - PolicyId := "MS.AAD.9.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], - "ExcludeGroups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"], - "ExcludeRoles": [] - } - }, - "SessionControls": { - "SignInFrequency": { - "IsEnabled" : true, - "Type" : "hours", - "Value" : 12 - } - }, - "State": "enabled", - "DisplayName": "Test name" - } - ], - "scuba_config": { - "Aad": { - "Policy2_9_1": { - "CapExclusions": { - "Users": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], - "Groups": [] - } - } - } - } - } - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." -} - -test_UserGroupExclusionGroupExemptOnly_Incorrect if { - PolicyId := "MS.AAD.9.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], - "ExcludeGroups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"], - "ExcludeRoles": [] - } - }, - "SessionControls": { - "SignInFrequency": { - "IsEnabled" : true, - "Type" : "hours", - "Value" : 12 - } - }, - "State": "enabled", - "DisplayName": "Test name" - } - ], - "scuba_config": { - "Aad": { - "Policy2_9_1": { - "CapExclusions": { - "Users": [], - "Groups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"] - } - } - } - } - } - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." -} - -test_UserGroupExclusionTooFewUserExempts_Incorrect if { - PolicyId := "MS.AAD.9.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423", "65fea286-22d3-42f9-b4ca-93a6f75817d4"], - "ExcludeGroups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"], - "ExcludeRoles": [] - } - }, - "SessionControls": { - "SignInFrequency": { - "IsEnabled" : true, - "Type" : "hours", - "Value" : 12 - } - }, - "State": "enabled", - "DisplayName": "Test name" - } - ], - "scuba_config": { - "Aad": { - "Policy2_9_1": { - "CapExclusions": { - "Users": ["65fea286-22d3-42f9-b4ca-93a6f75817d4"], - "Groups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"] - } - } - } - } - } - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." -} - -# Other conditions -test_ConditionalAccessPolicies_Correct if { - PolicyId := "MS.AAD.9.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": [], - "ExcludeGroups": [], - "ExcludeRoles": [] - } - }, - "SessionControls": { - "SignInFrequency": { - "IsEnabled" : true, - "Type" : "hours", - "Value" : 12 - } - }, - "State": "enabled", - "DisplayName" : "Test Name" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "1 conditional access policy(s) found that meet(s) all requirements:
Test Name. View all CA policies." -} - -test_IncludeApplications_Incorrect if { - PolicyId := "MS.AAD.9.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": [] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": [], - "ExcludeGroups": [], - "ExcludeRoles": [] - } - }, - "SessionControls": { - "SignInFrequency": { - "IsEnabled" : true, - "Type" : "hours", - "Value" : 12 - } - }, - "State": "enabled", - "DisplayName" : "Test Name" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." -} - -test_IncludeUsers_Incorrect if { - PolicyId := "MS.AAD.9.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": [], - "ExcludeUsers": [], - "ExcludeGroups": [], - "ExcludeRoles": [] - } - }, - "SessionControls": { - "SignInFrequency": { - "IsEnabled" : true, - "Type" : "hours", - "Value" : 12 - } - }, - "State": "enabled", - "DisplayName" : "Test Name" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." -} - -test_ExcludeUsers_Incorrect if { - PolicyId := "MS.AAD.9.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": ["4b8dda31-c541-4e2d-aa7f-5f6e1980dc90"], - "ExcludeGroups": [], - "ExcludeRoles": [] - } - }, - "SessionControls": { - "SignInFrequency": { - "IsEnabled" : true, - "Type" : "hours", - "Value" : 12 - } - }, - "State": "enabled", - "DisplayName" : "Test Name" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." -} - -test_ExcludeGroups_Incorrect if { - PolicyId := "MS.AAD.9.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": [], - "ExcludeGroups": ["4b8dda31-c541-4e2d-aa7f-5f6e1980dc90"], - "ExcludeRoles": [] - } - }, - "SessionControls": { - "SignInFrequency": { - "IsEnabled" : true, - "Type" : "hours", - "Value" : 12 - } - }, - "State": "enabled", - "DisplayName" : "Test Name" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." -} - -test_ExcludeRoles_Incorrect if { - PolicyId := "MS.AAD.9.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers":[], - "ExcludeGroups": [], - "ExcludeRoles": ["4b8dda31-c541-4e2d-aa7f-5f6e1980dc90"] - } - }, - "SessionControls": { - "SignInFrequency": { - "IsEnabled" : true, - "Type" : "hours", - "Value" : 12 - } - }, - "State": "enabled", - "DisplayName" : "Test Name" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." -} - -test_IsEnabled_Incorrect if { - PolicyId := "MS.AAD.9.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": [], - "ExcludeGroups": [], - "ExcludeRoles": [] - } - }, - "SessionControls": { - "SignInFrequency": { - "IsEnabled" : false, - "Type" : "hours", - "Value" : 12 - } - }, - "State": "enabled", - "DisplayName" : "Test Name" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." -} - -test_Type_Incorrect if { - PolicyId := "MS.AAD.9.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": [], - "ExcludeGroups": [], - "ExcludeRoles": [] - } - }, - "SessionControls": { - "SignInFrequency": { - "IsEnabled" : true, - "Type" : "Hello World", - "Value" : 12 - } - }, - "State": "enabled", - "DisplayName" : "Test Name" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." -} - -test_Value_Incorrect if { - PolicyId := "MS.AAD.9.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": [], - "ExcludeGroups": [], - "ExcludeRoles": [] - } - }, - "SessionControls": { - "SignInFrequency": { - "IsEnabled" : true, - "Type" : "hours", - "Value" : 24 - } - }, - "State": "enabled", - "DisplayName" : "Test Name" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." -} - -test_State_Incorrect if { - PolicyId := "MS.AAD.9.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": [], - "ExcludeGroups": [], - "ExcludeRoles": [] - } - }, - "SessionControls": { - "SignInFrequency": { - "IsEnabled" : true, - "Type" : "hours", - "Value" : 12 - } - }, - "State": "disabled", - "DisplayName" : "Test Name" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." -} \ No newline at end of file diff --git a/Testing/Unit/Rego/AAD/AADConfig_10_test.rego b/Testing/Unit/Rego/AAD/AADConfig_10_test.rego deleted file mode 100644 index 55ef33f402..0000000000 --- a/Testing/Unit/Rego/AAD/AADConfig_10_test.rego +++ /dev/null @@ -1,968 +0,0 @@ -package aad -import future.keywords - - -# -# Policy 1 -#-- -# User exclusions test -test_UserExclusionNoExempt_Incorrect if { - PolicyId := "MS.AAD.10.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], - "ExcludeGroups": [], - "ExcludeRoles": [] - } - }, - "SessionControls": { - "PersistentBrowser": { - "IsEnabled" : true, - "Mode" : "never" - } - }, - "State": "enabled", - "DisplayName": "Test name" - } - ] - } - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." -} - -test_UserExclusionConditions_Correct if { - PolicyId := "MS.AAD.10.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], - "ExcludeGroups": [], - "ExcludeRoles": [] - } - }, - "SessionControls": { - "PersistentBrowser": { - "IsEnabled" : true, - "Mode" : "never" - } - }, - "State": "enabled", - "DisplayName": "Test name" - } - ], - "scuba_config": { - "Aad": { - "Policy2_10_1": { - "CapExclusions": { - "Users": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], - "Groups": [] - } - } - - } - - } - } - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "1 conditional access policy(s) found that meet(s) all requirements:
Test name. View all CA policies." -} - -test_UserExclusionsNoExempt_Incorrect if { - PolicyId := "MS.AAD.10.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3", "65fea286-22d3-42f9-b4ca-93a6f75817d4"], - "ExcludeGroups": [], - "ExcludeRoles": [] - } - }, - "SessionControls": { - "PersistentBrowser": { - "IsEnabled" : true, - "Mode" : "never" - } - }, - "State": "enabled", - "DisplayName": "Test name" - } - ] - } - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." -} - -test_UserExclusionsSingleExempt_Incorrect if { - PolicyId := "MS.AAD.10.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3", "65fea286-22d3-42f9-b4ca-93a6f75817d4"], - "ExcludeGroups": [], - "ExcludeRoles": [] - } - }, - "SessionControls": { - "PersistentBrowser": { - "IsEnabled" : true, - "Mode" : "never" - } - }, - "State": "enabled", - "DisplayName": "Test name" - } - ], - "scuba_config": { - "Aad": { - "Policy2_10_1": { - "CapExclusions": { - "Users": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], - "Groups": [] - } - } - - } - - } - } - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." -} - -test_MultiUserExclusionsConditions_Correct if { - PolicyId := "MS.AAD.10.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3", "65fea286-22d3-42f9-b4ca-93a6f75817d4"], - "ExcludeGroups": [], - "ExcludeRoles": [] - } - }, - "SessionControls": { - "PersistentBrowser": { - "IsEnabled" : true, - "Mode" : "never" - } - }, - "State": "enabled", - "DisplayName": "Test name" - } - ], - "scuba_config": { - "Aad": { - "Policy2_10_1": { - "CapExclusions": { - "Users": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3", "65fea286-22d3-42f9-b4ca-93a6f75817d4"], - "Groups": [] - } - } - - } - - } - } - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "1 conditional access policy(s) found that meet(s) all requirements:
Test name. View all CA policies." -} - -# Group Exclusion tests -test_GroupExclusionNoExempt_Incorrect if { - PolicyId := "MS.AAD.10.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": [], - "ExcludeGroups": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], - "ExcludeRoles": [] - } - }, - "SessionControls": { - "PersistentBrowser": { - "IsEnabled" : true, - "Mode" : "never" - } - }, - "State": "enabled", - "DisplayName": "Test name" - } - ] - } - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." -} - -test_GroupExclusionsConditions_Correct if { - PolicyId := "MS.AAD.10.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": [], - "ExcludeGroups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"], - "ExcludeRoles": [] - } - }, - "SessionControls": { - "PersistentBrowser": { - "IsEnabled" : true, - "Mode" : "never" - } - }, - "State": "enabled", - "DisplayName": "Test name" - } - ], - "scuba_config": { - "Aad": { - "Policy2_10_1": { - "CapExclusions": { - "Users": [], - "Groups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"] - } - } - - } - } - } - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "1 conditional access policy(s) found that meet(s) all requirements:
Test name. View all CA policies." -} - -test_GroupExclusionsNoExempt_Incorrect if { - PolicyId := "MS.AAD.10.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": [], - "ExcludeGroups": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3", "65fea286-22d3-42f9-b4ca-93a6f75817d4"], - "ExcludeRoles": [] - } - }, - "SessionControls": { - "PersistentBrowser": { - "IsEnabled" : true, - "Mode" : "never" - } - }, - "State": "enabled", - "DisplayName": "Test name" - } - ] - } - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." -} - -test_GroupExclusionsSingleExempt_Incorrect if { - PolicyId := "MS.AAD.10.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": [], - "ExcludeGroups": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3", "65fea286-22d3-42f9-b4ca-93a6f75817d4"], - "ExcludeRoles": [] - } - }, - "SessionControls": { - "PersistentBrowser": { - "IsEnabled" : true, - "Mode" : "never" - } - }, - "State": "enabled", - "DisplayName": "Test name" - } - ], - "scuba_config": { - "Aad": { - "Policy2_10_1": { - "CapExclusions": { - "Users": [], - "Groups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"] - } - } - - } - } - } - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." -} - -test_MultiGroupExclusionsConditions_Correct if { - PolicyId := "MS.AAD.10.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": [], - "ExcludeGroups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423", "65fea286-22d3-42f9-b4ca-93a6f75817d4"], - "ExcludeRoles": [] - } - }, - "SessionControls": { - "PersistentBrowser": { - "IsEnabled" : true, - "Mode" : "never" - } - }, - "State": "enabled", - "DisplayName": "Test name" - } - ], - "scuba_config": { - "Aad": { - "Policy2_10_1": { - "CapExclusions": { - "Users": [], - "Groups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423", "65fea286-22d3-42f9-b4ca-93a6f75817d4"] - } - } - - } - } - } - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "1 conditional access policy(s) found that meet(s) all requirements:
Test name. View all CA policies." -} - -# User and group exclusions tests -test_UserGroupExclusionConditions_Correct if { - PolicyId := "MS.AAD.10.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], - "ExcludeGroups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"], - "ExcludeRoles": [] - } - }, - "SessionControls": { - "PersistentBrowser": { - "IsEnabled" : true, - "Mode" : "never" - } - }, - "State": "enabled", - "DisplayName": "Test name" - } - ], - "scuba_config": { - "Aad": { - "Policy2_10_1": { - "CapExclusions": { - "Users": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], - "Groups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"] - } - } - } - } - } - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "1 conditional access policy(s) found that meet(s) all requirements:
Test name. View all CA policies." -} - -test_UserGroupExclusionNoExempt_Incorrect if { - PolicyId := "MS.AAD.10.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], - "ExcludeGroups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"], - "ExcludeRoles": [] - } - }, - "SessionControls": { - "PersistentBrowser": { - "IsEnabled" : true, - "Mode" : "never" - } - }, - "State": "enabled", - "DisplayName": "Test name" - } - ] - } - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." -} - -test_UserGroupExclusionUserExemptOnly_Incorrect if { - PolicyId := "MS.AAD.10.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], - "ExcludeGroups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"], - "ExcludeRoles": [] - } - }, - "SessionControls": { - "PersistentBrowser": { - "IsEnabled" : true, - "Mode" : "never" - } - }, - "State": "enabled", - "DisplayName": "Test name" - } - ], - "scuba_config": { - "Aad": { - "Policy2_10_1": { - "CapExclusions": { - "Users": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], - "Groups": [] - } - } - } - } - } - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." -} - -test_UserGroupExclusionGroupExemptOnly_Incorrect if { - PolicyId := "MS.AAD.10.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": ["49b4dcdf-1f90-41a7c3609b425-9dd7-5e3"], - "ExcludeGroups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"], - "ExcludeRoles": [] - } - }, - "SessionControls": { - "PersistentBrowser": { - "IsEnabled" : true, - "Mode" : "never" - } - }, - "State": "enabled", - "DisplayName": "Test name" - } - ], - "scuba_config": { - "Aad": { - "Policy2_10_1": { - "CapExclusions": { - "Users": [], - "Groups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"] - } - } - } - } - } - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." -} - -test_UserGroupExclusionTooFewUserExempts_Incorrect if { - PolicyId := "MS.AAD.10.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423", "65fea286-22d3-42f9-b4ca-93a6f75817d4"], - "ExcludeGroups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"], - "ExcludeRoles": [] - } - }, - "SessionControls": { - "PersistentBrowser": { - "IsEnabled" : true, - "Mode" : "never" - } - }, - "State": "enabled", - "DisplayName": "Test name" - } - ], - "scuba_config": { - "Aad": { - "Policy2_10_1": { - "CapExclusions": { - "Users": ["65fea286-22d3-42f9-b4ca-93a6f75817d4"], - "Groups": ["49b4dcdf-1f90-41a5-9dd7-5e7c3609b423"] - } - } - } - } - } - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." -} - -# Other conditions -test_ConditionalAccessPolicies_Correct if { - PolicyId := "MS.AAD.10.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": [], - "ExcludeGroups": [], - "ExcludeRoles": [] - } - }, - "SessionControls": { - "PersistentBrowser": { - "IsEnabled" : true, - "Mode" : "never" - } - }, - "State": "enabled", - "DisplayName" : "Test Name" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "1 conditional access policy(s) found that meet(s) all requirements:
Test Name. View all CA policies." -} - -test_IncludeApplications_Incorrect if { - PolicyId := "MS.AAD.10.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": [] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": [], - "ExcludeGroups": [], - "ExcludeRoles": [] - } - }, - "SessionControls": { - "PersistentBrowser": { - "IsEnabled" : true, - "Mode" : "never" - } - }, - "State": "enabled", - "DisplayName" : "Test Name" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." -} - -test_IncludeUsers_Incorrect if { - PolicyId := "MS.AAD.10.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": [], - "ExcludeUsers": [], - "ExcludeGroups": [], - "ExcludeRoles": [] - } - }, - "SessionControls": { - "PersistentBrowser": { - "IsEnabled" : true, - "Mode" : "never" - } - }, - "State": "enabled", - "DisplayName" : "Test Name" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." -} - -test_ExcludeUsers_Incorrect if { - PolicyId := "MS.AAD.10.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": ["4b8dda31-c541-4e2d-aa7f-5f6e1980dc90"], - "ExcludeGroups": [], - "ExcludeRoles": [] - } - }, - "SessionControls": { - "PersistentBrowser": { - "IsEnabled" : true, - "Mode" : "never" - } - }, - "State": "enabled", - "DisplayName" : "Test Name" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." -} - -test_ExcludeGroups_Incorrect if { - PolicyId := "MS.AAD.10.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": [], - "ExcludeGroups": ["4b8dda31-c541-4e2d-aa7f-5f6e1980dc90"], - "ExcludeRoles": [] - } - }, - "SessionControls": { - "PersistentBrowser": { - "IsEnabled" : true, - "Mode" : "never" - } - }, - "State": "enabled", - "DisplayName" : "Test Name" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." -} - -test_ExcludeRoles_Incorrect if { - PolicyId := "MS.AAD.10.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": [], - "ExcludeGroups": [], - "ExcludeRoles": ["4b8dda31-c541-4e2d-aa7f-5f6e1980dc90"] - } - }, - "SessionControls": { - "PersistentBrowser": { - "IsEnabled" : true, - "Mode" : "never" - } - }, - "State": "enabled", - "DisplayName" : "Test Name" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." -} - -test_IsEnabled_Incorrect if { - PolicyId := "MS.AAD.10.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": [], - "ExcludeGroups": [], - "ExcludeRoles": [] - } - }, - "SessionControls": { - "PersistentBrowser": { - "IsEnabled" : false, - "Mode" : "never" - } - }, - "State": "enabled", - "DisplayName" : "Test Name" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." -} - -test_Mode_Incorrect if { - PolicyId := "MS.AAD.10.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": [], - "ExcludeGroups": [], - "ExcludeRoles": [] - } - }, - "SessionControls": { - "PersistentBrowser": { - "IsEnabled" : true, - "Mode" : "always" - } - }, - "State": "enabled", - "DisplayName" : "Test Name" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." -} - -test_State_Incorrect if { - PolicyId := "MS.AAD.10.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"], - "ExcludeUsers": [], - "ExcludeGroups": [], - "ExcludeRoles": [] - } - }, - "SessionControls": { - "PersistentBrowser": { - "IsEnabled" : true, - "Mode" : "never" - } - }, - "State": "disabled", - "DisplayName" : "Test Name" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." -} \ No newline at end of file diff --git a/Testing/Unit/Rego/AAD/AADConfig_11_test.rego b/Testing/Unit/Rego/AAD/AADConfig_11_test.rego deleted file mode 100644 index c2cee717c1..0000000000 --- a/Testing/Unit/Rego/AAD/AADConfig_11_test.rego +++ /dev/null @@ -1,83 +0,0 @@ -package aad -import future.keywords - - -# -# Policy 1 -#-- -test_PrivilegedUsers_Correct if { - PolicyId := "MS.AAD.11.1v1" - - Output := tests with input as { - "privileged_users" : { - "User1": { - "DisplayName": "Test Name1", - "roles": ["Privileged Role Administrator", "Global Administrator"] - }, - "User2": { - "DisplayName": "Test Name2", - "roles": ["Global Administrator"] - } - } - } - - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "2 global admin(s) found:
Test Name1, Test Name2" -} - -test_PrivilegedUsers_Incorrect_V1 if { - PolicyId := "MS.AAD.11.1v1" - - Output := tests with input as { - "privileged_users" : { - "User1": { - "DisplayName": "Test Name1", - "roles": ["Privileged Role Administrator", "Global Administrator"] - } - } - } - - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "1 global admin(s) found:
Test Name1" -} - -test_PrivilegedUsers_Incorrect_V2 if { - PolicyId := "MS.AAD.11.1v1" - - Output := tests with input as { - "privileged_users" : { - "User1": { - "DisplayName": "Test Name1", - "roles": ["Privileged Role Administrator", "Global Administrator"] - }, - "User2": { - "DisplayName": "Test Name2", - "roles": ["Global Administrator"] - }, - "User3": { - "DisplayName": "Test Name3", - "roles": ["Global Administrator"] - }, - "User4": { - "DisplayName": "Test Name4", - "roles": ["Global Administrator"] - }, - "User5": { - "DisplayName": "Test Name5", - "roles": ["Global Administrator"] - } - } - } - - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "5 global admin(s) found:
Test Name1, Test Name2, Test Name3, Test Name4, Test Name5" -} \ No newline at end of file diff --git a/Testing/Unit/Rego/AAD/AADConfig_12_test.rego b/Testing/Unit/Rego/AAD/AADConfig_12_test.rego deleted file mode 100644 index 0360a2a054..0000000000 --- a/Testing/Unit/Rego/AAD/AADConfig_12_test.rego +++ /dev/null @@ -1,75 +0,0 @@ -package aad -import future.keywords - - -# -# Policy 1 -#-- -test_OnPremisesImmutableId_Correct if { - PolicyId := "MS.AAD.12.1v1" - - Output := tests with input as { - "privileged_users": { - "User1": { - "DisplayName": "Alice", - "OnPremisesImmutableId": null, - "roles": ["Privileged Role Administrator", "Global Administrator"] - }, - "User2": { - "DisplayName": "Bob", - "OnPremisesImmutableId": null, - "roles": ["Global Administrator"] - } - } - } - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "0 admin(s) that are not cloud-only found" -} - -test_OnPremisesImmutableId_Incorrect_V1 if { - PolicyId := "MS.AAD.12.1v1" - - Output := tests with input as { - "privileged_users": { - "User1": { - "DisplayName": "Alice", - "OnPremisesImmutableId": "HelloWorld", - "roles": ["Privileged Role Administrator", "Global Administrator"] - } - } - } - - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "1 admin(s) that are not cloud-only found:
Alice" -} - -test_OnPremisesImmutableId_Incorrect_V2 if { - PolicyId := "MS.AAD.12.1v1" - - Output := tests with input as { - "privileged_users": { - "User1": { - "DisplayName": "Alice", - "OnPremisesImmutableId": "HelloWorld", - "roles": ["Privileged Role Administrator", "Global Administrator"] - }, - "User2": { - "DisplayName": "Bob", - "OnPremisesImmutableId": null, - "roles": ["Global Administrator"] - } - } - } - - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "1 admin(s) that are not cloud-only found:
Alice" -} \ No newline at end of file diff --git a/Testing/Unit/Rego/AAD/AADConfig_13_test.rego b/Testing/Unit/Rego/AAD/AADConfig_13_test.rego deleted file mode 100644 index 0871803157..0000000000 --- a/Testing/Unit/Rego/AAD/AADConfig_13_test.rego +++ /dev/null @@ -1,285 +0,0 @@ -package aad -import future.keywords - - -# -# Policy 1 -#-- -test_ConditionalAccessPolicies_Correct if { - PolicyId := "MS.AAD.13.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeRoles": ["Role1", "Role2" ], - "ExcludeRoles": [] - } - }, - "GrantControls": { - "BuiltInControls": ["mfa"] - }, - "State": "enabled", - "DisplayName": "MFA required for all highly Privileged Roles Policy" - } - ], - "privileged_roles": [ - { - "RoleTemplateId": "Role1", - "DisplayName": "Global Administrator" - }, - { - "RoleTemplateId": "Role2", - "DisplayName": "Privileged Role Administrator" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "1 conditional access policy(s) found that meet(s) all requirements:
MFA required for all highly Privileged Roles Policy. View all CA policies." -} - -test_IncludeApplications_Incorrect if { - PolicyId := "MS.AAD.13.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": [""] - }, - "Users": { - "IncludeRoles": ["Role1", "Role2" ], - "ExcludeRoles": [] - } - }, - "GrantControls": { - "BuiltInControls": ["mfa"] - }, - "State": "enabled", - "DisplayName": {"MFA required for all highly Privileged Roles Policy"} - } - ], - "privileged_roles": [ - { - "RoleTemplateId": "Role1", - "DisplayName": "Global Administrator" - }, - { - "RoleTemplateId": "Role2", - "DisplayName": "Privileged Role Administrator" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." -} - -test_BuiltInControls_Incorrect if { - PolicyId := "MS.AAD.13.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeRoles": ["Role1", "Role2" ], - "ExcludeRoles": [] - } - }, - "GrantControls": { - "BuiltInControls": [""] - }, - "State": "enabled", - "DisplayName": {"MFA required for all highly Privileged Roles Policy"} - } - ], - "privileged_roles": [ - { - "RoleTemplateId": "Role1", - "DisplayName": "Global Administrator" - }, - { - "RoleTemplateId": "Role2", - "DisplayName": "Privileged Role Administrator" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." -} - -test_State_Incorrect if { - PolicyId := "MS.AAD.13.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeRoles": ["Role1", "Role2" ], - "ExcludeRoles": [] - } - }, - "GrantControls": { - "BuiltInControls": ["mfa"] - }, - "State": "disabled", - "DisplayName": {"MFA required for all highly Privileged Roles Policy"} - } - ], - "privileged_roles": [ - { - "RoleTemplateId": "Role1", - "DisplayName": "Global Administrator" - }, - { - "RoleTemplateId": "Role2", - "DisplayName": "Privileged Role Administrator" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." -} - -test_IncludeRoles_Incorrect_V1 if { - PolicyId := "MS.AAD.13.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeRoles": ["Role1"], - "ExcludeRoles": [] - } - }, - "GrantControls": { - "BuiltInControls": ["mfa"] - }, - "State": "enabled", - "DisplayName": {"MFA required for all highly Privileged Roles Policy"} - } - ], - "privileged_roles": [ - { - "RoleTemplateId": "Role1", - "DisplayName": "Global Administrator" - }, - { - "RoleTemplateId": "Role2", - "DisplayName": "Privileged Role Administrator" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." -} - -test_IncludeRoles_Incorrect_V2 if { - PolicyId := "MS.AAD.13.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeRoles": ["Role2"], - "ExcludeRoles": [] - } - }, - "GrantControls": { - "BuiltInControls": ["mfa"] - }, - "State": "enabled", - "DisplayName": {"MFA required for all highly Privileged Roles Policy"} - } - ], - "privileged_roles": [ - { - "RoleTemplateId": "Role1", - "DisplayName": "Global Administrator" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." -} - -test_ExcludeRoles_Incorrect if { - PolicyId := "MS.AAD.13.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeRoles": ["Role1", "Role2"], - "ExcludeRoles": ["Role1"] - } - }, - "GrantControls": { - "BuiltInControls": ["mfa"] - }, - "State": "enabled", - "DisplayName": {"MFA required for all highly Privileged Roles Policy"} - } - ], - "privileged_roles": [ - { - "RoleTemplateId": "Role1", - "DisplayName": "Global Administrator" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." -} \ No newline at end of file diff --git a/Testing/Unit/Rego/AAD/AADConfig_14_test.rego b/Testing/Unit/Rego/AAD/AADConfig_14_test.rego deleted file mode 100644 index 10b67485aa..0000000000 --- a/Testing/Unit/Rego/AAD/AADConfig_14_test.rego +++ /dev/null @@ -1,194 +0,0 @@ -package aad -import future.keywords - - -# -# Policy 1 -#-- -test_AdditionalProperties_Correct if { - PolicyId := "MS.AAD.14.1v1" - - Output := tests with input as { - "privileged_roles": [ - { - "DisplayName": "Global Administrator", - "Rules": [ - { - "Id": "Expiration_Admin_Assignment", - "AdditionalProperties": { - "isExpirationRequired": true, - "maximumDuration": "P15D" - } - } - ] - } - ], - "service_plans": [ - { "ServicePlanName": "EXCHANGE_S_FOUNDATION", - "ServicePlanId": "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" - }, - { "ServicePlanName": "AAD_PREMIUM_P2", - "ServicePlanId": "c7d91867-e1ce-4402-8d4f-22188b44b6c2" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "0 role(s) configured to allow permanent active assignment or expiration period too long" -} - -test_AdditionalProperties_Incorrect_V1 if { - PolicyId := "MS.AAD.14.1v1" - - Output := tests with input as { - "privileged_roles": [ - { - "DisplayName": "Global Administrator", - "Rules": [ - { - "Id": "Expiration_Admin_Assignment", - "AdditionalProperties": { - "isExpirationRequired": false, - "maximumDuration": "P30D" - } - } - ] - } - ], - "service_plans": [ - { "ServicePlanName": "EXCHANGE_S_FOUNDATION", - "ServicePlanId": "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" - }, - { "ServicePlanName": "AAD_PREMIUM_P2", - "ServicePlanId": "c7d91867-e1ce-4402-8d4f-22188b44b6c2" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "1 role(s) configured to allow permanent active assignment or expiration period too long:
Global Administrator" -} - -test_AdditionalProperties_Incorrect_V2 if { - PolicyId := "MS.AAD.14.1v1" - - Output := tests with input as { - "privileged_roles": [ - { - "DisplayName": "Global Administrator", - "Rules": [ - { - "Id": "Expiration_Admin_Assignment", - "AdditionalProperties": { - "isExpirationRequired": true, - "maximumDuration": "P30D" - } - } - ] - } - ], - "service_plans": [ - { "ServicePlanName": "EXCHANGE_S_FOUNDATION", - "ServicePlanId": "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" - }, - { "ServicePlanName": "AAD_PREMIUM_P2", - "ServicePlanId": "c7d91867-e1ce-4402-8d4f-22188b44b6c2" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "1 role(s) configured to allow permanent active assignment or expiration period too long:
Global Administrator" -} - -# -# Policy 2 -#-- -test_Assignments_Correct if { - PolicyId := "MS.AAD.14.2v1" - - Output := tests with input as { - "privileged_roles": [ - { - "DisplayName": "Global Administrator", - "Assignments": [ - { - "StartDateTime": "/Date(1660328610000)/" - } - ], - "Rules": [ - { - "Id": "Expiration_Admin_Assignment", - "AdditionalProperties": { - "isExpirationRequired": true, - "maximumDuration": "P30D" - } - } - ] - } - ], - "service_plans": [ - { "ServicePlanName": "EXCHANGE_S_FOUNDATION", - "ServicePlanId": "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" - }, - { "ServicePlanName": "AAD_PREMIUM_P2", - "ServicePlanId": "c7d91867-e1ce-4402-8d4f-22188b44b6c2" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "0 role(s) assigned to users outside of PIM" -} - -test_Assignments_Incorrect if { - PolicyId := "MS.AAD.14.2v1" - - Output := tests with input as { - "privileged_roles": [ - { - "DisplayName": "Global Administrator", - "Assignments": [ - { - "StartDateTime": null - } - ], - "Rules": [ - { - "Id": "Expiration_Admin_Assignment", - "AdditionalProperties": { - "isExpirationRequired": true, - "maximumDuration": "P30D" - } - } - ] - } - ], - "service_plans": [ - { "ServicePlanName": "EXCHANGE_S_FOUNDATION", - "ServicePlanId": "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" - }, - { "ServicePlanName": "AAD_PREMIUM_P2", - "ServicePlanId": "c7d91867-e1ce-4402-8d4f-22188b44b6c2" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "1 role(s) assigned to users outside of PIM:
Global Administrator" -} \ No newline at end of file diff --git a/Testing/Unit/Rego/AAD/AADConfig_15_test.rego b/Testing/Unit/Rego/AAD/AADConfig_15_test.rego deleted file mode 100644 index 14cc57dc87..0000000000 --- a/Testing/Unit/Rego/AAD/AADConfig_15_test.rego +++ /dev/null @@ -1,78 +0,0 @@ -package aad -import future.keywords - - -# -# Policy 1 -#-- -test_AdditionalProperties_Correct if { - PolicyId := "MS.AAD.15.1v1" - - Output := tests with input as { - "privileged_roles": [ - { - "DisplayName": "Global Administrator", - "Rules": [ - { - "Id": "Approval_EndUser_Assignment", - "AdditionalProperties": { - "setting": { - "isApprovalRequired" : true - } - } - } - ] - } - ], - "service_plans": [ - { "ServicePlanName": "EXCHANGE_S_FOUNDATION", - "ServicePlanId": "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" - }, - { "ServicePlanName": "AAD_PREMIUM_P2", - "ServicePlanId": "c7d91867-e1ce-4402-8d4f-22188b44b6c2" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "0 role(s) that do not require approval to activate found" -} - -test_AdditionalProperties_Incorrect if { - PolicyId := "MS.AAD.15.1v1" - - Output := tests with input as { - "privileged_roles": [ - { - "DisplayName": "Global Administrator", - "Rules": [ - { - "Id": "Approval_EndUser_Assignment", - "AdditionalProperties": { - "setting": { - "isApprovalRequired" : false - } - } - } - ] - } - ], - "service_plans": [ - { "ServicePlanName": "EXCHANGE_S_FOUNDATION", - "ServicePlanId": "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" - }, - { "ServicePlanName": "AAD_PREMIUM_P2", - "ServicePlanId": "c7d91867-e1ce-4402-8d4f-22188b44b6c2" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "1 role(s) that do not require approval to activate found:
Global Administrator" -} \ No newline at end of file diff --git a/Testing/Unit/Rego/AAD/AADConfig_16_test.rego b/Testing/Unit/Rego/AAD/AADConfig_16_test.rego deleted file mode 100644 index f40652fc13..0000000000 --- a/Testing/Unit/Rego/AAD/AADConfig_16_test.rego +++ /dev/null @@ -1,350 +0,0 @@ -package aad -import future.keywords - - -# -# Policy 1 -#-- -test_notificationRecipients_Correct if { - PolicyId := "MS.AAD.16.1v1" - - Output := tests with input as { - "privileged_roles": [ - { - "RoleTemplateId": "1D2EE3F0-90D3-4764-8AF8-BE81FE9D4D71", - "DisplayName": "Global Administrator", - "Rules": [ - { - "Id": "Notification_Admin_Admin_Assignment", - "AdditionalProperties": { - "notificationRecipients": ["test@example.com"] - } - }, - { - "Id": "Notification_Admin_Admin_Eligibility", - "AdditionalProperties": { - "notificationRecipients": ["test@example.com"] - } - } - ] - } - ], - "service_plans": [ - { "ServicePlanName": "EXCHANGE_S_FOUNDATION", - "ServicePlanId": "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" - }, - { "ServicePlanName": "AAD_PREMIUM_P2", - "ServicePlanId": "c7d91867-e1ce-4402-8d4f-22188b44b6c2" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "0 role(s) without notification e-mail configured for role assignments found" -} - -test_notificationRecipients_Incorrect_V1 if { - PolicyId := "MS.AAD.16.1v1" - - Output := tests with input as { - "privileged_roles": [ - { - "RoleTemplateId": "1D2EE3F0-90D3-4764-8AF8-BE81FE9D4D71", - "DisplayName": "Global Administrator", - "Rules": [ - { - "Id": "Notification_Admin_Admin_Assignment", - "AdditionalProperties": { - "notificationRecipients": [] - } - }, - { - "Id": "Notification_Admin_Admin_Eligibility", - "AdditionalProperties": { - "notificationRecipients": ["test@example.com"] - } - } - ] - } - ], - "service_plans": [ - { "ServicePlanName": "EXCHANGE_S_FOUNDATION", - "ServicePlanId": "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" - }, - { "ServicePlanName": "AAD_PREMIUM_P2", - "ServicePlanId": "c7d91867-e1ce-4402-8d4f-22188b44b6c2" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "1 role(s) without notification e-mail configured for role assignments found:
Global Administrator" -} - -test_notificationRecipients_Incorrect_V2 if { - PolicyId := "MS.AAD.16.1v1" - - Output := tests with input as { - "privileged_roles": [ - { - "RoleTemplateId": "1D2EE3F0-90D3-4764-8AF8-BE81FE9D4D71", - "DisplayName": "Global Administrator", - "Rules": [ - { - "Id": "Notification_Admin_Admin_Assignment", - "AdditionalProperties": { - "notificationRecipients": ["test@example.com"] - } - }, - { - "Id": "Notification_Admin_Admin_Eligibility", - "AdditionalProperties": { - "notificationRecipients": [] - } - } - ] - } - ], - "service_plans": [ - { "ServicePlanName": "EXCHANGE_S_FOUNDATION", - "ServicePlanId": "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" - }, - { "ServicePlanName": "AAD_PREMIUM_P2", - "ServicePlanId": "c7d91867-e1ce-4402-8d4f-22188b44b6c2" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "1 role(s) without notification e-mail configured for role assignments found:
Global Administrator" -} - -test_notificationRecipients_Incorrect_V3 if { - PolicyId := "MS.AAD.16.1v1" - - Output := tests with input as { - "privileged_roles": [ - { - "RoleTemplateId": "1D2EE3F0-90D3-4764-8AF8-BE81FE9D4D71", - "DisplayName": "Global Administrator", - "Rules": [ - { - "Id": "Notification_Admin_Admin_Assignment", - "AdditionalProperties": { - "notificationRecipients": [] - } - }, - { - "Id": "Notification_Admin_Admin_Eligibility", - "AdditionalProperties": { - "notificationRecipients": [] - } - } - ] - } - ], - "service_plans": [ - { "ServicePlanName": "EXCHANGE_S_FOUNDATION", - "ServicePlanId": "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" - }, - { "ServicePlanName": "AAD_PREMIUM_P2", - "ServicePlanId": "c7d91867-e1ce-4402-8d4f-22188b44b6c2" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "1 role(s) without notification e-mail configured for role assignments found:
Global Administrator" -} - -test_Id_Correct_V1 if { - PolicyId := "MS.AAD.16.2v1" - - Output := tests with input as { - "privileged_roles": [ - { - "RoleTemplateId": "1D2EE3F0-90D3-4764-8AF8-BE81FE9D4D71", - "DisplayName": "Global Administrator", - "Rules": [ - { - "Id": "Notification_Admin_EndUser_Assignment", - "AdditionalProperties": { - "notificationType": "Email", - "notificationRecipients": ["test@example.com"] - } - } - ] - } - ], - "service_plans": [ - { "ServicePlanName": "EXCHANGE_S_FOUNDATION", - "ServicePlanId": "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" - }, - { "ServicePlanName": "AAD_PREMIUM_P2", - "ServicePlanId": "c7d91867-e1ce-4402-8d4f-22188b44b6c2" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_Id_Correct_V2 if { - PolicyId := "MS.AAD.16.2v1" - - Output := tests with input as { - "privileged_roles": [ - { - "RoleTemplateId": "1D2EE3F0-90D3-4764-8AF8-BE81FE9D4D71", - "DisplayName": "Global Administrator", - "Rules": [ - { - "Id": "Notification_Admin_EndUser_Assignment", - "AdditionalProperties": { - "notificationType": "", - "notificationRecipients": ["test@example.com"] - } - } - ] - } - ], - "service_plans": [ - { "ServicePlanName": "EXCHANGE_S_FOUNDATION", - "ServicePlanId": "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" - }, - { "ServicePlanName": "AAD_PREMIUM_P2", - "ServicePlanId": "c7d91867-e1ce-4402-8d4f-22188b44b6c2" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement met" -} - -test_Id_Incorrect if { - PolicyId := "MS.AAD.16.2v1" - - Output := tests with input as { - "privileged_roles": [ - { - "RoleTemplateId": "1D2EE3F0-90D3-4764-8AF8-BE81FE9D4D71", - "DisplayName": "Global Administrator", - "Rules": [ - { - "Id": "Notification_Admin_EndUser_Assignment", - "AdditionalProperties": { - "notificationType": "Email", - "notificationRecipients": [] - } - } - ] - } - ], - "service_plans": [ - { "ServicePlanName": "EXCHANGE_S_FOUNDATION", - "ServicePlanId": "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" - }, - { "ServicePlanName": "AAD_PREMIUM_P2", - "ServicePlanId": "c7d91867-e1ce-4402-8d4f-22188b44b6c2" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Requirement not met" -} - -test_DisplayName_Correct if { - PolicyId := "MS.AAD.16.3v1" - - Output := tests with input as { - "privileged_roles": [ - { - "RoleTemplateId": "1D2EE3F0-90D3-4764-8AF8-BE81FE9D4D71", - "DisplayName": "Global Administrator", - "Rules": [ - { - "Id": "Notification_Admin_EndUser_Assignment", - "AdditionalProperties": { - "notificationType": "Email", - "notificationRecipients": [] - } - } - ] - } - ], - "service_plans": [ - { "ServicePlanName": "EXCHANGE_S_FOUNDATION", - "ServicePlanId": "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" - }, - { "ServicePlanName": "AAD_PREMIUM_P2", - "ServicePlanId": "c7d91867-e1ce-4402-8d4f-22188b44b6c2" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "0 role(s) without notification e-mail configured for role activations found" -} - -test_DisplayName_Incorrect if { - PolicyId := "MS.AAD.16.3v1" - - Output := tests with input as { - "privileged_roles": [ - { - "RoleTemplateId": "1D2EE3F0-90D3-4764-8AF8-BE81FE9D4D71", - "DisplayName": "Cloud Administrator", - "Rules": [ - { - "Id": "Notification_Admin_EndUser_Assignment", - "AdditionalProperties": { - "notificationType": "Email", - "notificationRecipients": [] - } - } - ] - } - ], - "service_plans": [ - { "ServicePlanName": "EXCHANGE_S_FOUNDATION", - "ServicePlanId": "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" - }, - { "ServicePlanName": "AAD_PREMIUM_P2", - "ServicePlanId": "c7d91867-e1ce-4402-8d4f-22188b44b6c2" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "1 role(s) without notification e-mail configured for role activations found:
Cloud Administrator" -} \ No newline at end of file diff --git a/Testing/Unit/Rego/AAD/AADConfig_17_test.rego b/Testing/Unit/Rego/AAD/AADConfig_17_test.rego deleted file mode 100644 index 84c87e31dd..0000000000 --- a/Testing/Unit/Rego/AAD/AADConfig_17_test.rego +++ /dev/null @@ -1,186 +0,0 @@ -package aad -import future.keywords - - -# -# Policy 1 -#-- -test_ConditionalAccessPolicies_Correct if { - PolicyId := "MS.AAD.17.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"] - } - }, - "GrantControls": { - "BuiltInControls": ["domainJoinedDevice"] - }, - "State": "enabled", - "DisplayName": "AD Joined Device Authentication Policy" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "1 conditional access policy(s) found that meet(s) all requirements:
AD Joined Device Authentication Policy. View all CA policies." -} - -test_BuiltInControls_Correct if { - PolicyId := "MS.AAD.17.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"] - } - }, - "GrantControls": { - "BuiltInControls": ["compliantDevice"] - }, - "State": "enabled", - "DisplayName": "AD Joined Device Authentication Policy" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "1 conditional access policy(s) found that meet(s) all requirements:
AD Joined Device Authentication Policy. View all CA policies." -} - -test_IncludeApplications_Incorrect if { - PolicyId := "MS.AAD.17.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": [""] - }, - "Users": { - "IncludeUsers": ["All"] - } - }, - "GrantControls": { - "BuiltInControls": ["compliantDevice"] - }, - "State": "enabled", - "DisplayName": "AD Joined Device Authentication Policy" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." -} - -test_IncludeUsers_Incorrect if { - PolicyId := "MS.AAD.17.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": [""] - } - }, - "GrantControls": { - "BuiltInControls": ["compliantDevice"] - }, - "State": "enabled", - "DisplayName": "AD Joined Device Authentication Policy" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." -} - -test_BuiltInControls_Incorrect if { - PolicyId := "MS.AAD.17.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"] - } - }, - "GrantControls": { - "BuiltInControls": [""] - }, - "State": "enabled", - "DisplayName": "AD Joined Device Authentication Policy" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." -} - -test_State_Incorrect if { - PolicyId := "MS.AAD.17.1v1" - - Output := tests with input as { - "conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "IncludeApplications": ["All"] - }, - "Users": { - "IncludeUsers": ["All"] - } - }, - "GrantControls": { - "BuiltInControls": ["compliantDevice"] - }, - "State": "disabled", - "DisplayName": "AD Joined Device Authentication Policy" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." -} \ No newline at end of file diff --git a/Testing/Unit/Rego/AAD/AADConfig_18_test.rego b/Testing/Unit/Rego/AAD/AADConfig_18_test.rego deleted file mode 100644 index 0455c806cf..0000000000 --- a/Testing/Unit/Rego/AAD/AADConfig_18_test.rego +++ /dev/null @@ -1,159 +0,0 @@ -package aad -import future.keywords -import data.report.utils.NotCheckedDetails - -# -# Policy 1 -#-- -test_AllowInvitesFrom_Correct if { - PolicyId := "MS.AAD.18.1v1" - - Output := tests with input as { - "authorization_policies": [ - { - "Id": "authorizationPolicy", - "AllowInvitesFrom": "adminsAndGuestInviters" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Permission level set to \"adminsAndGuestInviters\" (authorizationPolicy)" -} - -test_AllowInvitesFrom_Incorrect if { - PolicyId := "MS.AAD.18.1v1" - - Output := tests with input as { - "authorization_policies": [ - { - "Id": "authorizationPolicy", - "AllowInvitesFrom": "Bad value" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Permission level set to \"Bad value\" (authorizationPolicy)" -} - -# -# Policy 2 -#-- -test_NotImplemented_Correct if { - PolicyId := "MS.AAD.18.2v1" - Output := tests with input as { } - - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == NotCheckedDetails(PolicyId) -} - -# -# Policy 3 -#-- -test_GuestUserRoleId_Correct_V1 if { - PolicyId := "MS.AAD.18.3v1" - - Output := tests with input as { - "authorization_policies": [ - { - "GuestUserRoleId" : "2af84b1e-32c8-42b7-82bc-daa82404023b", - "Id" : "authorizationPolicy" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Permission level set to \"Restricted access\" (authorizationPolicy)" -} - -test_GuestUserRoleId_Correct_V2 if { - PolicyId := "MS.AAD.18.3v1" - - Output := tests with input as { - "authorization_policies": [ - { - "GuestUserRoleId" : "10dae51f-b6af-4016-8d66-8c2a99b929b3", - "Id" : "authorizationPolicy" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Permission level set to \"Limited access\" (authorizationPolicy)" -} - -test_GuestUserRoleId_Incorrect_V1 if { - PolicyId := "MS.AAD.18.3v1" - - Output := tests with input as { - "authorization_policies": [ - { - "GuestUserRoleId" : "a0b1b346-4d3e-4e8b-98f8-753987be4970", - "Id" : "authorizationPolicy" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Permission level set to \"Same as member users\" (authorizationPolicy)" -} - -test_GuestUserRoleId_Incorrect_V2 if { - PolicyId := "MS.AAD.18.3v1" - - Output := tests with input as { - "authorization_policies": [ - { - "GuestUserRoleId" : "Hello world", - "Id" : "authorizationPolicy" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "Permission level set to \"Unknown\" (authorizationPolicy)" -} - -test_GuestUserRoleId_Incorrect_V3 if { - PolicyId := "MS.AAD.18.3v1" - - Output := tests with input as { - "authorization_policies": [ - { - "GuestUserRoleId" : "Hello world", - "Id" : "policy 1" - }, - { - "GuestUserRoleId" : "2af84b1e-32c8-42b7-82bc-daa82404023b", - "Id" : "policy 2" - } - ] - } - - RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] - - count(RuleOutput) == 1 - not RuleOutput[0].RequirementMet -} \ No newline at end of file diff --git a/sample-config-files/aad-config.yaml b/sample-config-files/aad-config.yaml index 69a9dac91c..3218cd497c 100644 --- a/sample-config-files/aad-config.yaml +++ b/sample-config-files/aad-config.yaml @@ -7,7 +7,7 @@ Description: | conditional access policy checks that normally would not pass if exclusions are present. These parameters support operational use cases for having backup or break glass account exclusions to global user policies without - failing best practices. Any exemptions and their risks should be carefully + failing best practices. Any exemptions and their risks should be carefully considered and documented as part of an organization's cybersecurity risk management program process and practices. This example includes the following design choices for illustrative purposes: @@ -30,17 +30,15 @@ OutReportName: BaselineReports GlobalVars: # For cross product variables AllProductVar: value_example Aad: -# All AAD specific variables go here - Policy2_1_1: &CommonExclusions +# All AAD specific variables go here + MS.AAD.1.1v1: &CommonExclusions CapExclusions: Users: - fc29f4a8-2b27-4d1e-898e-cfacb98bd8f8 Groups: - 08adb07a-956f-450e-b41c-81e92e3db2c4 - Policy2_2_1: *CommonExclusions - Policy2_3_1: *CommonExclusions - Policy2_4_1: *CommonExclusions - Policy2_9_1: *CommonExclusions - Policy2_10_1: *CommonExclusions + MS.AAD.2.1v1: *CommonExclusions + MS.AAD.2.3v1: *CommonExclusions + MS.AAD.3.2v1: *CommonExclusions #SharePoint: #Teams: \ No newline at end of file From 2ade0e43e190bda26ad35a103286b6d442bd444d Mon Sep 17 00:00:00 2001 From: Richard Crutchfield Date: Wed, 5 Jul 2023 12:03:06 -0400 Subject: [PATCH 13/33] Differentiate policy id vs implementation (#414) --- .../Modules/CreateReport/CreateReport.psm1 | 2 +- .../CreateReportStubs/TestResults.json | 5152 +++++++++-------- .../Import-SecureBaseline.Tests.ps1 | 4 +- .../CreateReport/New-Report.Tests.ps1 | 6 +- 4 files changed, 2841 insertions(+), 2323 deletions(-) diff --git a/PowerShell/ScubaGear/Modules/CreateReport/CreateReport.psm1 b/PowerShell/ScubaGear/Modules/CreateReport/CreateReport.psm1 index 8b11beabf8..9462e35710 100644 --- a/PowerShell/ScubaGear/Modules/CreateReport/CreateReport.psm1 +++ b/PowerShell/ScubaGear/Modules/CreateReport/CreateReport.psm1 @@ -236,7 +236,7 @@ function Import-SecureBaseline{ $Group.GroupName = $GroupName.Split(".")[1].Trim() # 1 to remove the leading space $Group.Controls = @() - $IdRegex = "#### MS\.[$($Product.ToUpper())]+\.$($Group.GroupNumber)\." + $IdRegex = "#### MS\.[$($Product.ToUpper())]+\.$($Group.GroupNumber)\.\d+v\d+\s*$" # Select-String line numbers aren't 0-indexed, hence the "-1" on the next line $LineNumbers = Select-String $IdRegex "$($BaselinePath)$($Product).md" | ForEach-Object {$_."LineNumber"-1} diff --git a/Testing/Unit/PowerShell/CreateReport/CreateReportStubs/TestResults.json b/Testing/Unit/PowerShell/CreateReport/CreateReportStubs/TestResults.json index 917da84cd7..59cdafa4ca 100644 --- a/Testing/Unit/PowerShell/CreateReport/CreateReportStubs/TestResults.json +++ b/Testing/Unit/PowerShell/CreateReport/CreateReportStubs/TestResults.json @@ -1,2318 +1,2836 @@ -[ - { - "ActualValue": "", - "Commandlet": [ - "Get-MgSubscribedSku", - "Get-PrivilegedUser" - ], - "Criticality": "Shall", - "PolicyId": "MS.AAD.12.1v1", - "ReportDetails": "0 admin(s) that are not cloud-only found", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Shall/Not-Implemented", - "PolicyId": "MS.AAD.4.2v1", - "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Shall/Not-Implemented", - "PolicyId": "MS.AAD.4.3v1", - "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Shall/Not-Implemented", - "PolicyId": "MS.AAD.4.4v1", - "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Shall/Not-Implemented", - "PolicyId": "MS.AAD.5.1v1", - "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Shall/Not-Implemented", - "PolicyId": "MS.AAD.5.4v1", - "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Shall/Not-Implemented", - "PolicyId": "MS.AAD.8.1v1", - "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Should/Not-Implemented", - "PolicyId": "MS.AAD.18.2v1", - "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Should/Not-Implemented", - "PolicyId": "MS.AAD.2.2v1", - "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Should/Not-Implemented", - "PolicyId": "MS.AAD.5.2v1", - "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Should/Not-Implemented", - "PolicyId": "MS.AAD.5.3v1", - "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", - "RequirementMet": false - }, - { - "ActualValue": { - "all_allow_invite_values": [ - { - "AllowInvitesFromValue": "everyone", - "PolicyId": "authorizationPolicy" - } - ] - }, - "Commandlet": [ - "Get-MgPolicyAuthorizationPolicy" - ], - "Criticality": "Should", - "PolicyId": "MS.AAD.18.1v1", - "ReportDetails": "Permission level set to \"everyone\" (authorizationPolicy)", - "RequirementMet": false - }, - { - "ActualValue": { - "all_allowed_create_values": [ - { - "DefaultUser_AllowedToCreateApps": true, - "PolicyId": "authorizationPolicy" - } - ] - }, - "Commandlet": [ - "Get-MgPolicyAuthorizationPolicy" - ], - "Criticality": "Shall", - "PolicyId": "MS.AAD.6.1v1", - "ReportDetails": "1 authorization policies found that allow non-admin users to register third-party applications:
authorizationPolicy", - "RequirementMet": false - }, - { - "ActualValue": { - "all_consent_policies": [ - { - "IsEnabled": true, - "PolicyId": null - } - ] - }, - "Commandlet": [ - "Get-MgPolicyAdminConsentRequestPolicy" - ], - "Criticality": "Shall", - "PolicyId": "MS.AAD.7.2v1", - "ReportDetails": "Requirement met", - "RequirementMet": true - }, - { - "ActualValue": { - "all_grant_policy_values": [ - { - "DefaultUser_DefaultGrantPolicy": [ - "ManagePermissionGrantsForSelf.microsoft-user-default-legacy" - ], - "PolicyId": "authorizationPolicy" - } - ] - }, - "Commandlet": [ - "Get-MgPolicyAuthorizationPolicy" - ], - "Criticality": "Shall", - "PolicyId": "MS.AAD.7.1v1", - "ReportDetails": "1 authorization policies found that allow non-admin users to consent to third-party applications:
authorizationPolicy", - "RequirementMet": false - }, - { - "ActualValue": { - "all_roleid_values": [ - { - "GuestUserRoleId": "10dae51f-b6af-4016-8d66-8c2a99b929b3", - "GuestUserRoleIdString": "Limited access", - "Id": "authorizationPolicy" - } - ] - }, - "Commandlet": [ - "Get-MgPolicyAuthorizationPolicy" - ], - "Criticality": "Should", - "PolicyId": "MS.AAD.18.3v1", - "ReportDetails": "Permission level set to \"Limited access\" (authorizationPolicy)", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-MgIdentityConditionalAccessPolicy" - ], - "Criticality": "Shall", - "PolicyId": "MS.AAD.9.1v1", - "ReportDetails": "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies.", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-MgIdentityConditionalAccessPolicy" - ], - "Criticality": "Should", - "PolicyId": "MS.AAD.17.1v1", - "ReportDetails": "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies.", - "RequirementMet": false - }, - { - "ActualValue": [ - "Addam Schroll", - "Andrew Huynh", - "Grant Dasher", - "Nanda Katikaneni", - "Shanti Satyapal", - "Ted Kolovos", - "Thomas Comeau" - ], - "Commandlet": [ - "Get-MgSubscribedSku", - "Get-PrivilegedUser" - ], - "Criticality": "Shall", - "PolicyId": "MS.AAD.11.1v1", - "ReportDetails": "7 global admin(s) found:
Addam Schroll, Andrew Huynh, Grant Dasher, Nanda Katikaneni, Shanti Satyapal, Ted Kolovos, Thomas Comeau", - "RequirementMet": false - }, - { - "ActualValue": [ - "Application Administrator", - "Cloud Application Administrator", - "Hybrid Identity Administrator", - "Privileged Role Administrator", - "SharePoint Administrator" - ], - "Commandlet": [ - "Get-MgSubscribedSku", - "Get-PrivilegedRole" - ], - "Criticality": "Should", - "PolicyId": "MS.AAD.15.1v1", - "ReportDetails": "5 role(s) that do not require approval to activate found:
Application Administrator, Cloud Application Administrator, Hybrid Identity Administrator, Privileged Role Administrator, SharePoint Administrator", - "RequirementMet": false - }, - { - "ActualValue": [ - "Exchange Administrator", - "Global Administrator", - "Privileged Role Administrator", - "SharePoint Administrator" - ], - "Commandlet": [ - "Get-MgSubscribedSku", - "Get-PrivilegedRole" - ], - "Criticality": "Shall", - "PolicyId": "MS.AAD.14.2v1", - "ReportDetails": "4 role(s) assigned to users outside of PIM:
Exchange Administrator, Global Administrator, Privileged Role Administrator, SharePoint Administrator", - "RequirementMet": false - }, - { - "ActualValue": [ - "Global Administrator", - "SharePoint Administrator", - "User Administrator" - ], - "Commandlet": [ - "Get-MgSubscribedSku", - "Get-PrivilegedRole" - ], - "Criticality": "Shall", - "PolicyId": "MS.AAD.14.1v1", - "ReportDetails": "3 role(s) configured to allow permanent active assignment or expiration period too long:
Global Administrator, SharePoint Administrator, User Administrator", - "RequirementMet": false - }, - { - "ActualValue": [ - "Live - Block legacy authentication" - ], - "Commandlet": [ - "Get-MgIdentityConditionalAccessPolicy" - ], - "Criticality": "Shall", - "PolicyId": "MS.AAD.1.1v1", - "ReportDetails": "1 conditional access policy(s) found that meet(s) all requirements:
Live - Block legacy authentication. View all CA policies.", - "RequirementMet": true - }, - { - "ActualValue": [ - "Live - MFA Required for Everyone" - ], - "Commandlet": [ - "Get-MgIdentityConditionalAccessPolicy" - ], - "Criticality": "Shall", - "PolicyId": "MS.AAD.4.1v1", - "ReportDetails": "1 conditional access policy(s) found that meet(s) all requirements:
Live - MFA Required for Everyone. View all CA policies.", - "RequirementMet": true - }, - { - "ActualValue": [ - "Live - MFA required for Highly Privileged Roles" - ], - "Commandlet": [ - "Get-MgSubscribedSku", - "Get-PrivilegedRole", - "Get-MgIdentityConditionalAccessPolicy" - ], - "Criticality": "Shall", - "PolicyId": "MS.AAD.13.1v1", - "ReportDetails": "1 conditional access policy(s) found that meet(s) all requirements:
Live - MFA required for Highly Privileged Roles. View all CA policies.", - "RequirementMet": true - }, - { - "ActualValue": [ - "Live - Prevent Persistent Sessions u0026 Enforce Sign-in Frequency" - ], - "Commandlet": [ - "Get-MgIdentityConditionalAccessPolicy" - ], - "Criticality": "Shall", - "PolicyId": "MS.AAD.10.1v1", - "ReportDetails": "1 conditional access policy(s) found that meet(s) all requirements:
Live - Prevent Persistent Sessions u0026 Enforce Sign-in Frequency. View all CA policies.", - "RequirementMet": true - }, - { - "ActualValue": [ - "Live - Risky Sign Ins Block Access" - ], - "Commandlet": [ - "Get-MgIdentityConditionalAccessPolicy" - ], - "Criticality": "Shall", - "PolicyId": "MS.AAD.3.1v1", - "ReportDetails": "1 conditional access policy(s) found that meet(s) all requirements:
Live - Risky Sign Ins Block Access. View all CA policies.", - "RequirementMet": true - }, - { - "ActualValue": [ - "Live - Risky Users Block Access" - ], - "Commandlet": [ - "Get-MgIdentityConditionalAccessPolicy" - ], - "Criticality": "Shall", - "PolicyId": "MS.AAD.2.1v1", - "ReportDetails": "1 conditional access policy(s) found that meet(s) all requirements:
Live - Risky Users Block Access. View all CA policies.", - "RequirementMet": true - }, - { - "ActualValue": [ - "Privileged Role Administrator" - ], - "Commandlet": [ - "Get-MgSubscribedSku", - "Get-PrivilegedRole" - ], - "Criticality": "Shall", - "PolicyId": "MS.AAD.16.2v1", - "ReportDetails": "Requirement met", - "RequirementMet": true - }, - { - "ActualValue": [ - "Privileged Role Administrator" - ], - "Commandlet": [ - "Get-MgSubscribedSku", - "Get-PrivilegedRole" - ], - "Criticality": "Should", - "PolicyId": "MS.AAD.16.3v1", - "ReportDetails": "1 role(s) without notification e-mail configured for role activations found:
Privileged Role Administrator", - "RequirementMet": false - }, - { - "ActualValue": [ - "Privileged Role Administrator", - "User Administrator" - ], - "Commandlet": [ - "Get-MgSubscribedSku", - "Get-PrivilegedRole" - ], - "Criticality": "Shall", - "PolicyId": "MS.AAD.16.1v1", - "ReportDetails": "2 role(s) without notification e-mail configured for role assignments found:
Privileged Role Administrator, User Administrator", - "RequirementMet": false - }, - { - "ActualValue": [ - { - "Name": "EnableGroupSpecificConsent", - "SettingsGroup": "Consent Policy Settings", - "Value": "false" - } - ], - "Commandlet": [ - "Get-MgDirectorySetting" - ], - "Criticality": "Shall", - "PolicyId": "MS.AAD.7.3v1", - "ReportDetails": "Requirement met", - "RequirementMet": true - }, - { - "ActualValue": false, - "Commandlet": [ - "Get-AntiPhishPolicy" - ], - "Control": "Defender 2.5", - "Criticality": "Shall", - "ReportDetails": "Requirement not met", - "Requirement": "All safety tips SHALL be enabled: domain impersonation default policy", - "RequirementMet": false - }, - { - "ActualValue": false, - "Commandlet": [ - "Get-AntiPhishPolicy" - ], - "Control": "Defender 2.5", - "Criticality": "Shall", - "ReportDetails": "Requirement not met", - "Requirement": "All safety tips SHALL be enabled: user impersonation default policy", - "RequirementMet": false - }, - { - "ActualValue": false, - "Commandlet": [ - "Get-AntiPhishPolicy" - ], - "Control": "Defender 2.5", - "Criticality": "Shall", - "ReportDetails": "Requirement not met", - "Requirement": "All safety tips SHALL be enabled: user impersonation unusual characters default policy", - "RequirementMet": false - }, - { - "ActualValue": false, - "Commandlet": [ - "Get-AntiPhishPolicy" - ], - "Criticality": "Shall", - "PolicyId": "MS.DEFENDER.5.8v1", - "ReportDetails": "Requirement not met", - "RequirementMet": false - }, - { - "ActualValue": true, - "Commandlet": [ - "Get-AntiPhishPolicy" - ], - "Control": "Defender 2.5", - "Criticality": "Shall", - "ReportDetails": "Requirement met", - "Requirement": "All safety tips SHALL be enabled: \"?\" for unauthenticated senders for spoof default policy", - "RequirementMet": true - }, - { - "ActualValue": true, - "Commandlet": [ - "Get-AntiPhishPolicy" - ], - "Control": "Defender 2.5", - "Criticality": "Shall", - "ReportDetails": "Requirement met", - "Requirement": "All safety tips SHALL be enabled: \"via\" tag default policy", - "RequirementMet": true - }, - { - "ActualValue": true, - "Commandlet": [ - "Get-HostedContentFilterPolicy" - ], - "Control": "Defender 2.6", - "Criticality": "Shall", - "ReportDetails": "Requirement met", - "Requirement": "Zero-hour auto purge (ZAP) SHALL be enabled for phishing: default policy", - "RequirementMet": true - }, - { - "ActualValue": true, - "Commandlet": [ - "Get-HostedContentFilterPolicy" - ], - "Control": "Defender 2.6", - "Criticality": "Shall", - "ReportDetails": "Requirement met", - "Requirement": "Zero-hour auto purge (ZAP) SHALL be enabled for spam messages: default policy", - "RequirementMet": true - }, - { - "ActualValue": true, - "Commandlet": [ - "Get-HostedContentFilterPolicy" - ], - "Criticality": "Shall", - "PolicyId": "MS.DEFENDER.6.7v1", - "ReportDetails": "Requirement met", - "RequirementMet": true - }, - { - "ActualValue": true, - "Commandlet": [ - "Get-HostedContentFilterPolicy" - ], - "Criticality": "Should", - "PolicyId": "MS.DEFENDER.6.6v1", - "ReportDetails": "Requirement met", - "RequirementMet": true - }, - { - "ActualValue": 7, - "Commandlet": [ - "Get-HostedContentFilterPolicy" - ], - "Criticality": "Should", - "PolicyId": "MS.DEFENDER.6.1v1", - "ReportDetails": "Requirement not met", - "RequirementMet": false - }, - { - "ActualValue": 15, - "Commandlet": [ - "Get-HostedContentFilterPolicy" - ], - "Criticality": "Should", - "PolicyId": "MS.DEFENDER.6.5v1", - "ReportDetails": "Requirement not met", - "RequirementMet": false - }, - { - "ActualValue": "MoveToJmf", - "Commandlet": [ - "Get-AntiPhishPolicy" - ], - "Criticality": "Shall", - "PolicyId": "MS.DEFENDER.5.7v1", - "ReportDetails": "Requirement not met", - "RequirementMet": false - }, - { - "ActualValue": "MoveToJmf", - "Commandlet": [ - "Get-HostedContentFilterPolicy" - ], - "Control": "Defender 2.6", - "Criticality": "Shall", - "ReportDetails": "Requirement met", - "Requirement": "High confidence spam SHALL be moved to either the junk email folder or the quarantine folder: default policy", - "RequirementMet": true - }, - { - "ActualValue": "MoveToJmf", - "Commandlet": [ - "Get-HostedContentFilterPolicy" - ], - "Criticality": "Shall", - "PolicyId": "MS.DEFENDER.6.2v1", - "ReportDetails": "Requirement met", - "RequirementMet": true - }, - { - "ActualValue": "MoveToJmf", - "Commandlet": [ - "Get-HostedContentFilterPolicy" - ], - "Criticality": "Shall", - "PolicyId": "MS.DEFENDER.6.3v1", - "ReportDetails": "Requirement not met", - "RequirementMet": false - }, - { - "ActualValue": "MoveToJmf", - "Commandlet": [ - "Get-HostedContentFilterPolicy" - ], - "Criticality": "Should", - "PolicyId": "MS.DEFENDER.6.4v1", - "ReportDetails": "Requirement met", - "RequirementMet": true - }, - { - "ActualValue": "NoAction", - "Commandlet": [ - "Get-AntiPhishPolicy" - ], - "Control": "Defender 2.5", - "Criticality": "Shall", - "ReportDetails": "Requirement not met", - "Requirement": "Message action SHALL be set to quarantine if the message is detected as impersonated: domains default policy", - "RequirementMet": false - }, - { - "ActualValue": "NoAction", - "Commandlet": [ - "Get-AntiPhishPolicy" - ], - "Control": "Defender 2.5", - "Criticality": "Shall", - "ReportDetails": "Requirement not met", - "Requirement": "Message action SHALL be set to quarantine if the message is detected as impersonated: mailbox default policy", - "RequirementMet": false - }, - { - "ActualValue": "NoAction", - "Commandlet": [ - "Get-AntiPhishPolicy" - ], - "Criticality": "Shall", - "PolicyId": "MS.DEFENDER.5.6v1", - "ReportDetails": "Requirement not met", - "RequirementMet": false - }, - { - "ActualValue": "Quarantine", - "Commandlet": [ - "Get-HostedContentFilterPolicy" - ], - "Control": "Defender 2.6", - "Criticality": "Shall", - "ReportDetails": "Requirement met", - "Requirement": "High confidence phishing SHALL be quarantined: default policy", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Shall/Not-Implemented", - "PolicyId": "MS.DEFENDER.10.2v1", - "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Shall/Not-Implemented", - "PolicyId": "MS.DEFENDER.10.3v1", - "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Should/Not-Implemented", - "PolicyId": "MS.DEFENDER.2.5v1", - "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Should/Not-Implemented", - "PolicyId": "MS.DEFENDER.2.6v1", - "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Should/Not-Implemented", - "PolicyId": "MS.DEFENDER.9.2v1", - "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-AntiPhishPolicy" - ], - "Control": "Defender 2.5", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "All safety tips SHOULD be enabled: \"?\" for unauthenticated senders for spoof non-default policies", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-AntiPhishPolicy" - ], - "Control": "Defender 2.5", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "All safety tips SHOULD be enabled: \"via\" tag non-default policies", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-AntiPhishPolicy" - ], - "Control": "Defender 2.5", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "All safety tips SHOULD be enabled: domain impersonation non-default policies", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-AntiPhishPolicy" - ], - "Control": "Defender 2.5", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "All safety tips SHOULD be enabled: first contact non-default policies", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-AntiPhishPolicy" - ], - "Control": "Defender 2.5", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "All safety tips SHOULD be enabled: user impersonation non-default policies", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-AntiPhishPolicy" - ], - "Control": "Defender 2.5", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "All safety tips SHOULD be enabled: user impersonation unusual characters non-default policies", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-AntiPhishPolicy" - ], - "Control": "Defender 2.5", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "Mail classified as spoofed SHOULD be quarantined: non-default policies", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-AntiPhishPolicy" - ], - "Control": "Defender 2.5", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "Message action SHOULD be set to quarantine if the message is detected as impersonated: domains non-default policies", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-AntiPhishPolicy" - ], - "Control": "Defender 2.5", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "Message action SHOULD be set to quarantine if the message is detected as impersonated: mailbox non-default policies", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-AntiPhishPolicy" - ], - "Control": "Defender 2.5", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "Message action SHOULD be set to quarantine if the message is detected as impersonated: users non-default policies", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-AntiPhishPolicy" - ], - "Criticality": "Should", - "PolicyId": "MS.DEFENDER.5.1v1", - "ReportDetails": "No users are included for targeted user protection.", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-AntiPhishPolicy" - ], - "Criticality": "Should", - "PolicyId": "MS.DEFENDER.5.2v1", - "ReportDetails": "Requirement not met", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-AntiPhishPolicy" - ], - "Criticality": "Should", - "PolicyId": "MS.DEFENDER.5.3v1", - "ReportDetails": "The Custom Domains protection policies: Enabled, EnableTargetedDomainsProtection, and TargetedDomainsToProtect are not set correctly", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-AntiPhishPolicy" - ], - "Criticality": "Should", - "PolicyId": "MS.DEFENDER.5.5v1", - "ReportDetails": "Requirement not met", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-DLPCompliancePolicy" - ], - "Control": "Defender 2.2", - "Criticality": "Should", - "ReportDetails": "No policy found that applies to OneDrive.", - "Requirement": "The custom policy SHOULD be applied in OneDrive", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-DLPCompliancePolicy" - ], - "Control": "Defender 2.2", - "Criticality": "Should", - "ReportDetails": "No policy found that applies to SharePoint.", - "Requirement": "The custom policy SHOULD be applied in SharePoint", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-DLPCompliancePolicy" - ], - "Control": "Defender 2.2", - "Criticality": "Should", - "ReportDetails": "No policy found that applies to Teams.", - "Requirement": "The custom policy SHOULD be applied in Teams", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-DLPCompliancePolicy" - ], - "Criticality": "Should", - "PolicyId": "MS.DEFENDER.2.2v1", - "ReportDetails": "No policy found that applies to Exchange.", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-DlpComplianceRule" - ], - "Control": "Defender 2.2", - "Criticality": "Shall", - "ReportDetails": "No matching rule found for Credit Card Number", - "Requirement": "A custom policy SHALL be configured to protect PII and sensitive information, as defined by the agency: Credit Card Number", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-DlpComplianceRule" - ], - "Control": "Defender 2.2", - "Criticality": "Shall", - "ReportDetails": "No matching rule found for U.S. Individual Taxpayer Identification Number (ITIN)", - "Requirement": "A custom policy SHALL be configured to protect PII and sensitive information, as defined by the agency: U.S. Individual Taxpayer Identification Number (ITIN)", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-DlpComplianceRule" - ], - "Criticality": "Shall", - "PolicyId": "MS.DEFENDER.2.1v1", - "ReportDetails": "No matching rule found for U.S. Social Security Number (SSN)", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-DlpComplianceRule" - ], - "Criticality": "Should", - "PolicyId": "MS.DEFENDER.2.3v1", - "ReportDetails": "Requirement met", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-DlpComplianceRule" - ], - "Criticality": "Should", - "PolicyId": "MS.DEFENDER.2.4v1", - "ReportDetails": "Requirement met", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-EOPProtectionPolicyRule" - ], - "Control": "Defender 2.1", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "Strict Preset security profiles SHOULD NOT be used", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-EOPProtectionPolicyRule" - ], - "Criticality": "Should", - "PolicyId": "MS.DEFENDER.1.1v1", - "ReportDetails": "Requirement met", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-HostedContentFilterPolicy" - ], - "Control": "Defender 2.6", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "Allowed senders MAY be added but allowed domains SHOULD NOT be added: non-default", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-HostedContentFilterPolicy" - ], - "Control": "Defender 2.6", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "Bulk email SHOULD be moved to either the junk email folder or the quarantine folder: non-default policies", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-HostedContentFilterPolicy" - ], - "Control": "Defender 2.6", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "High confidence phishing SHOULD be quarantined: non-default policies", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-HostedContentFilterPolicy" - ], - "Control": "Defender 2.6", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "High confidence spam SHOULD be moved to either the junk email folder or the quarantine folder: non-default policies", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-HostedContentFilterPolicy" - ], - "Control": "Defender 2.6", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "Phishing SHOULD be quarantined: non-default policies", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-HostedContentFilterPolicy" - ], - "Control": "Defender 2.6", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "Spam SHOULD be moved to either the junk email folder or the quarantine folder: non-default policies", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-HostedContentFilterPolicy" - ], - "Control": "Defender 2.6", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "Spam in quarantine SHOULD be retained for at least 30 days: non-default policies", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-HostedContentFilterPolicy" - ], - "Control": "Defender 2.6", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "Spam safety tips SHOULD be turned on: non-default policies", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-HostedContentFilterPolicy" - ], - "Control": "Defender 2.6", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "The bulk complaint level (BCL) threshold SHOULD be set to six or lower: non-default policies", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-HostedContentFilterPolicy" - ], - "Control": "Defender 2.6", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "Zero-hour auto purge (ZAP) SHOULD be enabled for Spam: non-default", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-HostedContentFilterPolicy" - ], - "Control": "Defender 2.6", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "Zero-hour auto purge (ZAP) SHOULD be enabled for phishing: non-default", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-HostedContentFilterPolicy" - ], - "Control": "Defender 2.6", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "Zero-hour auto purge (ZAP) SHOULD be enabled: non-default", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-HostedContentFilterPolicy" - ], - "Criticality": "Shall", - "PolicyId": "MS.DEFENDER.6.8v1", - "ReportDetails": "Requirement met", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-MalwareFilterPolicy" - ], - "Criticality": "Shall", - "PolicyId": "MS.DEFENDER.3.1v1", - "ReportDetails": "Requirement met", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-MalwareFilterPolicy" - ], - "Criticality": "Should", - "PolicyId": "MS.DEFENDER.4.1v1", - "ReportDetails": "Requirement met", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-SafeAttachmentPolicy", - "Get-SafeAttachmentRule", - "Get-AcceptedDomain" - ], - "Criticality": "Shall", - "PolicyId": "MS.DEFENDER.8.2v1", - "ReportDetails": "No enabled policy found with action set to block that apply to all domains", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-SafeAttachmentPolicy", - "Get-SafeAttachmentRule", - "Get-AcceptedDomain" - ], - "Criticality": "Should", - "PolicyId": "MS.DEFENDER.8.3v1", - "ReportDetails": "No enabled policy found with action set to block and at least one contact specified", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-SafeAttachmentRule", - "Get-AcceptedDomain" - ], - "Criticality": "Shall", - "PolicyId": "MS.DEFENDER.8.1v1", - "ReportDetails": "No policy found that applies to all domains: alexwilber.myo365.site, y2zj1.onmicrosoft.com", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-SafeLinksPolicy", - "Get-SafeLinksRule" - ], - "Criticality": "Shall", - "PolicyId": "MS.DEFENDER.7.2v1", - "ReportDetails": "Requirement not met", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-SafeLinksPolicy", - "Get-SafeLinksRule" - ], - "Criticality": "Shall", - "PolicyId": "MS.DEFENDER.7.3v1", - "ReportDetails": "Requirement not met", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-SafeLinksPolicy", - "Get-SafeLinksRule" - ], - "Criticality": "Shall", - "PolicyId": "MS.DEFENDER.7.4v1", - "ReportDetails": "Requirement not met", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-SafeLinksPolicy", - "Get-SafeLinksRule" - ], - "Criticality": "Shall", - "PolicyId": "MS.DEFENDER.7.5v1", - "ReportDetails": "Requirement not met", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-SafeLinksPolicy", - "Get-SafeLinksRule" - ], - "Criticality": "Shall", - "PolicyId": "MS.DEFENDER.7.6v1", - "ReportDetails": "Requirement not met", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-SafeLinksPolicy", - "Get-SafeLinksRule" - ], - "Criticality": "Shall", - "PolicyId": "MS.DEFENDER.7.7v1", - "ReportDetails": "Requirement not met", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-SafeLinksPolicy", - "Get-SafeLinksRule" - ], - "Criticality": "Shall", - "PolicyId": "MS.DEFENDER.7.8v1", - "ReportDetails": "Requirement not met", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-SafeLinksPolicy", - "Get-SafeLinksRule" - ], - "Criticality": "Shall", - "PolicyId": "MS.DEFENDER.7.9v1", - "ReportDetails": "Requirement not met", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-SafeLinksRule", - "Get-AcceptedDomain" - ], - "Criticality": "Shall", - "PolicyId": "MS.DEFENDER.7.1v1", - "ReportDetails": "No policy found that applies to all domains: alexwilber.myo365.site, y2zj1.onmicrosoft.com", - "RequirementMet": false - }, - { - "ActualValue": [ - "A potentially malicious URL click was detected", - "Malware campaign detected after delivery", - "Messages have been delayed", - "Suspicious Email Forwarding Activity", - "Suspicious connector activity", - "Suspicious email sending patterns detected", - "Tenant restricted from sending unprovisioned email", - "Unusual increase in email reported as phish", - "User restricted from sending email" - ], - "Commandlet": [ - "Get-ProtectionAlert" - ], - "Criticality": "Shall", - "PolicyId": "MS.DEFENDER.9.1v1", - "ReportDetails": "9 disabled required alert(s) found: A potentially malicious URL click was detected, Malware campaign detected after delivery, Messages have been delayed, Suspicious Email Forwarding Activity, Suspicious connector activity, Suspicious email sending patterns detected, Tenant restricted from sending unprovisioned email, Unusual increase in email reported as phish, User restricted from sending email", - "RequirementMet": false - }, - { - "ActualValue": [ - "Default" - ], - "Commandlet": [ - "Get-MalwareFilterPolicy" - ], - "Control": "Defender 2.3", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "Disallowed file types SHALL be determined and set. At a minimum, click-to-run files SHOULD be blocked: cmd files", - "RequirementMet": true - }, - { - "ActualValue": [ - "Default" - ], - "Commandlet": [ - "Get-MalwareFilterPolicy" - ], - "Control": "Defender 2.3", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "Disallowed file types SHALL be determined and set. At a minimum, click-to-run files SHOULD be blocked: vbe files", - "RequirementMet": true - }, - { - "ActualValue": [ - "Default" - ], - "Commandlet": [ - "Get-MalwareFilterPolicy" - ], - "Criticality": "Should", - "PolicyId": "MS.DEFENDER.3.2v1", - "ReportDetails": "Requirement met", - "RequirementMet": true - }, - { - "ActualValue": [ - { - "EnableATPForSPOTeamsODB": true, - "Identity": "Default" - } - ], - "Commandlet": [ - "Get-AtpPolicyForO365" - ], - "Criticality": "Should", - "PolicyId": "MS.DEFENDER.8.4v1", - "ReportDetails": "Requirement met", - "RequirementMet": true - }, - { - "ActualValue": [ - { - "Identity": "Admin Audit Log Settings", - "UnifiedAuditLogIngestionEnabled": true - } - ], - "Commandlet": [ - "Get-AdminAuditLogConfig" - ], - "Criticality": "Shall", - "PolicyId": "MS.DEFENDER.10.1v1", - "ReportDetails": "Requirement met", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Shall/3rd Party", - "PolicyId": "MS.EXO.10.1v1", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Shall/3rd Party", - "PolicyId": "MS.EXO.10.2v1", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Shall/3rd Party", - "PolicyId": "MS.EXO.14.1v1", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Shall/3rd Party", - "PolicyId": "MS.EXO.14.2v1", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Shall/3rd Party", - "PolicyId": "MS.EXO.14.3v1", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Shall/3rd Party", - "PolicyId": "MS.EXO.16.1v1", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Shall/3rd Party", - "PolicyId": "MS.EXO.17.1v1", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Shall/3rd Party", - "PolicyId": "MS.EXO.17.2v1", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Shall/3rd Party", - "PolicyId": "MS.EXO.17.3v1", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Shall/3rd Party", - "PolicyId": "MS.EXO.8.1v1", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Shall/3rd Party", - "PolicyId": "MS.EXO.8.2v1", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Shall/3rd Party", - "PolicyId": "MS.EXO.9.1v1", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Shall/3rd Party", - "PolicyId": "MS.EXO.9.3v1", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Shall/Not-Implemented", - "PolicyId": "MS.EXO.2.1v1", - "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Should/3rd Party", - "PolicyId": "MS.EXO.10.3v1", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Should/3rd Party", - "PolicyId": "MS.EXO.11.1v1", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Should/3rd Party", - "PolicyId": "MS.EXO.11.2v1", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Should/3rd Party", - "PolicyId": "MS.EXO.11.3v1", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Should/3rd Party", - "PolicyId": "MS.EXO.15.1v1", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Should/3rd Party", - "PolicyId": "MS.EXO.15.2v1", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Should/3rd Party", - "PolicyId": "MS.EXO.15.3v1", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Should/3rd Party", - "PolicyId": "MS.EXO.16.2v1", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Should/3rd Party", - "PolicyId": "MS.EXO.9.2v1", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-ScubaDmarcRecords", - "Get-AcceptedDomain" - ], - "Criticality": "Shall", - "PolicyId": "MS.EXO.4.1v1", - "ReportDetails": "Requirement met", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-ScubaDmarcRecords", - "Get-AcceptedDomain" - ], - "Criticality": "Shall", - "PolicyId": "MS.EXO.4.2v1", - "ReportDetails": "Requirement met", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-ScubaDmarcRecords", - "Get-AcceptedDomain" - ], - "Criticality": "Shall", - "PolicyId": "MS.EXO.4.3v1", - "ReportDetails": "Requirement met", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-ScubaDmarcRecords", - "Get-AcceptedDomain" - ], - "Criticality": "Should", - "PolicyId": "MS.EXO.4.4v1", - "ReportDetails": "Requirement met", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-TransportRule" - ], - "Criticality": "Shall", - "PolicyId": "MS.EXO.7.1v1", - "ReportDetails": "No transport rule found that applies warnings to emails received from outside the organization", - "RequirementMet": false - }, - { - "ActualValue": [ - [], - [ - null - ] - ], - "Commandlet": [ - "Get-DkimSigningConfig", - "Get-ScubaDkimRecords", - "Get-AcceptedDomain" - ], - "Criticality": "Should", - "PolicyId": "MS.EXO.3.1v1", - "ReportDetails": "1 of 1 agency domain(s) found in violation: alexwilber.myo365.site", - "RequirementMet": false - }, - { - "ActualValue": [ - { - "AddressBookPolicyRoutingEnabled": false, - "AdminDisplayName": "", - "AgentGeneratedMessageLoopDetectionInSmtpEnabled": true, - "AgentGeneratedMessageLoopDetectionInSubmissionEnabled": true, - "AllowLegacyTLSClients": false, - "AnonymousSenderToRecipientRatePerHour": 1800, - "AttributionRejectBeforeMServRequest": false, - "AttributionRejectConsumerMessages": false, - "ClearCategories": true, - "ConvertDisclaimerWrapperToEml": false, - "ConvertReportToMessage": false, - "CurrentTransportSystemState": "Green", - "DSNConversionMode": "PreserveDSNBody", - "DiagnosticsAggregationServicePort": 9710, - "DistinguishedName": "CN=Transport Settings,CN=Configuration,CN=y2zj1.onmicrosoft.com,CN=ConfigurationUnits,DC=NAMPR10A008,DC=PROD,DC=OUTLOOK,DC=COM", - "EnableExternalHTTPMailDelivery": false, - "ExchangeObjectId": "b4f29764-fa61-4718-ac8d-29e1ad3007b9", - "ExchangeVersion": "0.1 (8.0.535.0)", - "ExternalDelayDsnEnabled": true, - "ExternalDsnDefaultLanguage": null, - "ExternalDsnLanguageDetectionEnabled": true, - "ExternalDsnMaxMessageAttachSize": "10 MB (10,485,760 bytes)", - "ExternalDsnReportingAuthority": null, - "ExternalDsnSendHtml": true, - "ExternalPostmasterAddress": null, - "GenerateCopyOfDSNFor": [], - "Guid": "b4f29764-fa61-4718-ac8d-29e1ad3007b9", - "HeaderPromotionModeSetting": "NoCreate", - "HygieneSuite": "Premium", - "Id": "Transport Settings", - "Identity": "Transport Settings", - "InternalDelayDsnEnabled": true, - "InternalDsnDefaultLanguage": null, - "InternalDsnLanguageDetectionEnabled": true, - "InternalDsnMaxMessageAttachSize": "10 MB (10,485,760 bytes)", - "InternalDsnReportingAuthority": null, - "InternalDsnSendHtml": true, - "InternalSMTPServers": [], - "IsValid": true, - "JournalArchivingEnabled": false, - "JournalMessageExpirationDays": 0, - "JournalReportDLMemberSubstitutionEnabled": false, - "JournalingReportNdrTo": "u003cu003e", - "LegacyArchiveJournalingEnabled": false, - "LegacyArchiveLiveJournalingEnabled": false, - "LegacyJournalingMigrationEnabled": false, - "MaxAllowedAgentGeneratedMessageDepth": 3, - "MaxAllowedAgentGeneratedMessageDepthPerAgent": 2, - "MaxDumpsterSizePerDatabase": "18 MB (18,874,368 bytes)", - "MaxDumpsterTime": "7.00:00:00", - "MaxReceiveSize": "Unlimited", - "MaxRecipientEnvelopeLimit": "Unlimited", - "MaxSendSize": "Unlimited", - "MessageExpiration": "1.00:00:00", - "MigrationEnabled": true, - "Name": "Transport Settings", - "ObjectCategory": "NAMPR10A008.PROD.OUTLOOK.COM/Configuration/Schema/ms-Exch-Transport-Settings", - "ObjectClass": [ - "top", - "container", - "msExchTransportSettings" - ], - "ObjectState": "Unchanged", - "OpenDomainRoutingEnabled": false, - "OrganizationFederatedMailbox": "FederatedEmail.4c1f4d8b-8179-4148-93bf-00a95fa1e042@y2zj1.onmicrosoft.com", - "OrganizationId": "NAMPR10A008.PROD.OUTLOOK.COM/Microsoft Exchange Hosted Organizations/y2zj1.onmicrosoft.com - NAMPR10A008.PROD.OUTLOOK.COM/ConfigurationUnits/y2zj1.onmicrosoft.com/Configuration", - "OrganizationalUnitRoot": "y2zj1.onmicrosoft.com", - "OriginatingServer": "DM5PR10A08DC002.NAMPR10A008.PROD.OUTLOOK.COM", - "OtherWellKnownObjects": [], - "PreserveReportBodypart": true, - "QueueDiagnosticsAggregationInterval": "00:01:00", - "RedirectDLMessagesForLegacyArchiveJournaling": false, - "RedirectUnprovisionedUserMessagesForLegacyArchiveJournaling": false, - "ReplyAllStormBlockDurationHours": 6, - "ReplyAllStormDetectionMinimumRecipients": 2500, - "ReplyAllStormDetectionMinimumReplies": 10, - "ReplyAllStormProtectionEnabled": true, - "Rfc2231EncodingEnabled": false, - "SafetyNetHoldTime": "7.00:00:00", - "SmtpClientAuthenticationDisabled": true, - "SupervisionTags": [ - "Reject", - "Allow" - ], - "TLSReceiveDomainSecureList": [], - "TLSSendDomainSecureList": [], - "TransportRuleAttachmentTextScanLimit": "1 MB (1,048,576 bytes)", - "TransportRuleCollectionAddedRecipientsLimit": 100, - "TransportRuleCollectionRegexCharsLimit": "20 KB (20,480 bytes)", - "TransportRuleConfig": [ - "TransportRuleMinProductVersion:14.0.0.0", - "TransportRuleRegexValidationTimeout:00:00:00.3000000", - "TransportRuleAttachmentTextScanLimit:1 MB (1,048,576 bytes)", - "TransportRuleSizeLimit:8 KB (8,192 bytes)", - "TransportRuleCollectionRegexCharsLimit:20 KB (20,480 bytes)", - "TransportRuleLimit:300", - "TransportRuleCollectionAddedRecipientsLimit:100" - ], - "TransportRuleLimit": 300, - "TransportRuleMinProductVersion": { - "Build": 0, - "Major": 14, - "MajorRevision": 0, - "Minor": 0, - "MinorRevision": 0, - "Revision": 0 - }, - "TransportRuleRegexValidationTimeout": "00:00:00.3000000", - "TransportRuleSizeLimit": "8 KB (8,192 bytes)", - "TransportSystemState": "", - "VerifySecureSubmitEnabled": false, - "VoicemailJournalingEnabled": true, - "WhenChanged": "/Date(1643184486000)/", - "WhenChangedUTC": "/Date(1643184486000)/", - "WhenCreated": "/Date(1643059670000)/", - "WhenCreatedUTC": "/Date(1643059670000)/", - "Xexch50Enabled": true - } - ], - "Commandlet": [ - "Get-TransportConfig" - ], - "Criticality": "Shall", - "PolicyId": "MS.EXO.5.1v1", - "ReportDetails": "Requirement met", - "RequirementMet": true - }, - { - "ActualValue": [ - { - "AdminDisplayName": "", - "Default": true, - "DistinguishedName": "CN=Default Sharing Policy,CN=Federation,CN=Configuration,CN=y2zj1.onmicrosoft.com,CN=ConfigurationUnits,DC=NAMPR10A008,DC=PROD,DC=OUTLOOK,DC=COM", - "Domains": [ - "Anonymous:CalendarSharingFreeBusyReviewer", - "*:CalendarSharingFreeBusySimple" - ], - "Enabled": true, - "ExchangeObjectId": "2f1ca8cf-5ba5-45e3-b73a-1405ff552a2e", - "ExchangeVersion": "0.10 (14.0.100.0)", - "Guid": "2f1ca8cf-5ba5-45e3-b73a-1405ff552a2e", - "Id": "Default Sharing Policy", - "Identity": "Default Sharing Policy", - "IsValid": true, - "Name": "Default Sharing Policy", - "ObjectCategory": "NAMPR10A008.PROD.OUTLOOK.COM/Configuration/Schema/ms-Exch-Sharing-Policy", - "ObjectClass": [ - "top", - "msExchSharingPolicy" - ], - "ObjectState": "Changed", - "OrganizationId": "NAMPR10A008.PROD.OUTLOOK.COM/Microsoft Exchange Hosted Organizations/y2zj1.onmicrosoft.com - NAMPR10A008.PROD.OUTLOOK.COM/ConfigurationUnits/y2zj1.onmicrosoft.com/Configuration", - "OrganizationalUnitRoot": "y2zj1.onmicrosoft.com", - "OriginatingServer": "DM5PR10A08DC002.NAMPR10A008.PROD.OUTLOOK.COM", - "WhenChanged": "/Date(1645650761000)/", - "WhenChangedUTC": "/Date(1645650761000)/", - "WhenCreated": "/Date(1645650752000)/", - "WhenCreatedUTC": "/Date(1645650752000)/" - } - ], - "Commandlet": [ - "Get-SharingPolicy" - ], - "Criticality": "Shall", - "PolicyId": "MS.EXO.6.1v1", - "ReportDetails": "Requirement met", - "RequirementMet": true - }, - { - "ActualValue": [ - { - "AdminDisplayName": "", - "Default": true, - "DistinguishedName": "CN=Default Sharing Policy,CN=Federation,CN=Configuration,CN=y2zj1.onmicrosoft.com,CN=ConfigurationUnits,DC=NAMPR10A008,DC=PROD,DC=OUTLOOK,DC=COM", - "Domains": [ - "Anonymous:CalendarSharingFreeBusyReviewer", - "*:CalendarSharingFreeBusySimple" - ], - "Enabled": true, - "ExchangeObjectId": "2f1ca8cf-5ba5-45e3-b73a-1405ff552a2e", - "ExchangeVersion": "0.10 (14.0.100.0)", - "Guid": "2f1ca8cf-5ba5-45e3-b73a-1405ff552a2e", - "Id": "Default Sharing Policy", - "Identity": "Default Sharing Policy", - "IsValid": true, - "Name": "Default Sharing Policy", - "ObjectCategory": "NAMPR10A008.PROD.OUTLOOK.COM/Configuration/Schema/ms-Exch-Sharing-Policy", - "ObjectClass": [ - "top", - "msExchSharingPolicy" - ], - "ObjectState": "Changed", - "OrganizationId": "NAMPR10A008.PROD.OUTLOOK.COM/Microsoft Exchange Hosted Organizations/y2zj1.onmicrosoft.com - NAMPR10A008.PROD.OUTLOOK.COM/ConfigurationUnits/y2zj1.onmicrosoft.com/Configuration", - "OrganizationalUnitRoot": "y2zj1.onmicrosoft.com", - "OriginatingServer": "DM5PR10A08DC002.NAMPR10A008.PROD.OUTLOOK.COM", - "WhenChanged": "/Date(1645650761000)/", - "WhenChangedUTC": "/Date(1645650761000)/", - "WhenCreated": "/Date(1645650752000)/", - "WhenCreatedUTC": "/Date(1645650752000)/" - } - ], - "Commandlet": [ - "Get-SharingPolicy" - ], - "Criticality": "Shall", - "PolicyId": "MS.EXO.6.2v1", - "ReportDetails": "Requirement met", - "RequirementMet": true - }, - { - "ActualValue": [ - { - "AdminDisplayName": "", - "DirectoryBasedEdgeBlockMode": "Default", - "DistinguishedName": "CN=Default,CN=Hosted Connection Filter,CN=Transport Settings,CN=Configuration,CN=y2zj1.onmicrosoft.com,CN=ConfigurationUnits,DC=NAMPR10A008,DC=PROD,DC=OUTLOOK,DC=COM", - "EnableSafeList": false, - "ExchangeObjectId": "3843aef3-f3bd-49c1-a674-4d6741ac11b6", - "ExchangeVersion": "0.20 (15.0.0.0)", - "Guid": "3843aef3-f3bd-49c1-a674-4d6741ac11b6", - "IPAllowList": [], - "IPBlockList": [], - "Id": "Default", - "Identity": "Default", - "IsDefault": true, - "IsValid": true, - "Name": "Default", - "ObjectCategory": "NAMPR10A008.PROD.OUTLOOK.COM/Configuration/Schema/ms-Exch-Hosted-Connection-Filter-Policy", - "ObjectClass": [ - "top", - "msExchHostedConnectionFilterPolicy" - ], - "ObjectState": "Unchanged", - "OrganizationId": "NAMPR10A008.PROD.OUTLOOK.COM/Microsoft Exchange Hosted Organizations/y2zj1.onmicrosoft.com - NAMPR10A008.PROD.OUTLOOK.COM/ConfigurationUnits/y2zj1.onmicrosoft.com/Configuration", - "OrganizationalUnitRoot": "y2zj1.onmicrosoft.com", - "OriginatingServer": "DM5PR10A08DC002.NAMPR10A008.PROD.OUTLOOK.COM", - "WhenChanged": "/Date(1645650833000)/", - "WhenChangedUTC": "/Date(1645650833000)/", - "WhenCreated": "/Date(1645650828000)/", - "WhenCreatedUTC": "/Date(1645650828000)/" - } - ], - "Commandlet": [ - "Get-HostedConnectionFilterPolicy" - ], - "Criticality": "Should", - "PolicyId": "MS.EXO.12.1v1", - "ReportDetails": "Requirement met", - "RequirementMet": true - }, - { - "ActualValue": [ - { - "AdminDisplayName": "", - "DirectoryBasedEdgeBlockMode": "Default", - "DistinguishedName": "CN=Default,CN=Hosted Connection Filter,CN=Transport Settings,CN=Configuration,CN=y2zj1.onmicrosoft.com,CN=ConfigurationUnits,DC=NAMPR10A008,DC=PROD,DC=OUTLOOK,DC=COM", - "EnableSafeList": false, - "ExchangeObjectId": "3843aef3-f3bd-49c1-a674-4d6741ac11b6", - "ExchangeVersion": "0.20 (15.0.0.0)", - "Guid": "3843aef3-f3bd-49c1-a674-4d6741ac11b6", - "IPAllowList": [], - "IPBlockList": [], - "Id": "Default", - "Identity": "Default", - "IsDefault": true, - "IsValid": true, - "Name": "Default", - "ObjectCategory": "NAMPR10A008.PROD.OUTLOOK.COM/Configuration/Schema/ms-Exch-Hosted-Connection-Filter-Policy", - "ObjectClass": [ - "top", - "msExchHostedConnectionFilterPolicy" - ], - "ObjectState": "Unchanged", - "OrganizationId": "NAMPR10A008.PROD.OUTLOOK.COM/Microsoft Exchange Hosted Organizations/y2zj1.onmicrosoft.com - NAMPR10A008.PROD.OUTLOOK.COM/ConfigurationUnits/y2zj1.onmicrosoft.com/Configuration", - "OrganizationalUnitRoot": "y2zj1.onmicrosoft.com", - "OriginatingServer": "DM5PR10A08DC002.NAMPR10A008.PROD.OUTLOOK.COM", - "WhenChanged": "/Date(1645650833000)/", - "WhenChangedUTC": "/Date(1645650833000)/", - "WhenCreated": "/Date(1645650828000)/", - "WhenCreatedUTC": "/Date(1645650828000)/" - } - ], - "Commandlet": [ - "Get-HostedConnectionFilterPolicy" - ], - "Criticality": "Should", - "PolicyId": "MS.EXO.12.2v1", - "ReportDetails": "Requirement met", - "RequirementMet": true - }, - { - "ActualValue": [ - { - "AuditDisabled": false, - "DisplayName": "y2zj1", - "Name": "y2zj1.onmicrosoft.com" - } - ], - "Commandlet": [ - "Get-OrganizationConfig" - ], - "Criticality": "Shall", - "PolicyId": "MS.EXO.13.1v1", - "ReportDetails": "Requirement met", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-ScubaSpfRecords", - "Get-AcceptedDomain" - ], - "Criticality": "Shall", - "PolicyId": "MS.EXO.2.2v1", - "ReportDetails": "Requirement met", - "RequirementMet": true - }, - { - "ActualValue": [ - "*" - ], - "Commandlet": [ - "Get-RemoteDomain" - ], - "Criticality": "Shall", - "PolicyId": "MS.EXO.1.1v1", - "ReportDetails": "1 remote domain(s) that allows automatic forwarding: *", - "RequirementMet": false - }, - { - "ActualValue": "PowerShell Error", - "Commandlet": [ - "Get-DlpPolicy" - ], - "Criticality": "Should", - "PolicyId": "MS.POWERPLATFORM.2.2v1", - "ReportDetails": "PowerShell Error", - "RequirementMet": false - }, - { - "ActualValue": "PowerShell Error", - "Commandlet": [ - "Get-PowerAppTenantIsolationPolicy" - ], - "Criticality": "Shall", - "PolicyId": "MS.POWERPLATFORM.3.1v1", - "ReportDetails": "PowerShell Error", - "RequirementMet": false - }, - { - "ActualValue": "PowerShell Error", - "Commandlet": [ - "Get-TenantSettings" - ], - "Control": "Power Platform 2.1", - "Criticality": "Shall", - "ReportDetails": "PowerShell Error", - "Requirement": "The ability to create trial environments SHALL be restricted to admins", - "RequirementMet": false - }, - { - "ActualValue": "PowerShell Error", - "Commandlet": [ - "Get-TenantSettings" - ], - "Criticality": "Shall", - "PolicyId": "MS.POWERPLATFORM.1.1v1", - "ReportDetails": "PowerShell Error", - "RequirementMet": false - }, - { - "ActualValue": "PowerShell error", - "Commandlet": [ - "Get-DlpPolicy" - ], - "Criticality": "Should", - "PolicyId": "MS.POWERPLATFORM.2.3v1", - "ReportDetails": "PowerShell error", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Shall/Not-Implemented", - "PolicyId": "MS.POWERPLATFORM.4.1v1", - "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Should/Not-Implemented", - "PolicyId": "MS.POWERPLATFORM.3.2v1", - "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Should/Not-Implemented", - "PolicyId": "MS.POWERPLATFORM.3.3v1", - "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-DlpPolicy" - ], - "Criticality": "Shall", - "PolicyId": "MS.POWERPLATFORM.2.1v1", - "ReportDetails": "No policy found that applies to default environment", - "RequirementMet": false - }, - { - "ActualValue": 1, - "Commandlet": [ - "Get-SPOTenant", - "Get-PnPTenant" - ], - "Criticality": "Should", - "PolicyId": "MS.SHAREPOINT.1.3v1", - "ReportDetails": "Requirement met", - "RequirementMet": true - }, - { - "ActualValue": 2, - "Commandlet": [ - "Get-SPOSite", - "Get-PnPTenantSite" - ], - "Control": "Sharepoint 2.5", - "Criticality": "Shall", - "ReportDetails": "Requirement met", - "Requirement": "Users SHALL be prevented from running custom scripts on self-service created sites", - "RequirementMet": true - }, - { - "ActualValue": 2, - "Commandlet": [ - "Get-SPOTenant", - "Get-PnPTenant" - ], - "Criticality": "Shall", - "PolicyId": "MS.SHAREPOINT.1.1v1", - "ReportDetails": "Requirement not met", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Control": "Sharepoint 2.5", - "Criticality": "Shall/Not-Implemented", - "PolicyId": "MS.SHAREPOINT.TBD", - "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", - "Requirement": "Users SHALL be prevented from running custom scripts on personal sites (OneDrive)", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Shall/Not-Implemented", - "PolicyId": "MS.SHAREPOINT.1.2v1", - "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Should/Not-Implemented", - "PolicyId": "MS.SHAREPOINT.2.1v1", - "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", - "RequirementMet": false - }, - { - "ActualValue": [ - 1, - true, - 29 - ], - "Commandlet": [ - "Get-SPOTenant", - "Get-PnPTenant" - ], - "Control": "Sharepoint 2.4", - "Criticality": "Should", - "ReportDetails": "Requirement not met: Expiration timer for 'People who use a verification code' NOT set to 30 days", - "Requirement": "Expiration timer for 'People who use a verification code' should be set to 30 days", - "RequirementMet": false - }, - { - "ActualValue": [ - 1, - true, - 31 - ], - "Commandlet": [ - "Get-SPOTenant", - "Get-PnPTenant" - ], - "Criticality": "Should", - "PolicyId": "MS.SHAREPOINT.3.1v1", - "ReportDetails": "Requirement not met: Expiration timer for 'Guest access to a site or OneDrive' NOT set to 30 days", - "RequirementMet": false - }, - { - "ActualValue": true, - "Commandlet": [ - "Get-CsTeamsMeetingPolicy" - ], - "Criticality": "Should", - "PolicyId": "MS.TEAMS.9.1v1", - "ReportDetails": "Requirement not met", - "RequirementMet": false - }, - { - "ActualValue": "AlwaysEnabled", - "Commandlet": [ - "Get-CsTeamsMeetingBroadcastPolicy" - ], - "Criticality": "Should", - "PolicyId": "MS.TEAMS.10.1v1", - "ReportDetails": "Requirement not met", - "RequirementMet": false - }, - { - "ActualValue": "EveryoneInCompany", - "Commandlet": [ - "Get-CsTeamsMeetingPolicy" - ], - "Criticality": "Should", - "PolicyId": "MS.TEAMS.3.2v1", - "ReportDetails": "Requirement met", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Shall/3rd Party", - "PolicyId": "MS.TEAMS.11.1v1", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Shall/3rd Party", - "PolicyId": "MS.TEAMS.11.4v1", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Shall/3rd Party", - "PolicyId": "MS.TEAMS.8.3v1", - "ReportDetails": "Not currently checked automatically. See Secure Configuration Baseline policy for instructions on manual check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Should/3rd Party", - "PolicyId": "MS.TEAMS.11.2v1", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Should/3rd Party", - "PolicyId": "MS.TEAMS.12.1v1", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Should/3rd Party", - "PolicyId": "MS.TEAMS.12.2v1", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Should/3rd Party", - "PolicyId": "MS.TEAMS.13.1v1", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Should/3rd Party", - "PolicyId": "MS.TEAMS.13.2v1", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "RequirementMet": false - }, - { - "ActualValue": [], - "Commandlet": [], - "Criticality": "Should/3rd Party", - "PolicyId": "MS.TEAMS.13.3v1", - "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", - "RequirementMet": false - }, - { - "ActualValue": [ - "EveryoneInCompany", - false - ], - "Commandlet": [ - "Get-CsTeamsMeetingPolicy" - ], - "Criticality": "Should", - "PolicyId": "MS.TEAMS.3.1v1", - "ReportDetails": "Requirement met", - "RequirementMet": true - }, - { - "ActualValue": [ - [], - "MicrosoftCommunicationsOnline/NOAM-ED6-A7" - ], - "Commandlet": [ - "Get-CsTeamsClientConfiguration" - ], - "Criticality": "Shall", - "PolicyId": "MS.TEAMS.7.1v1", - "ReportDetails": "Requirement met", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-CsTeamsAppPermissionPolicy" - ], - "Criticality": "Should", - "PolicyId": "MS.TEAMS.8.1v1", - "ReportDetails": "Requirement met", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-CsTeamsMeetingPolicy" - ], - "Control": "Teams 2.4", - "Criticality": "Should", - "ReportDetails": "Requirement met", - "Requirement": "Anonymous users SHOULD be enabled to join meetings", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-CsTeamsMeetingPolicy" - ], - "Criticality": "Shall", - "PolicyId": "MS.TEAMS.2.1v1", - "ReportDetails": "Requirement met", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-CsTeamsMeetingPolicy" - ], - "Criticality": "Should", - "PolicyId": "MS.TEAMS.1.1v1", - "ReportDetails": "Requirement met", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-CsTeamsMeetingPolicy" - ], - "Criticality": "Should", - "PolicyId": "MS.TEAMS.9.3v1", - "ReportDetails": "Requirement met", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-CsTenantFederationConfiguration" - ], - "Criticality": "Shall", - "PolicyId": "MS.TEAMS.4.1v1", - "ReportDetails": "Requirement met", - "RequirementMet": true - }, - { - "ActualValue": [], - "Commandlet": [ - "Get-CsTenantFederationConfiguration" - ], - "Criticality": "Shall", - "PolicyId": "MS.TEAMS.6.1v1", - "ReportDetails": "Requirement met", - "RequirementMet": true - }, - { - "ActualValue": [ - "Global" - ], - "Commandlet": [ - "Get-CsTeamsAppPermissionPolicy" - ], - "Criticality": "Should", - "PolicyId": "MS.TEAMS.8.2av1", - "ReportDetails": "1 meeting policy(ies) found that allow custom apps by default: Global", - "RequirementMet": false - }, - { - "ActualValue": [ - "Global" - ], - "Commandlet": [ - "Get-CsTeamsAppPermissionPolicy" - ], - "Criticality": "Should", - "PolicyId": "MS.TEAMS.8.2v1", - "ReportDetails": "1 meeting policy(ies) found that allow third-party apps by default: Global", - "RequirementMet": false - }, - { - "ActualValue": [ - "Global" - ], - "Commandlet": [ - "Get-CsTenantFederationConfiguration" - ], - "Criticality": "Shall", - "PolicyId": "MS.TEAMS.5.1v1", - "ReportDetails": "1 Configuration allowed unmanaged users to initiate contact with internal user across domains: Global", - "RequirementMet": false - }, - { - "ActualValue": [ - "Global" - ], - "Commandlet": [ - "Get-CsTenantFederationConfiguration" - ], - "Criticality": "Should", - "PolicyId": "MS.TEAMS.5.2v1", - "ReportDetails": "1 Internal users are enabled to initiate contact with unmanaged users across domains: Global", - "RequirementMet": false +[ + { + "ActualValue": "Alex Wilber", + "Commandlet": [ + "Get-MgSubscribedSku", + "Get-PrivilegedUser" + ], + "Criticality": "Shall", + "PolicyId": "MS.AAD.7.3v1", + "ReportDetails": "1 admin(s) that are not cloud-only found:\u003cbr/\u003eAlex Wilber", + "RequirementMet": false + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + + ], + "Criticality": "Shall/Not-Implemented", + "PolicyId": "MS.AAD.3.1v1", + "ReportDetails": "Not currently checked automatically. See \u003ca href=\"https://github.com/cisagov/ScubaGear/blob/0.3.0/baselines/aad.md#msaad31v1\" target=\"_blank\"\u003eSecure Configuration Baseline policy\u003c/a\u003e for instructions on manual check", + "RequirementMet": false + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + + ], + "Criticality": "Shall/Not-Implemented", + "PolicyId": "MS.AAD.3.5v1", + "ReportDetails": "Not currently checked automatically. See \u003ca href=\"https://github.com/cisagov/ScubaGear/blob/0.3.0/baselines/aad.md#msaad35v1\" target=\"_blank\"\u003eSecure Configuration Baseline policy\u003c/a\u003e for instructions on manual check", + "RequirementMet": false + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + + ], + "Criticality": "Shall/Not-Implemented", + "PolicyId": "MS.AAD.4.1v1", + "ReportDetails": "Not currently checked automatically. See \u003ca href=\"https://github.com/cisagov/ScubaGear/blob/0.3.0/baselines/aad.md#msaad41v1\" target=\"_blank\"\u003eSecure Configuration Baseline policy\u003c/a\u003e for instructions on manual check", + "RequirementMet": false + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + + ], + "Criticality": "Shall/Not-Implemented", + "PolicyId": "MS.AAD.6.1v1", + "ReportDetails": "Not currently checked automatically. See \u003ca href=\"https://github.com/cisagov/ScubaGear/blob/0.3.0/baselines/aad.md#msaad61v1\" target=\"_blank\"\u003eSecure Configuration Baseline policy\u003c/a\u003e for instructions on manual check", + "RequirementMet": false + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + + ], + "Criticality": "Shall/Not-Implemented", + "PolicyId": "MS.AAD.7.2v1", + "ReportDetails": "Not currently checked automatically. See \u003ca href=\"https://github.com/cisagov/ScubaGear/blob/0.3.0/baselines/aad.md#msaad72v1\" target=\"_blank\"\u003eSecure Configuration Baseline policy\u003c/a\u003e for instructions on manual check", + "RequirementMet": false + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + + ], + "Criticality": "Should/Not-Implemented", + "PolicyId": "MS.AAD.2.2v1", + "ReportDetails": "Not currently checked automatically. See \u003ca href=\"https://github.com/cisagov/ScubaGear/blob/0.3.0/baselines/aad.md#msaad22v1\" target=\"_blank\"\u003eSecure Configuration Baseline policy\u003c/a\u003e for instructions on manual check", + "RequirementMet": false + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + + ], + "Criticality": "Should/Not-Implemented", + "PolicyId": "MS.AAD.3.3v1", + "ReportDetails": "Not currently checked automatically. See \u003ca href=\"https://github.com/cisagov/ScubaGear/blob/0.3.0/baselines/aad.md#msaad33v1\" target=\"_blank\"\u003eSecure Configuration Baseline policy\u003c/a\u003e for instructions on manual check", + "RequirementMet": false + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + + ], + "Criticality": "Should/Not-Implemented", + "PolicyId": "MS.AAD.3.4v1", + "ReportDetails": "Not currently checked automatically. See \u003ca href=\"https://github.com/cisagov/ScubaGear/blob/0.3.0/baselines/aad.md#msaad34v1\" target=\"_blank\"\u003eSecure Configuration Baseline policy\u003c/a\u003e for instructions on manual check", + "RequirementMet": false + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + + ], + "Criticality": "Should/Not-Implemented", + "PolicyId": "MS.AAD.3.8v1", + "ReportDetails": "Not currently checked automatically. See \u003ca href=\"https://github.com/cisagov/ScubaGear/blob/0.3.0/baselines/aad.md#msaad38v1\" target=\"_blank\"\u003eSecure Configuration Baseline policy\u003c/a\u003e for instructions on manual check", + "RequirementMet": false + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + + ], + "Criticality": "Should/Not-Implemented", + "PolicyId": "MS.AAD.8.3v1", + "ReportDetails": "Not currently checked automatically. See \u003ca href=\"https://github.com/cisagov/ScubaGear/blob/0.3.0/baselines/aad.md#msaad83v1\" target=\"_blank\"\u003eSecure Configuration Baseline policy\u003c/a\u003e for instructions on manual check", + "RequirementMet": false + }, + { + "ActualValue": { + "all_allow_invite_values": [ + { + "AllowInvitesFromValue": "everyone", + "PolicyId": "authorizationPolicy" + } + ] + }, + "Commandlet": [ + "Get-MgPolicyAuthorizationPolicy" + ], + "Criticality": "Should", + "PolicyId": "MS.AAD.8.2v1", + "ReportDetails": "Permission level set to \"everyone\" (authorizationPolicy)", + "RequirementMet": false + }, + { + "ActualValue": { + "all_allowed_create_values": [ + { + "DefaultUser_AllowedToCreateApps": false, + "PolicyId": "authorizationPolicy" + } + ] + }, + "Commandlet": [ + "Get-MgPolicyAuthorizationPolicy" + ], + "Criticality": "Shall", + "PolicyId": "MS.AAD.5.1v1", + "ReportDetails": "0 authorization policies found that allow non-admin users to register third-party applications", + "RequirementMet": true + }, + { + "ActualValue": { + "all_consent_policies": [ + { + "IsEnabled": false, + "PolicyId": null + } + ] + }, + "Commandlet": [ + "Get-MgPolicyAdminConsentRequestPolicy" + ], + "Criticality": "Shall", + "PolicyId": "MS.AAD.5.3v1", + "ReportDetails": "Requirement not met", + "RequirementMet": false + }, + { + "ActualValue": { + "all_grant_policy_values": [ + { + "DefaultUser_DefaultGrantPolicy": [ + + ], + "PolicyId": "authorizationPolicy" + } + ] + }, + "Commandlet": [ + "Get-MgPolicyAuthorizationPolicy" + ], + "Criticality": "Shall", + "PolicyId": "MS.AAD.5.2v1", + "ReportDetails": "0 authorization policies found that allow non-admin users to consent to third-party applications", + "RequirementMet": true + }, + { + "ActualValue": { + "all_roleid_values": [ + { + "GuestUserRoleId": "10dae51f-b6af-4016-8d66-8c2a99b929b3", + "GuestUserRoleIdString": "Limited access", + "Id": "authorizationPolicy" + } + ] + }, + "Commandlet": [ + "Get-MgPolicyAuthorizationPolicy" + ], + "Criticality": "Should", + "PolicyId": "MS.AAD.8.1v1", + "ReportDetails": "Permission level set to \"Limited access\" (authorizationPolicy)", + "RequirementMet": true + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + "Get-MgIdentityConditionalAccessPolicy" + ], + "Criticality": "Should", + "PolicyId": "MS.AAD.3.7v1", + "ReportDetails": "0 conditional access policy(s) found that meet(s) all requirements. \u003ca href=\u0027#caps\u0027\u003eView all CA policies\u003c/a\u003e.", + "RequirementMet": false + }, + { + "ActualValue": [ + "Addam Schroll", + "Andrew Huynh", + "Grant Dasher", + "Nanda Katikaneni", + "Shanti Satyapal", + "Ted Kolovos", + "Thomas Comeau" + ], + "Commandlet": [ + "Get-MgSubscribedSku", + "Get-PrivilegedUser" + ], + "Criticality": "Shall", + "PolicyId": "MS.AAD.7.1v1", + "ReportDetails": "7 global admin(s) found:\u003cbr/\u003eAddam Schroll, Andrew Huynh, Grant Dasher, Nanda Katikaneni, Shanti Satyapal, Ted Kolovos, Thomas Comeau", + "RequirementMet": true + }, + { + "ActualValue": [ + "Application Administrator", + "Cloud Application Administrator", + "Hybrid Identity Administrator", + "Privileged Role Administrator", + "SharePoint Administrator" + ], + "Commandlet": [ + "Get-MgSubscribedSku", + "Get-PrivilegedRole" + ], + "Criticality": "Should", + "PolicyId": "MS.AAD.7.6v1", + "ReportDetails": "5 role(s) that do not require approval to activate found:\u003cbr/\u003eApplication Administrator, Cloud Application Administrator, Hybrid Identity Administrator, Privileged Role Administrator, SharePoint Administrator", + "RequirementMet": false + }, + { + "ActualValue": [ + "Exchange Administrator", + "Global Administrator", + "Privileged Role Administrator", + "SharePoint Administrator", + "User Administrator" + ], + "Commandlet": [ + "Get-MgSubscribedSku", + "Get-PrivilegedRole" + ], + "Criticality": "Shall", + "PolicyId": "MS.AAD.7.5v1", + "ReportDetails": "5 role(s) assigned to users outside of PIM:\u003cbr/\u003eExchange Administrator, Global Administrator, Privileged Role Administrator, SharePoint Administrator, User Administrator", + "RequirementMet": false + }, + { + "ActualValue": [ + "Global Administrator", + "SharePoint Administrator", + "User Administrator" + ], + "Commandlet": [ + "Get-MgSubscribedSku", + "Get-PrivilegedRole" + ], + "Criticality": "Shall", + "PolicyId": "MS.AAD.7.4v1", + "ReportDetails": "3 role(s) configured to allow permanent active assignment or expiration period too long:\u003cbr/\u003eGlobal Administrator, SharePoint Administrator, User Administrator", + "RequirementMet": false + }, + { + "ActualValue": [ + "Live - Block legacy authentication" + ], + "Commandlet": [ + "Get-MgIdentityConditionalAccessPolicy" + ], + "Criticality": "Shall", + "PolicyId": "MS.AAD.1.1v1", + "ReportDetails": "1 conditional access policy(s) found that meet(s) all requirements:\u003cbr/\u003eLive - Block legacy authentication. \u003ca href=\u0027#caps\u0027\u003eView all CA policies\u003c/a\u003e.", + "RequirementMet": true + }, + { + "ActualValue": [ + "Live - MFA Required for Everyone" + ], + "Commandlet": [ + "Get-MgIdentityConditionalAccessPolicy" + ], + "Criticality": "Shall", + "PolicyId": "MS.AAD.3.2v1", + "ReportDetails": "1 conditional access policy(s) found that meet(s) all requirements:\u003cbr/\u003eLive - MFA Required for Everyone. \u003ca href=\u0027#caps\u0027\u003eView all CA policies\u003c/a\u003e.", + "RequirementMet": true + }, + { + "ActualValue": [ + "Live - MFA required for Highly Privileged Roles" + ], + "Commandlet": [ + "Get-MgSubscribedSku", + "Get-PrivilegedRole", + "Get-MgIdentityConditionalAccessPolicy" + ], + "Criticality": "Shall", + "PolicyId": "MS.AAD.3.6v1", + "ReportDetails": "1 conditional access policy(s) found that meet(s) all requirements:\u003cbr/\u003eLive - MFA required for Highly Privileged Roles. \u003ca href=\u0027#caps\u0027\u003eView all CA policies\u003c/a\u003e.", + "RequirementMet": true + }, + { + "ActualValue": [ + "Live - Risky Sign Ins Block Access" + ], + "Commandlet": [ + "Get-MgIdentityConditionalAccessPolicy" + ], + "Criticality": "Shall", + "PolicyId": "MS.AAD.2.3v1", + "ReportDetails": "1 conditional access policy(s) found that meet(s) all requirements:\u003cbr/\u003eLive - Risky Sign Ins Block Access. \u003ca href=\u0027#caps\u0027\u003eView all CA policies\u003c/a\u003e.", + "RequirementMet": true + }, + { + "ActualValue": [ + "Live - Risky Users Block Access" + ], + "Commandlet": [ + "Get-MgIdentityConditionalAccessPolicy" + ], + "Criticality": "Shall", + "PolicyId": "MS.AAD.2.1v1", + "ReportDetails": "1 conditional access policy(s) found that meet(s) all requirements:\u003cbr/\u003eLive - Risky Users Block Access. \u003ca href=\u0027#caps\u0027\u003eView all CA policies\u003c/a\u003e.", + "RequirementMet": true + }, + { + "ActualValue": [ + "Privileged Role Administrator" + ], + "Commandlet": [ + "Get-MgSubscribedSku", + "Get-PrivilegedRole" + ], + "Criticality": "Shall", + "PolicyId": "MS.AAD.7.8v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [ + "Privileged Role Administrator" + ], + "Commandlet": [ + "Get-MgSubscribedSku", + "Get-PrivilegedRole" + ], + "Criticality": "Should", + "PolicyId": "MS.AAD.7.9v1", + "ReportDetails": "1 role(s) without notification e-mail configured for role activations found:\u003cbr/\u003ePrivileged Role Administrator", + "RequirementMet": false + }, + { + "ActualValue": [ + "Privileged Role Administrator", + "User Administrator" + ], + "Commandlet": [ + "Get-MgSubscribedSku", + "Get-PrivilegedRole" + ], + "Criticality": "Shall", + "PolicyId": "MS.AAD.7.7v1", + "ReportDetails": "2 role(s) without notification e-mail configured for role assignments found:\u003cbr/\u003ePrivileged Role Administrator, User Administrator", + "RequirementMet": false + }, + { + "ActualValue": [ + { + "Name": "EnableGroupSpecificConsent", + "SettingsGroup": "Consent Policy Settings", + "Value": "false" + } + ], + "Commandlet": [ + "Get-MgDirectorySetting" + ], + "Criticality": "Shall", + "PolicyId": "MS.AAD.5.4v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": false, + "Commandlet": [ + "Get-AntiPhishPolicy" + ], + "Control": "Defender 2.5", + "Criticality": "Shall", + "ReportDetails": "Requirement not met", + "Requirement": "All safety tips SHALL be enabled: domain impersonation default policy", + "RequirementMet": false + }, + { + "ActualValue": false, + "Commandlet": [ + "Get-AntiPhishPolicy" + ], + "Control": "Defender 2.5", + "Criticality": "Shall", + "ReportDetails": "Requirement not met", + "Requirement": "All safety tips SHALL be enabled: user impersonation default policy", + "RequirementMet": false + }, + { + "ActualValue": false, + "Commandlet": [ + "Get-AntiPhishPolicy" + ], + "Control": "Defender 2.5", + "Criticality": "Shall", + "ReportDetails": "Requirement not met", + "Requirement": "All safety tips SHALL be enabled: user impersonation unusual characters default policy", + "RequirementMet": false + }, + { + "ActualValue": false, + "Commandlet": [ + "Get-AntiPhishPolicy" + ], + "Criticality": "Shall", + "PolicyId": "MS.DEFENDER.5.8v1", + "ReportDetails": "Requirement not met", + "RequirementMet": false + }, + { + "ActualValue": true, + "Commandlet": [ + "Get-AntiPhishPolicy" + ], + "Control": "Defender 2.5", + "Criticality": "Shall", + "ReportDetails": "Requirement met", + "Requirement": "All safety tips SHALL be enabled: \"?\" for unauthenticated senders for spoof default policy", + "RequirementMet": true + }, + { + "ActualValue": true, + "Commandlet": [ + "Get-AntiPhishPolicy" + ], + "Control": "Defender 2.5", + "Criticality": "Shall", + "ReportDetails": "Requirement met", + "Requirement": "All safety tips SHALL be enabled: \"via\" tag default policy", + "RequirementMet": true + }, + { + "ActualValue": true, + "Commandlet": [ + "Get-HostedContentFilterPolicy" + ], + "Control": "Defender 2.6", + "Criticality": "Shall", + "ReportDetails": "Requirement met", + "Requirement": "Zero-hour auto purge (ZAP) SHALL be enabled for phishing: default policy", + "RequirementMet": true + }, + { + "ActualValue": true, + "Commandlet": [ + "Get-HostedContentFilterPolicy" + ], + "Control": "Defender 2.6", + "Criticality": "Shall", + "ReportDetails": "Requirement met", + "Requirement": "Zero-hour auto purge (ZAP) SHALL be enabled for spam messages: default policy", + "RequirementMet": true + }, + { + "ActualValue": true, + "Commandlet": [ + "Get-HostedContentFilterPolicy" + ], + "Criticality": "Shall", + "PolicyId": "MS.DEFENDER.6.7v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": true, + "Commandlet": [ + "Get-HostedContentFilterPolicy" + ], + "Criticality": "Should", + "PolicyId": "MS.DEFENDER.6.6v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": 7, + "Commandlet": [ + "Get-HostedContentFilterPolicy" + ], + "Criticality": "Should", + "PolicyId": "MS.DEFENDER.6.1v1", + "ReportDetails": "Requirement not met", + "RequirementMet": false + }, + { + "ActualValue": 15, + "Commandlet": [ + "Get-HostedContentFilterPolicy" + ], + "Criticality": "Should", + "PolicyId": "MS.DEFENDER.6.5v1", + "ReportDetails": "Requirement not met", + "RequirementMet": false + }, + { + "ActualValue": "MoveToJmf", + "Commandlet": [ + "Get-AntiPhishPolicy" + ], + "Criticality": "Shall", + "PolicyId": "MS.DEFENDER.5.7v1", + "ReportDetails": "Requirement not met", + "RequirementMet": false + }, + { + "ActualValue": "MoveToJmf", + "Commandlet": [ + "Get-HostedContentFilterPolicy" + ], + "Control": "Defender 2.6", + "Criticality": "Shall", + "ReportDetails": "Requirement met", + "Requirement": "High confidence spam SHALL be moved to either the junk email folder or the quarantine folder: default policy", + "RequirementMet": true + }, + { + "ActualValue": "MoveToJmf", + "Commandlet": [ + "Get-HostedContentFilterPolicy" + ], + "Criticality": "Shall", + "PolicyId": "MS.DEFENDER.6.2v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": "MoveToJmf", + "Commandlet": [ + "Get-HostedContentFilterPolicy" + ], + "Criticality": "Shall", + "PolicyId": "MS.DEFENDER.6.3v1", + "ReportDetails": "Requirement not met", + "RequirementMet": false + }, + { + "ActualValue": "MoveToJmf", + "Commandlet": [ + "Get-HostedContentFilterPolicy" + ], + "Criticality": "Should", + "PolicyId": "MS.DEFENDER.6.4v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": "NoAction", + "Commandlet": [ + "Get-AntiPhishPolicy" + ], + "Control": "Defender 2.5", + "Criticality": "Shall", + "ReportDetails": "Requirement not met", + "Requirement": "Message action SHALL be set to quarantine if the message is detected as impersonated: domains default policy", + "RequirementMet": false + }, + { + "ActualValue": "NoAction", + "Commandlet": [ + "Get-AntiPhishPolicy" + ], + "Control": "Defender 2.5", + "Criticality": "Shall", + "ReportDetails": "Requirement not met", + "Requirement": "Message action SHALL be set to quarantine if the message is detected as impersonated: mailbox default policy", + "RequirementMet": false + }, + { + "ActualValue": "NoAction", + "Commandlet": [ + "Get-AntiPhishPolicy" + ], + "Criticality": "Shall", + "PolicyId": "MS.DEFENDER.5.6v1", + "ReportDetails": "Requirement not met", + "RequirementMet": false + }, + { + "ActualValue": "Quarantine", + "Commandlet": [ + "Get-HostedContentFilterPolicy" + ], + "Control": "Defender 2.6", + "Criticality": "Shall", + "ReportDetails": "Requirement met", + "Requirement": "High confidence phishing SHALL be quarantined: default policy", + "RequirementMet": true + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + + ], + "Criticality": "Shall/Not-Implemented", + "PolicyId": "MS.DEFENDER.10.2v1", + "ReportDetails": "Not currently checked automatically. See \u003ca href=\"https://github.com/cisagov/ScubaGear/blob/0.3.0/baselines/defender.md#msdefender102v1\" target=\"_blank\"\u003eSecure Configuration Baseline policy\u003c/a\u003e for instructions on manual check", + "RequirementMet": false + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + + ], + "Criticality": "Shall/Not-Implemented", + "PolicyId": "MS.DEFENDER.10.3v1", + "ReportDetails": "Not currently checked automatically. See \u003ca href=\"https://github.com/cisagov/ScubaGear/blob/0.3.0/baselines/defender.md#msdefender103v1\" target=\"_blank\"\u003eSecure Configuration Baseline policy\u003c/a\u003e for instructions on manual check", + "RequirementMet": false + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + + ], + "Criticality": "Should/Not-Implemented", + "PolicyId": "MS.DEFENDER.2.5v1", + "ReportDetails": "Not currently checked automatically. See \u003ca href=\"https://github.com/cisagov/ScubaGear/blob/0.3.0/baselines/defender.md#msdefender25v1\" target=\"_blank\"\u003eSecure Configuration Baseline policy\u003c/a\u003e for instructions on manual check", + "RequirementMet": false + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + + ], + "Criticality": "Should/Not-Implemented", + "PolicyId": "MS.DEFENDER.2.6v1", + "ReportDetails": "Not currently checked automatically. See \u003ca href=\"https://github.com/cisagov/ScubaGear/blob/0.3.0/baselines/defender.md#msdefender26v1\" target=\"_blank\"\u003eSecure Configuration Baseline policy\u003c/a\u003e for instructions on manual check", + "RequirementMet": false + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + + ], + "Criticality": "Should/Not-Implemented", + "PolicyId": "MS.DEFENDER.9.2v1", + "ReportDetails": "Not currently checked automatically. See \u003ca href=\"https://github.com/cisagov/ScubaGear/blob/0.3.0/baselines/defender.md#msdefender92v1\" target=\"_blank\"\u003eSecure Configuration Baseline policy\u003c/a\u003e for instructions on manual check", + "RequirementMet": false + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + "Get-AntiPhishPolicy" + ], + "Control": "Defender 2.5", + "Criticality": "Should", + "ReportDetails": "Requirement met", + "Requirement": "All safety tips SHOULD be enabled: \"?\" for unauthenticated senders for spoof non-default policies", + "RequirementMet": true + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + "Get-AntiPhishPolicy" + ], + "Control": "Defender 2.5", + "Criticality": "Should", + "ReportDetails": "Requirement met", + "Requirement": "All safety tips SHOULD be enabled: \"via\" tag non-default policies", + "RequirementMet": true + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + "Get-AntiPhishPolicy" + ], + "Control": "Defender 2.5", + "Criticality": "Should", + "ReportDetails": "Requirement met", + "Requirement": "All safety tips SHOULD be enabled: domain impersonation non-default policies", + "RequirementMet": true + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + "Get-AntiPhishPolicy" + ], + "Control": "Defender 2.5", + "Criticality": "Should", + "ReportDetails": "Requirement met", + "Requirement": "All safety tips SHOULD be enabled: user impersonation non-default policies", + "RequirementMet": true + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + "Get-AntiPhishPolicy" + ], + "Control": "Defender 2.5", + "Criticality": "Should", + "ReportDetails": "Requirement met", + "Requirement": "All safety tips SHOULD be enabled: user impersonation unusual characters non-default policies", + "RequirementMet": true + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + "Get-AntiPhishPolicy" + ], + "Control": "Defender 2.5", + "Criticality": "Should", + "ReportDetails": "Requirement met", + "Requirement": "Mail classified as spoofed SHOULD be quarantined: non-default policies", + "RequirementMet": true + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + "Get-AntiPhishPolicy" + ], + "Control": "Defender 2.5", + "Criticality": "Should", + "ReportDetails": "Requirement met", + "Requirement": "Message action SHOULD be set to quarantine if the message is detected as impersonated: domains non-default policies", + "RequirementMet": true + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + "Get-AntiPhishPolicy" + ], + "Control": "Defender 2.5", + "Criticality": "Should", + "ReportDetails": "Requirement met", + "Requirement": "Message action SHOULD be set to quarantine if the message is detected as impersonated: mailbox non-default policies", + "RequirementMet": true + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + "Get-AntiPhishPolicy" + ], + "Control": "Defender 2.5", + "Criticality": "Should", + "ReportDetails": "Requirement met", + "Requirement": "Message action SHOULD be set to quarantine if the message is detected as impersonated: users non-default policies", + "RequirementMet": true + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + "Get-AntiPhishPolicy" + ], + "Criticality": "Should", + "PolicyId": "MS.DEFENDER.5.1v1", + "ReportDetails": "No users are included for targeted user protection.", + "RequirementMet": false + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + "Get-AntiPhishPolicy" + ], + "Criticality": "Should", + "PolicyId": "MS.DEFENDER.5.3v1", + "ReportDetails": "The Custom Domains protection policies: Enabled, EnableTargetedDomainsProtection, and TargetedDomainsToProtect are not set correctly", + "RequirementMet": false + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + "Get-DLPCompliancePolicy" + ], + "Control": "Defender 2.2", + "Criticality": "Should", + "ReportDetails": "No policy found that applies to OneDrive.", + "Requirement": "The custom policy SHOULD be applied in OneDrive", + "RequirementMet": false + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + "Get-DlpComplianceRule" + ], + "Control": "Defender 2.2", + "Criticality": "Shall", + "ReportDetails": "No matching rule found for U.S. Individual Taxpayer Identification Number (ITIN)", + "Requirement": "A custom policy SHALL be configured to protect PII and sensitive information, as defined by the agency: U.S. Individual Taxpayer Identification Number (ITIN)", + "RequirementMet": false + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + "Get-DlpComplianceRule" + ], + "Criticality": "Shall", + "PolicyId": "MS.DEFENDER.2.1v1", + "ReportDetails": "No matching rule found for U.S. Social Security Number (SSN)", + "RequirementMet": false + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + "Get-HostedContentFilterPolicy" + ], + "Control": "Defender 2.6", + "Criticality": "Should", + "ReportDetails": "Requirement met", + "Requirement": "Allowed senders MAY be added but allowed domains SHOULD NOT be added: non-default", + "RequirementMet": true + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + "Get-HostedContentFilterPolicy" + ], + "Control": "Defender 2.6", + "Criticality": "Should", + "ReportDetails": "Requirement met", + "Requirement": "Bulk email SHOULD be moved to either the junk email folder or the quarantine folder: non-default policies", + "RequirementMet": true + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + "Get-HostedContentFilterPolicy" + ], + "Control": "Defender 2.6", + "Criticality": "Should", + "ReportDetails": "Requirement met", + "Requirement": "High confidence phishing SHOULD be quarantined: non-default policies", + "RequirementMet": true + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + "Get-HostedContentFilterPolicy" + ], + "Control": "Defender 2.6", + "Criticality": "Should", + "ReportDetails": "Requirement met", + "Requirement": "High confidence spam SHOULD be moved to either the junk email folder or the quarantine folder: non-default policies", + "RequirementMet": true + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + "Get-HostedContentFilterPolicy" + ], + "Control": "Defender 2.6", + "Criticality": "Should", + "ReportDetails": "Requirement met", + "Requirement": "Phishing SHOULD be quarantined: non-default policies", + "RequirementMet": true + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + "Get-HostedContentFilterPolicy" + ], + "Control": "Defender 2.6", + "Criticality": "Should", + "ReportDetails": "Requirement met", + "Requirement": "Spam SHOULD be moved to either the junk email folder or the quarantine folder: non-default policies", + "RequirementMet": true + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + "Get-HostedContentFilterPolicy" + ], + "Control": "Defender 2.6", + "Criticality": "Should", + "ReportDetails": "Requirement met", + "Requirement": "Spam in quarantine SHOULD be retained for at least 30 days: non-default policies", + "RequirementMet": true + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + "Get-HostedContentFilterPolicy" + ], + "Control": "Defender 2.6", + "Criticality": "Should", + "ReportDetails": "Requirement met", + "Requirement": "Spam safety tips SHOULD be turned on: non-default policies", + "RequirementMet": true + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + "Get-HostedContentFilterPolicy" + ], + "Control": "Defender 2.6", + "Criticality": "Should", + "ReportDetails": "Requirement met", + "Requirement": "The bulk complaint level (BCL) threshold SHOULD be set to six or lower: non-default policies", + "RequirementMet": true + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + "Get-HostedContentFilterPolicy" + ], + "Control": "Defender 2.6", + "Criticality": "Should", + "ReportDetails": "Requirement met", + "Requirement": "Zero-hour auto purge (ZAP) SHOULD be enabled for Spam: non-default", + "RequirementMet": true + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + "Get-HostedContentFilterPolicy" + ], + "Control": "Defender 2.6", + "Criticality": "Should", + "ReportDetails": "Requirement met", + "Requirement": "Zero-hour auto purge (ZAP) SHOULD be enabled for phishing: non-default", + "RequirementMet": true + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + "Get-HostedContentFilterPolicy" + ], + "Control": "Defender 2.6", + "Criticality": "Should", + "ReportDetails": "Requirement met", + "Requirement": "Zero-hour auto purge (ZAP) SHOULD be enabled: non-default", + "RequirementMet": true + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + "Get-HostedContentFilterPolicy" + ], + "Criticality": "Shall", + "PolicyId": "MS.DEFENDER.6.8v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + "Get-MalwareFilterPolicy" + ], + "Criticality": "Shall", + "PolicyId": "MS.DEFENDER.3.1v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + "Get-MalwareFilterPolicy" + ], + "Criticality": "Should", + "PolicyId": "MS.DEFENDER.4.1v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + "Get-SafeAttachmentPolicy", + "Get-SafeAttachmentRule", + "Get-AcceptedDomain" + ], + "Criticality": "Shall", + "PolicyId": "MS.DEFENDER.8.2v1", + "ReportDetails": "No enabled policy found with action set to block that apply to all domains", + "RequirementMet": false + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + "Get-SafeAttachmentPolicy", + "Get-SafeAttachmentRule", + "Get-AcceptedDomain" + ], + "Criticality": "Should", + "PolicyId": "MS.DEFENDER.8.3v1", + "ReportDetails": "No enabled policy found with action set to block and at least one contact specified", + "RequirementMet": false + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + "Get-SafeAttachmentRule", + "Get-AcceptedDomain" + ], + "Criticality": "Shall", + "PolicyId": "MS.DEFENDER.8.1v1", + "ReportDetails": "No policy found that applies to all domains: alexwilber.myo365.site, y2zj1.onmicrosoft.com", + "RequirementMet": false + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + "Get-SafeLinksPolicy", + "Get-SafeLinksRule" + ], + "Criticality": "Shall", + "PolicyId": "MS.DEFENDER.7.2v1", + "ReportDetails": "Requirement not met", + "RequirementMet": false + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + "Get-SafeLinksPolicy", + "Get-SafeLinksRule" + ], + "Criticality": "Shall", + "PolicyId": "MS.DEFENDER.7.3v1", + "ReportDetails": "Requirement not met", + "RequirementMet": false + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + "Get-SafeLinksPolicy", + "Get-SafeLinksRule" + ], + "Criticality": "Shall", + "PolicyId": "MS.DEFENDER.7.4v1", + "ReportDetails": "Requirement not met", + "RequirementMet": false + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + "Get-SafeLinksPolicy", + "Get-SafeLinksRule" + ], + "Criticality": "Shall", + "PolicyId": "MS.DEFENDER.7.5v1", + "ReportDetails": "Requirement not met", + "RequirementMet": false + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + "Get-SafeLinksPolicy", + "Get-SafeLinksRule" + ], + "Criticality": "Shall", + "PolicyId": "MS.DEFENDER.7.6v1", + "ReportDetails": "Requirement not met", + "RequirementMet": false + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + "Get-SafeLinksPolicy", + "Get-SafeLinksRule" + ], + "Criticality": "Shall", + "PolicyId": "MS.DEFENDER.7.7v1", + "ReportDetails": "Requirement not met", + "RequirementMet": false + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + "Get-SafeLinksPolicy", + "Get-SafeLinksRule" + ], + "Criticality": "Shall", + "PolicyId": "MS.DEFENDER.7.8v1", + "ReportDetails": "Requirement not met", + "RequirementMet": false + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + "Get-SafeLinksPolicy", + "Get-SafeLinksRule" + ], + "Criticality": "Shall", + "PolicyId": "MS.DEFENDER.7.9v1", + "ReportDetails": "Requirement not met", + "RequirementMet": false + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + "Get-SafeLinksRule", + "Get-AcceptedDomain" + ], + "Criticality": "Shall", + "PolicyId": "MS.DEFENDER.7.1v1", + "ReportDetails": "No policy found that applies to all domains: alexwilber.myo365.site, y2zj1.onmicrosoft.com", + "RequirementMet": false + }, + { + "ActualValue": [ + "Default" + ], + "Commandlet": [ + "Get-MalwareFilterPolicy" + ], + "Control": "Defender 2.3", + "Criticality": "Should", + "ReportDetails": "Requirement met", + "Requirement": "Disallowed file types SHALL be determined and set. At a minimum, click-to-run files SHOULD be blocked: cmd files", + "RequirementMet": true + }, + { + "ActualValue": [ + "Default" + ], + "Commandlet": [ + "Get-MalwareFilterPolicy" + ], + "Control": "Defender 2.3", + "Criticality": "Should", + "ReportDetails": "Requirement met", + "Requirement": "Disallowed file types SHALL be determined and set. At a minimum, click-to-run files SHOULD be blocked: vbe files", + "RequirementMet": true + }, + { + "ActualValue": [ + "Default" + ], + "Commandlet": [ + "Get-MalwareFilterPolicy" + ], + "Criticality": "Should", + "PolicyId": "MS.DEFENDER.3.2v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [ + "Default Teams DLP policy rule" + ], + "Commandlet": [ + "Get-DlpComplianceRule" + ], + "Criticality": "Should", + "PolicyId": "MS.DEFENDER.2.4v1", + "ReportDetails": "1 rule(s) found that do(es) not notify at least one user: Default Teams DLP policy rule", + "RequirementMet": false + }, + { + "ActualValue": [ + "Default Teams DLP policy rule", + "Items with 10 or more credit card numbers shared externally" + ], + "Commandlet": [ + "Get-DlpComplianceRule" + ], + "Control": "Defender 2.2", + "Criticality": "Shall", + "ReportDetails": "Requirement met", + "Requirement": "A custom policy SHALL be configured to protect PII and sensitive information, as defined by the agency: Credit Card Number", + "RequirementMet": true + }, + { + "ActualValue": [ + "Default Teams DLP policy rule", + "Items with 10 or more credit card numbers shared externally" + ], + "Commandlet": [ + "Get-DlpComplianceRule" + ], + "Criticality": "Should", + "PolicyId": "MS.DEFENDER.2.3v1", + "ReportDetails": "2 rule(s) found that do(es) not block access or associated policy not set to enforce block action: Default Teams DLP policy rule, Items with 10 or more credit card numbers shared externally", + "RequirementMet": false + }, + { + "ActualValue": [ + "Enabled" + ], + "Commandlet": [ + "Get-EOPProtectionPolicyRule" + ], + "Control": "Defender 2.1", + "Criticality": "Should", + "ReportDetails": "The Strict Preset Security Policy is present and not disabled", + "Requirement": "Strict Preset security profiles SHOULD NOT be used", + "RequirementMet": false + }, + { + "ActualValue": [ + "Enabled" + ], + "Commandlet": [ + "Get-EOPProtectionPolicyRule" + ], + "Criticality": "Should", + "PolicyId": "MS.DEFENDER.1.1v1", + "ReportDetails": "The Standard Preset Security Policy is present and not disabled", + "RequirementMet": false + }, + { + "ActualValue": [ + "Malware campaign detected after delivery", + "Unusual increase in email reported as phish" + ], + "Commandlet": [ + "Get-ProtectionAlert" + ], + "Criticality": "Shall", + "PolicyId": "MS.DEFENDER.9.1v1", + "ReportDetails": "2 disabled required alert(s) found: Malware campaign detected after delivery, Unusual increase in email reported as phish", + "RequirementMet": false + }, + { + "ActualValue": [ + "Strict Preset Security Policy1685627357814" + ], + "Commandlet": [ + "Get-AntiPhishPolicy" + ], + "Control": "Defender 2.5", + "Criticality": "Should", + "ReportDetails": "1 custom anti phish policy(ies) found where first contact safety tips are not enabled: Strict Preset Security Policy1685627357814", + "Requirement": "All safety tips SHOULD be enabled: first contact non-default policies", + "RequirementMet": false + }, + { + "ActualValue": [ + { + "Action": "MoveToJmf", + "IntelligenceProtection": true, + "Name": "Standard Preset Security Policy1685627231985" + }, + { + "Action": "Quarantine", + "IntelligenceProtection": true, + "Name": "Strict Preset Security Policy1685627357814" + } + ], + "Commandlet": [ + "Get-AntiPhishPolicy" + ], + "Criticality": "Should", + "PolicyId": "MS.DEFENDER.5.5v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [ + { + "Action": "Quarantine", + "Name": "Standard Preset Security Policy1685627231985", + "OrgDomains": true + }, + { + "Action": "Quarantine", + "Name": "Strict Preset Security Policy1685627357814", + "OrgDomains": true + } + ], + "Commandlet": [ + "Get-AntiPhishPolicy" + ], + "Criticality": "Should", + "PolicyId": "MS.DEFENDER.5.2v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [ + { + "EnableATPForSPOTeamsODB": true, + "Identity": "Default" + } + ], + "Commandlet": [ + "Get-AtpPolicyForO365" + ], + "Criticality": "Should", + "PolicyId": "MS.DEFENDER.8.4v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [ + { + "Identity": "Admin Audit Log Settings", + "UnifiedAuditLogIngestionEnabled": true + } + ], + "Commandlet": [ + "Get-AdminAuditLogConfig" + ], + "Criticality": "Shall", + "PolicyId": "MS.DEFENDER.10.1v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [ + { + "Locations": [ + "All" + ], + "Name": "Default Office 365 DLP policy", + "Workload": "Exchange, SharePoint, OneDriveForBusiness" + } + ], + "Commandlet": [ + "Get-DLPCompliancePolicy" + ], + "Control": "Defender 2.2", + "Criticality": "Should", + "ReportDetails": "Requirement met", + "Requirement": "The custom policy SHOULD be applied in SharePoint", + "RequirementMet": true + }, + { + "ActualValue": [ + { + "Locations": [ + "All" + ], + "Name": "Default Office 365 DLP policy", + "Workload": "Exchange, SharePoint, OneDriveForBusiness" + } + ], + "Commandlet": [ + "Get-DLPCompliancePolicy" + ], + "Criticality": "Should", + "PolicyId": "MS.DEFENDER.2.2v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [ + { + "Locations": [ + "All" + ], + "Name": "Default policy for Teams", + "Workload": "Exchange, SharePoint, OneDriveForBusiness, Teams" + } + ], + "Commandlet": [ + "Get-DLPCompliancePolicy" + ], + "Control": "Defender 2.2", + "Criticality": "Should", + "ReportDetails": "Requirement met", + "Requirement": "The custom policy SHOULD be applied in Teams", + "RequirementMet": true + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + + ], + "Criticality": "Shall/3rd Party", + "PolicyId": "MS.EXO.10.1v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + + ], + "Criticality": "Shall/3rd Party", + "PolicyId": "MS.EXO.10.2v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + + ], + "Criticality": "Shall/3rd Party", + "PolicyId": "MS.EXO.14.1v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + + ], + "Criticality": "Shall/3rd Party", + "PolicyId": "MS.EXO.14.2v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + + ], + "Criticality": "Shall/3rd Party", + "PolicyId": "MS.EXO.14.3v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + + ], + "Criticality": "Shall/3rd Party", + "PolicyId": "MS.EXO.16.1v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + + ], + "Criticality": "Shall/3rd Party", + "PolicyId": "MS.EXO.17.1v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + + ], + "Criticality": "Shall/3rd Party", + "PolicyId": "MS.EXO.17.2v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + + ], + "Criticality": "Shall/3rd Party", + "PolicyId": "MS.EXO.17.3v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + + ], + "Criticality": "Shall/3rd Party", + "PolicyId": "MS.EXO.8.1v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + + ], + "Criticality": "Shall/3rd Party", + "PolicyId": "MS.EXO.8.2v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + + ], + "Criticality": "Shall/3rd Party", + "PolicyId": "MS.EXO.9.1v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + + ], + "Criticality": "Shall/3rd Party", + "PolicyId": "MS.EXO.9.3v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + + ], + "Criticality": "Shall/Not-Implemented", + "PolicyId": "MS.EXO.2.1v1", + "ReportDetails": "Not currently checked automatically. See \u003ca href=\"https://github.com/cisagov/ScubaGear/blob/0.3.0/baselines/exo.md#msexo21v1\" target=\"_blank\"\u003eSecure Configuration Baseline policy\u003c/a\u003e for instructions on manual check", + "RequirementMet": false + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + + ], + "Criticality": "Should/3rd Party", + "PolicyId": "MS.EXO.10.3v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + + ], + "Criticality": "Should/3rd Party", + "PolicyId": "MS.EXO.11.1v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + + ], + "Criticality": "Should/3rd Party", + "PolicyId": "MS.EXO.11.2v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + + ], + "Criticality": "Should/3rd Party", + "PolicyId": "MS.EXO.11.3v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + + ], + "Criticality": "Should/3rd Party", + "PolicyId": "MS.EXO.15.1v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + + ], + "Criticality": "Should/3rd Party", + "PolicyId": "MS.EXO.15.2v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + + ], + "Criticality": "Should/3rd Party", + "PolicyId": "MS.EXO.15.3v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + + ], + "Criticality": "Should/3rd Party", + "PolicyId": "MS.EXO.16.2v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + + ], + "Criticality": "Should/3rd Party", + "PolicyId": "MS.EXO.9.2v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + "Get-ScubaDmarcRecords", + "Get-AcceptedDomain" + ], + "Criticality": "Shall", + "PolicyId": "MS.EXO.4.1v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + "Get-ScubaDmarcRecords", + "Get-AcceptedDomain" + ], + "Criticality": "Shall", + "PolicyId": "MS.EXO.4.2v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + "Get-ScubaDmarcRecords", + "Get-AcceptedDomain" + ], + "Criticality": "Shall", + "PolicyId": "MS.EXO.4.3v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + "Get-ScubaDmarcRecords", + "Get-AcceptedDomain" + ], + "Criticality": "Should", + "PolicyId": "MS.EXO.4.4v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + "Get-TransportRule" + ], + "Criticality": "Shall", + "PolicyId": "MS.EXO.7.1v1", + "ReportDetails": "No transport rule found that applies warnings to emails received from outside the organization", + "RequirementMet": false + }, + { + "ActualValue": [ + [ + + ], + [ + null + ] + ], + "Commandlet": [ + "Get-DkimSigningConfig", + "Get-ScubaDkimRecords", + "Get-AcceptedDomain" + ], + "Criticality": "Should", + "PolicyId": "MS.EXO.3.1v1", + "ReportDetails": "1 of 1 agency domain(s) found in violation: alexwilber.myo365.site", + "RequirementMet": false + }, + { + "ActualValue": [ + { + "AddressBookPolicyRoutingEnabled": false, + "AdminDisplayName": "", + "AgentGeneratedMessageLoopDetectionInSmtpEnabled": true, + "AgentGeneratedMessageLoopDetectionInSubmissionEnabled": true, + "AllowLegacyTLSClients": false, + "AnonymousSenderToRecipientRatePerHour": 1800, + "AttributionRejectBeforeMServRequest": false, + "AttributionRejectConsumerMessages": false, + "ClearCategories": true, + "ConvertDisclaimerWrapperToEml": false, + "ConvertReportToMessage": false, + "CurrentTransportSystemState": "Green", + "DSNConversionMode": "PreserveDSNBody", + "DiagnosticsAggregationServicePort": 9710, + "DistinguishedName": "CN=Transport Settings,CN=Configuration,CN=y2zj1.onmicrosoft.com,CN=ConfigurationUnits,DC=NAMPR10A008,DC=PROD,DC=OUTLOOK,DC=COM", + "EnableExternalHTTPMailDelivery": false, + "ExchangeObjectId": "b4f29764-fa61-4718-ac8d-29e1ad3007b9", + "ExchangeVersion": "0.1 (8.0.535.0)", + "ExternalDelayDsnEnabled": true, + "ExternalDsnDefaultLanguage": null, + "ExternalDsnLanguageDetectionEnabled": true, + "ExternalDsnMaxMessageAttachSize": "10 MB (10,485,760 bytes)", + "ExternalDsnReportingAuthority": null, + "ExternalDsnSendHtml": true, + "ExternalPostmasterAddress": null, + "GenerateCopyOfDSNFor": [ + + ], + "Guid": "b4f29764-fa61-4718-ac8d-29e1ad3007b9", + "HeaderPromotionModeSetting": "NoCreate", + "HygieneSuite": "Premium", + "Id": "Transport Settings", + "Identity": "Transport Settings", + "InternalDelayDsnEnabled": true, + "InternalDsnDefaultLanguage": null, + "InternalDsnLanguageDetectionEnabled": true, + "InternalDsnMaxMessageAttachSize": "10 MB (10,485,760 bytes)", + "InternalDsnReportingAuthority": null, + "InternalDsnSendHtml": true, + "InternalSMTPServers": [ + + ], + "IsValid": true, + "JournalArchivingEnabled": false, + "JournalMessageExpirationDays": 0, + "JournalReportDLMemberSubstitutionEnabled": false, + "JournalingReportNdrTo": "u003cu003e", + "LegacyArchiveJournalingEnabled": false, + "LegacyArchiveLiveJournalingEnabled": false, + "LegacyJournalingMigrationEnabled": false, + "MaxAllowedAgentGeneratedMessageDepth": 3, + "MaxAllowedAgentGeneratedMessageDepthPerAgent": 2, + "MaxDumpsterSizePerDatabase": "18 MB (18,874,368 bytes)", + "MaxDumpsterTime": "7.00:00:00", + "MaxReceiveSize": "Unlimited", + "MaxRecipientEnvelopeLimit": "Unlimited", + "MaxSendSize": "Unlimited", + "MessageExpiration": "1.00:00:00", + "MigrationEnabled": true, + "Name": "Transport Settings", + "ObjectCategory": "NAMPR10A008.PROD.OUTLOOK.COM/Configuration/Schema/ms-Exch-Transport-Settings", + "ObjectClass": [ + "top", + "container", + "msExchTransportSettings" + ], + "ObjectState": "Unchanged", + "OpenDomainRoutingEnabled": false, + "OrganizationFederatedMailbox": "FederatedEmail.4c1f4d8b-8179-4148-93bf-00a95fa1e042@y2zj1.onmicrosoft.com", + "OrganizationId": "NAMPR10A008.PROD.OUTLOOK.COM/Microsoft Exchange Hosted Organizations/y2zj1.onmicrosoft.com - NAMPR10A008.PROD.OUTLOOK.COM/ConfigurationUnits/y2zj1.onmicrosoft.com/Configuration", + "OrganizationalUnitRoot": "y2zj1.onmicrosoft.com", + "OriginatingServer": "BN6PR10A08DC001.NAMPR10A008.PROD.OUTLOOK.COM", + "OtherWellKnownObjects": [ + + ], + "PreserveReportBodypart": true, + "QueueDiagnosticsAggregationInterval": "00:01:00", + "RedirectDLMessagesForLegacyArchiveJournaling": false, + "RedirectUnprovisionedUserMessagesForLegacyArchiveJournaling": false, + "ReplyAllStormBlockDurationHours": 6, + "ReplyAllStormDetectionMinimumRecipients": 2500, + "ReplyAllStormDetectionMinimumReplies": 10, + "ReplyAllStormProtectionEnabled": true, + "Rfc2231EncodingEnabled": false, + "SafetyNetHoldTime": "7.00:00:00", + "SmtpClientAuthenticationDisabled": true, + "SupervisionTags": [ + "Reject", + "Allow" + ], + "TLSReceiveDomainSecureList": [ + + ], + "TLSSendDomainSecureList": [ + + ], + "TransportRuleAttachmentTextScanLimit": "1 MB (1,048,576 bytes)", + "TransportRuleCollectionAddedRecipientsLimit": 100, + "TransportRuleCollectionRegexCharsLimit": "20 KB (20,480 bytes)", + "TransportRuleConfig": [ + "TransportRuleMinProductVersion:14.0.0.0", + "TransportRuleRegexValidationTimeout:00:00:00.3000000", + "TransportRuleAttachmentTextScanLimit:1 MB (1,048,576 bytes)", + "TransportRuleSizeLimit:8 KB (8,192 bytes)", + "TransportRuleCollectionRegexCharsLimit:20 KB (20,480 bytes)", + "TransportRuleLimit:300", + "TransportRuleCollectionAddedRecipientsLimit:100" + ], + "TransportRuleLimit": 300, + "TransportRuleMinProductVersion": { + "Build": 0, + "Major": 14, + "MajorRevision": 0, + "Minor": 0, + "MinorRevision": 0, + "Revision": 0 + }, + "TransportRuleRegexValidationTimeout": "00:00:00.3000000", + "TransportRuleSizeLimit": "8 KB (8,192 bytes)", + "TransportSystemState": "", + "VerifySecureSubmitEnabled": false, + "VoicemailJournalingEnabled": true, + "WhenChanged": "/Date(1643184493000)/", + "WhenChangedUTC": "/Date(1643184493000)/", + "WhenCreated": "/Date(1643059670000)/", + "WhenCreatedUTC": "/Date(1643059670000)/", + "Xexch50Enabled": true + } + ], + "Commandlet": [ + "Get-TransportConfig" + ], + "Criticality": "Shall", + "PolicyId": "MS.EXO.5.1v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [ + { + "AdminDisplayName": "", + "Default": true, + "DistinguishedName": "CN=Default Sharing Policy,CN=Federation,CN=Configuration,CN=y2zj1.onmicrosoft.com,CN=ConfigurationUnits,DC=NAMPR10A008,DC=PROD,DC=OUTLOOK,DC=COM", + "Domains": [ + "Anonymous:CalendarSharingFreeBusyReviewer", + "*:CalendarSharingFreeBusySimple" + ], + "Enabled": true, + "ExchangeObjectId": "2f1ca8cf-5ba5-45e3-b73a-1405ff552a2e", + "ExchangeVersion": "0.10 (14.0.100.0)", + "Guid": "2f1ca8cf-5ba5-45e3-b73a-1405ff552a2e", + "Id": "Default Sharing Policy", + "Identity": "Default Sharing Policy", + "IsValid": true, + "Name": "Default Sharing Policy", + "ObjectCategory": "NAMPR10A008.PROD.OUTLOOK.COM/Configuration/Schema/ms-Exch-Sharing-Policy", + "ObjectClass": [ + "top", + "msExchSharingPolicy" + ], + "ObjectState": "Changed", + "OrganizationId": "NAMPR10A008.PROD.OUTLOOK.COM/Microsoft Exchange Hosted Organizations/y2zj1.onmicrosoft.com - NAMPR10A008.PROD.OUTLOOK.COM/ConfigurationUnits/y2zj1.onmicrosoft.com/Configuration", + "OrganizationalUnitRoot": "y2zj1.onmicrosoft.com", + "OriginatingServer": "BN6PR10A08DC001.NAMPR10A008.PROD.OUTLOOK.COM", + "WhenChanged": "/Date(1645650762000)/", + "WhenChangedUTC": "/Date(1645650762000)/", + "WhenCreated": "/Date(1645650752000)/", + "WhenCreatedUTC": "/Date(1645650752000)/" + } + ], + "Commandlet": [ + "Get-SharingPolicy" + ], + "Criticality": "Shall", + "PolicyId": "MS.EXO.6.1v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [ + { + "AdminDisplayName": "", + "Default": true, + "DistinguishedName": "CN=Default Sharing Policy,CN=Federation,CN=Configuration,CN=y2zj1.onmicrosoft.com,CN=ConfigurationUnits,DC=NAMPR10A008,DC=PROD,DC=OUTLOOK,DC=COM", + "Domains": [ + "Anonymous:CalendarSharingFreeBusyReviewer", + "*:CalendarSharingFreeBusySimple" + ], + "Enabled": true, + "ExchangeObjectId": "2f1ca8cf-5ba5-45e3-b73a-1405ff552a2e", + "ExchangeVersion": "0.10 (14.0.100.0)", + "Guid": "2f1ca8cf-5ba5-45e3-b73a-1405ff552a2e", + "Id": "Default Sharing Policy", + "Identity": "Default Sharing Policy", + "IsValid": true, + "Name": "Default Sharing Policy", + "ObjectCategory": "NAMPR10A008.PROD.OUTLOOK.COM/Configuration/Schema/ms-Exch-Sharing-Policy", + "ObjectClass": [ + "top", + "msExchSharingPolicy" + ], + "ObjectState": "Changed", + "OrganizationId": "NAMPR10A008.PROD.OUTLOOK.COM/Microsoft Exchange Hosted Organizations/y2zj1.onmicrosoft.com - NAMPR10A008.PROD.OUTLOOK.COM/ConfigurationUnits/y2zj1.onmicrosoft.com/Configuration", + "OrganizationalUnitRoot": "y2zj1.onmicrosoft.com", + "OriginatingServer": "BN6PR10A08DC001.NAMPR10A008.PROD.OUTLOOK.COM", + "WhenChanged": "/Date(1645650762000)/", + "WhenChangedUTC": "/Date(1645650762000)/", + "WhenCreated": "/Date(1645650752000)/", + "WhenCreatedUTC": "/Date(1645650752000)/" + } + ], + "Commandlet": [ + "Get-SharingPolicy" + ], + "Criticality": "Shall", + "PolicyId": "MS.EXO.6.2v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [ + { + "AdminDisplayName": "", + "DirectoryBasedEdgeBlockMode": "Default", + "DistinguishedName": "CN=Default,CN=Hosted Connection Filter,CN=Transport Settings,CN=Configuration,CN=y2zj1.onmicrosoft.com,CN=ConfigurationUnits,DC=NAMPR10A008,DC=PROD,DC=OUTLOOK,DC=COM", + "EnableSafeList": false, + "ExchangeObjectId": "3843aef3-f3bd-49c1-a674-4d6741ac11b6", + "ExchangeVersion": "0.20 (15.0.0.0)", + "Guid": "3843aef3-f3bd-49c1-a674-4d6741ac11b6", + "IPAllowList": [ + + ], + "IPBlockList": [ + + ], + "Id": "Default", + "Identity": "Default", + "IsDefault": true, + "IsValid": true, + "Name": "Default", + "ObjectCategory": "NAMPR10A008.PROD.OUTLOOK.COM/Configuration/Schema/ms-Exch-Hosted-Connection-Filter-Policy", + "ObjectClass": [ + "top", + "msExchHostedConnectionFilterPolicy" + ], + "ObjectState": "Unchanged", + "OrganizationId": "NAMPR10A008.PROD.OUTLOOK.COM/Microsoft Exchange Hosted Organizations/y2zj1.onmicrosoft.com - NAMPR10A008.PROD.OUTLOOK.COM/ConfigurationUnits/y2zj1.onmicrosoft.com/Configuration", + "OrganizationalUnitRoot": "y2zj1.onmicrosoft.com", + "OriginatingServer": "BN6PR10A08DC001.NAMPR10A008.PROD.OUTLOOK.COM", + "WhenChanged": "/Date(1645650841000)/", + "WhenChangedUTC": "/Date(1645650841000)/", + "WhenCreated": "/Date(1645650828000)/", + "WhenCreatedUTC": "/Date(1645650828000)/" + } + ], + "Commandlet": [ + "Get-HostedConnectionFilterPolicy" + ], + "Criticality": "Should", + "PolicyId": "MS.EXO.12.1v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [ + { + "AdminDisplayName": "", + "DirectoryBasedEdgeBlockMode": "Default", + "DistinguishedName": "CN=Default,CN=Hosted Connection Filter,CN=Transport Settings,CN=Configuration,CN=y2zj1.onmicrosoft.com,CN=ConfigurationUnits,DC=NAMPR10A008,DC=PROD,DC=OUTLOOK,DC=COM", + "EnableSafeList": false, + "ExchangeObjectId": "3843aef3-f3bd-49c1-a674-4d6741ac11b6", + "ExchangeVersion": "0.20 (15.0.0.0)", + "Guid": "3843aef3-f3bd-49c1-a674-4d6741ac11b6", + "IPAllowList": [ + + ], + "IPBlockList": [ + + ], + "Id": "Default", + "Identity": "Default", + "IsDefault": true, + "IsValid": true, + "Name": "Default", + "ObjectCategory": "NAMPR10A008.PROD.OUTLOOK.COM/Configuration/Schema/ms-Exch-Hosted-Connection-Filter-Policy", + "ObjectClass": [ + "top", + "msExchHostedConnectionFilterPolicy" + ], + "ObjectState": "Unchanged", + "OrganizationId": "NAMPR10A008.PROD.OUTLOOK.COM/Microsoft Exchange Hosted Organizations/y2zj1.onmicrosoft.com - NAMPR10A008.PROD.OUTLOOK.COM/ConfigurationUnits/y2zj1.onmicrosoft.com/Configuration", + "OrganizationalUnitRoot": "y2zj1.onmicrosoft.com", + "OriginatingServer": "BN6PR10A08DC001.NAMPR10A008.PROD.OUTLOOK.COM", + "WhenChanged": "/Date(1645650841000)/", + "WhenChangedUTC": "/Date(1645650841000)/", + "WhenCreated": "/Date(1645650828000)/", + "WhenCreatedUTC": "/Date(1645650828000)/" + } + ], + "Commandlet": [ + "Get-HostedConnectionFilterPolicy" + ], + "Criticality": "Should", + "PolicyId": "MS.EXO.12.2v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [ + { + "AuditDisabled": false, + "DisplayName": "y2zj1", + "Name": "y2zj1.onmicrosoft.com" + } + ], + "Commandlet": [ + "Get-OrganizationConfig" + ], + "Criticality": "Shall", + "PolicyId": "MS.EXO.13.1v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + "Get-ScubaSpfRecords", + "Get-AcceptedDomain" + ], + "Criticality": "Shall", + "PolicyId": "MS.EXO.2.2v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [ + "*" + ], + "Commandlet": [ + "Get-RemoteDomain" + ], + "Criticality": "Shall", + "PolicyId": "MS.EXO.1.1v1", + "ReportDetails": "1 remote domain(s) that allows automatic forwarding: *", + "RequirementMet": false + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + + ], + "Criticality": "Shall/Not-Implemented", + "PolicyId": "MS.ONEDRIVE.6.1v1", + "ReportDetails": "Not currently checked automatically. See \u003ca href=\"https://github.com/cisagov/ScubaGear/blob/0.3.0/baselines/onedrive.md#msonedrive61v1\" target=\"_blank\"\u003eSecure Configuration Baseline policy\u003c/a\u003e for instructions on manual check", + "RequirementMet": false + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + + ], + "Criticality": "Shall/Not-Implemented", + "PolicyId": "MS.ONEDRIVE.7.1v1", + "ReportDetails": "Not currently checked automatically. See \u003ca href=\"https://github.com/cisagov/ScubaGear/blob/0.3.0/baselines/onedrive.md#msonedrive71v1\" target=\"_blank\"\u003eSecure Configuration Baseline policy\u003c/a\u003e for instructions on manual check", + "RequirementMet": false + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + + ], + "Criticality": "Should/Not-Implemented", + "PolicyId": "MS.ONEDRIVE.1.1v1", + "ReportDetails": "Not currently checked automatically. See \u003ca href=\"https://github.com/cisagov/ScubaGear/blob/0.3.0/baselines/onedrive.md#msonedrive11v1\" target=\"_blank\"\u003eSecure Configuration Baseline policy\u003c/a\u003e for instructions on manual check", + "RequirementMet": false + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + + ], + "Criticality": "Should/Not-Implemented", + "PolicyId": "MS.ONEDRIVE.2.1v1", + "ReportDetails": "Not currently checked automatically. See \u003ca href=\"https://github.com/cisagov/ScubaGear/blob/0.3.0/baselines/onedrive.md#msonedrive21v1\" target=\"_blank\"\u003eSecure Configuration Baseline policy\u003c/a\u003e for instructions on manual check", + "RequirementMet": false + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + + ], + "Criticality": "Should/Not-Implemented", + "PolicyId": "MS.ONEDRIVE.2.2v1", + "ReportDetails": "Not currently checked automatically. See \u003ca href=\"https://github.com/cisagov/ScubaGear/blob/0.3.0/baselines/onedrive.md#msonedrive22v1\" target=\"_blank\"\u003eSecure Configuration Baseline policy\u003c/a\u003e for instructions on manual check", + "RequirementMet": false + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + + ], + "Criticality": "Should/Not-Implemented", + "PolicyId": "MS.ONEDRIVE.3.1v1", + "ReportDetails": "Not currently checked automatically. See \u003ca href=\"https://github.com/cisagov/ScubaGear/blob/0.3.0/baselines/onedrive.md#msonedrive31v1\" target=\"_blank\"\u003eSecure Configuration Baseline policy\u003c/a\u003e for instructions on manual check", + "RequirementMet": false + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + "Get-SPOTenantSyncClientRestriction", + "Get-PnPTenantSyncClientRestriction" + ], + "Criticality": "Shall", + "PolicyId": "MS.ONEDRIVE.5.1v1", + "ReportDetails": "Requirement not met", + "Requirement": "OneDrive Client Sync SHALL only be allowed only within the local domain", + "RequirementMet": false + }, + { + "ActualValue": [ + { + "AllowedDomainList": [ + "786548dd-877b-4760-a749-6b1efbc1190a" + ], + "BlockMacSync": true, + "DisableReportProblemDialog": false, + "ExcludedFileExtensions": [ + "" + ], + "OptOutOfGrooveBlock": false, + "OptOutOfGrooveSoftBlock": false, + "TenantRestrictionEnabled": true + } + ], + "Commandlet": [ + "Get-SPOTenant", + "Get-PnPTenant" + ], + "Criticality": "Shall", + "PolicyId": "MS.ONEDRIVE.4.1v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": false, + "Commandlet": [ + "Get-PowerAppTenantIsolationPolicy" + ], + "Criticality": "Shall", + "PolicyId": "MS.POWERPLATFORM.3.1v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": true, + "Commandlet": [ + "Get-TenantSettings" + ], + "Control": "Power Platform 2.1", + "Criticality": "Shall", + "ReportDetails": "Requirement met", + "Requirement": "The ability to create trial environments SHALL be restricted to admins", + "RequirementMet": true + }, + { + "ActualValue": true, + "Commandlet": [ + "Get-TenantSettings" + ], + "Criticality": "Shall", + "PolicyId": "MS.POWERPLATFORM.1.1v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": "No DLP Policies found", + "Commandlet": [ + "Get-DlpPolicy" + ], + "Criticality": "Should", + "PolicyId": "MS.POWERPLATFORM.2.2v1", + "ReportDetails": "No DLP Policies found", + "RequirementMet": false + }, + { + "ActualValue": "No DLP Policies found", + "Commandlet": [ + "Get-DlpPolicy" + ], + "Criticality": "Should", + "PolicyId": "MS.POWERPLATFORM.2.3v1", + "ReportDetails": "No DLP Policies found", + "RequirementMet": false + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + + ], + "Criticality": "Shall/Not-Implemented", + "PolicyId": "MS.POWERPLATFORM.4.1v1", + "ReportDetails": "Not currently checked automatically. See \u003ca href=\"https://github.com/cisagov/ScubaGear/blob/0.3.0/baselines/powerplatform.md#mspowerplatform41v1\" target=\"_blank\"\u003eSecure Configuration Baseline policy\u003c/a\u003e for instructions on manual check", + "RequirementMet": false + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + + ], + "Criticality": "Should/Not-Implemented", + "PolicyId": "MS.POWERPLATFORM.3.2v1", + "ReportDetails": "Not currently checked automatically. See \u003ca href=\"https://github.com/cisagov/ScubaGear/blob/0.3.0/baselines/powerplatform.md#mspowerplatform32v1\" target=\"_blank\"\u003eSecure Configuration Baseline policy\u003c/a\u003e for instructions on manual check", + "RequirementMet": false + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + + ], + "Criticality": "Should/Not-Implemented", + "PolicyId": "MS.POWERPLATFORM.3.3v1", + "ReportDetails": "Not currently checked automatically. See \u003ca href=\"https://github.com/cisagov/ScubaGear/blob/0.3.0/baselines/powerplatform.md#mspowerplatform33v1\" target=\"_blank\"\u003eSecure Configuration Baseline policy\u003c/a\u003e for instructions on manual check", + "RequirementMet": false + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + "Get-DlpPolicy" + ], + "Criticality": "Shall", + "PolicyId": "MS.POWERPLATFORM.2.1v1", + "ReportDetails": "No policy found that applies to default environment", + "RequirementMet": false + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + + ], + "Criticality": "Shall/Not-Implemented", + "PolicyId": "MS.SHAREPOINT.5.1v1", + "ReportDetails": "Not currently checked automatically. See \u003ca href=\"https://github.com/cisagov/ScubaGear/blob/0.3.0/baselines/sharepoint.md#mssharepoint51v1\" target=\"_blank\"\u003eSecure Configuration Baseline policy\u003c/a\u003e for instructions on manual check", + "RequirementMet": false + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + + ], + "Criticality": "Should/Not-Implemented", + "PolicyId": "MS.SHAREPOINT.1.3v1", + "ReportDetails": "Not currently checked automatically. See \u003ca href=\"https://github.com/cisagov/ScubaGear/blob/0.3.0/baselines/sharepoint.md#mssharepoint13v1\" target=\"_blank\"\u003eSecure Configuration Baseline policy\u003c/a\u003e for instructions on manual check", + "RequirementMet": false + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + + ], + "Criticality": "Should/Not-Implemented", + "PolicyId": "MS.SHAREPOINT.3.1v1", + "ReportDetails": "Not currently checked automatically. See \u003ca href=\"https://github.com/cisagov/ScubaGear/blob/0.3.0/baselines/sharepoint.md#mssharepoint31v1\" target=\"_blank\"\u003eSecure Configuration Baseline policy\u003c/a\u003e for instructions on manual check", + "RequirementMet": false + }, + { + "ActualValue": [ + false + ], + "Commandlet": [ + "Get-SPOTenant", + "Get-PnPTenant" + ], + "Criticality": "Should", + "PolicyId": "MS.SHAREPOINT.1.4v1", + "ReportDetails": "Requirement not met", + "RequirementMet": false + }, + { + "ActualValue": [ + 1 + ], + "Commandlet": [ + "Get-SPOTenant", + "Get-PnPTenant" + ], + "Criticality": "Should", + "PolicyId": "MS.SHAREPOINT.1.1v1", + "ReportDetails": "Requirement not met", + "RequirementMet": false + }, + { + "ActualValue": [ + 1 + ], + "Commandlet": [ + "Get-SPOTenant", + "Get-PnPTenant" + ], + "Criticality": "Should", + "PolicyId": "MS.SHAREPOINT.1.2v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [ + 1, + true, + 29 + ], + "Commandlet": [ + "Get-SPOTenant", + "Get-PnPTenant" + ], + "Criticality": "Should", + "PolicyId": "MS.SHAREPOINT.4.2v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [ + 1, + true, + 31 + ], + "Commandlet": [ + "Get-SPOTenant", + "Get-PnPTenant" + ], + "Criticality": "Should", + "PolicyId": "MS.SHAREPOINT.4.1v1", + "ReportDetails": "Requirement not met: Expiration timer for \u0027Guest access to a site or OneDrive\u0027 NOT set to 30 days or less", + "RequirementMet": false + }, + { + "ActualValue": [ + 2 + ], + "Commandlet": [ + "Get-SPOSite", + "Get-PnPTenantSite" + ], + "Criticality": "Shall", + "PolicyId": "MS.SHAREPOINT.5.2v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [ + 2 + ], + "Commandlet": [ + "Get-SPOTenant", + "Get-PnPTenant" + ], + "Criticality": "Shall", + "PolicyId": "MS.SHAREPOINT.2.1v1", + "ReportDetails": "Requirement not met", + "RequirementMet": false + }, + { + "ActualValue": true, + "Commandlet": [ + "Get-CsTeamsMeetingPolicy" + ], + "Criticality": "Should", + "PolicyId": "MS.TEAMS.9.1v1", + "ReportDetails": "Requirement not met", + "RequirementMet": false + }, + { + "ActualValue": "EveryoneInCompany", + "Commandlet": [ + "Get-CsTeamsMeetingPolicy" + ], + "Criticality": "Should", + "PolicyId": "MS.TEAMS.3.2v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": "UserOverride", + "Commandlet": [ + "Get-CsTeamsMeetingBroadcastPolicy" + ], + "Criticality": "Should", + "PolicyId": "MS.TEAMS.10.1v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + + ], + "Criticality": "Shall/3rd Party", + "PolicyId": "MS.TEAMS.11.1v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + + ], + "Criticality": "Shall/3rd Party", + "PolicyId": "MS.TEAMS.11.4v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + + ], + "Criticality": "Shall/3rd Party", + "PolicyId": "MS.TEAMS.8.3v1", + "ReportDetails": "Not currently checked automatically. See \u003ca href=\"https://github.com/cisagov/ScubaGear/blob/0.3.0/baselines/teams.md#msteams83v1\" target=\"_blank\"\u003eSecure Configuration Baseline policy\u003c/a\u003e for instructions on manual check", + "RequirementMet": false + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + + ], + "Criticality": "Should/3rd Party", + "PolicyId": "MS.TEAMS.11.2v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + + ], + "Criticality": "Should/3rd Party", + "PolicyId": "MS.TEAMS.12.1v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + + ], + "Criticality": "Should/3rd Party", + "PolicyId": "MS.TEAMS.12.2v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + + ], + "Criticality": "Should/3rd Party", + "PolicyId": "MS.TEAMS.13.1v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + + ], + "Criticality": "Should/3rd Party", + "PolicyId": "MS.TEAMS.13.2v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + + ], + "Criticality": "Should/3rd Party", + "PolicyId": "MS.TEAMS.13.3v1", + "ReportDetails": "Custom implementation allowed. If you are using Defender to fulfill this requirement, run the Defender version of this script. Otherwise, use a 3rd party tool OR manually check", + "RequirementMet": false + }, + { + "ActualValue": [ + "EveryoneInCompany", + false + ], + "Commandlet": [ + "Get-CsTeamsMeetingPolicy" + ], + "Criticality": "Should", + "PolicyId": "MS.TEAMS.3.1v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [ + [ + + ], + "MicrosoftCommunicationsOnline/NOAM-ED6-A7" + ], + "Commandlet": [ + "Get-CsTeamsClientConfiguration" + ], + "Criticality": "Shall", + "PolicyId": "MS.TEAMS.7.1v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + "Get-CsTeamsAppPermissionPolicy" + ], + "Criticality": "Should", + "PolicyId": "MS.TEAMS.8.2av1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + "Get-CsTeamsAppPermissionPolicy" + ], + "Criticality": "Should", + "PolicyId": "MS.TEAMS.8.2v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + "Get-CsTeamsMeetingPolicy" + ], + "Control": "Teams 2.4", + "Criticality": "Should", + "ReportDetails": "Requirement met", + "Requirement": "Anonymous users SHOULD be enabled to join meetings", + "RequirementMet": true + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + "Get-CsTeamsMeetingPolicy" + ], + "Criticality": "Shall", + "PolicyId": "MS.TEAMS.2.1v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + "Get-CsTeamsMeetingPolicy" + ], + "Criticality": "Should", + "PolicyId": "MS.TEAMS.1.1v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + "Get-CsTeamsMeetingPolicy" + ], + "Criticality": "Should", + "PolicyId": "MS.TEAMS.9.3v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + "Get-CsTenantFederationConfiguration" + ], + "Criticality": "Shall", + "PolicyId": "MS.TEAMS.4.1v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + "Get-CsTenantFederationConfiguration" + ], + "Criticality": "Shall", + "PolicyId": "MS.TEAMS.5.1v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + "Get-CsTenantFederationConfiguration" + ], + "Criticality": "Shall", + "PolicyId": "MS.TEAMS.6.1v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [ + + ], + "Commandlet": [ + "Get-CsTenantFederationConfiguration" + ], + "Criticality": "Should", + "PolicyId": "MS.TEAMS.5.2v1", + "ReportDetails": "Requirement met", + "RequirementMet": true + }, + { + "ActualValue": [ + "Global", + "Tag:Test Policy" + ], + "Commandlet": [ + "Get-CsTeamsAppPermissionPolicy" + ], + "Criticality": "Should", + "PolicyId": "MS.TEAMS.8.1v1", + "ReportDetails": "2 meeting policy(ies) found that block Microsoft Apps by default: Global, Tag:Test Policy", + "RequirementMet": false } -] \ No newline at end of file +] diff --git a/Testing/Unit/PowerShell/CreateReport/Import-SecureBaseline.Tests.ps1 b/Testing/Unit/PowerShell/CreateReport/Import-SecureBaseline.Tests.ps1 index d1f1b8e80d..e82096590a 100644 --- a/Testing/Unit/PowerShell/CreateReport/Import-SecureBaseline.Tests.ps1 +++ b/Testing/Unit/PowerShell/CreateReport/Import-SecureBaseline.Tests.ps1 @@ -33,10 +33,10 @@ InModuleScope CreateReport { $Baselines.Count | Should -BeExactly 8 -Because "Markdown expected for all products." } It "Validate markdown group count for " -ForEach @( - @{Product = "aad"; GroupCount = 18; PolicyCount = 33} + @{Product = "aad"; GroupCount = 8; PolicyCount = 30} @{Product = "defender"; GroupCount = 6; PolicyCount = 22} @{Product = "exo"; GroupCount = 17; PolicyCount = 39} - @{Product = "onedrive"; GroupCount = 7; PolicyCount = 8} + @{Product = "onedrive"; GroupCount = 3; PolicyCount = 4} @{Product = "powerbi"; GroupCount = 10; PolicyCount = 12} @{Product = "powerplatform"; GroupCount = 4; PolicyCount = 8} @{Product = "sharepoint"; GroupCount = 5; PolicyCount = 10} diff --git a/Testing/Unit/PowerShell/CreateReport/New-Report.Tests.ps1 b/Testing/Unit/PowerShell/CreateReport/New-Report.Tests.ps1 index 79b7a8cffc..f2c44bbf81 100644 --- a/Testing/Unit/PowerShell/CreateReport/New-Report.Tests.ps1 +++ b/Testing/Unit/PowerShell/CreateReport/New-Report.Tests.ps1 @@ -42,12 +42,12 @@ InModuleScope CreateReport { } } It 'Creates a report for ' -ForEach @( - @{Product = 'aad'; WarningCount = 1}, + @{Product = 'aad'; WarningCount = 0}, @{Product = 'defender'; WarningCount = 10}, @{Product = 'exo'; WarningCount = 2}, - @{Product = 'onedrive'; WarningCount = 8}, + @{Product = 'onedrive'; WarningCount = 1}, @{Product = 'powerplatform'; WarningCount = 0}, - @{Product = 'sharepoint'; WarningCount = 5}, + @{Product = 'sharepoint'; WarningCount = 0}, @{Product = 'teams'; WarningCount = 5} ){ $CreateReportParams += @{ From 38ea3ea19405e67792a1cac577fdda555dc02e79 Mon Sep 17 00:00:00 2001 From: Richard Crutchfield Date: Tue, 11 Jul 2023 11:44:59 -0400 Subject: [PATCH 14/33] WIP --- Rego/AADConfig.rego | 43 ++++- Testing/Unit/Rego/AAD/AADConfig_03_test.rego | 184 ++++++++++++++++++- 2 files changed, 215 insertions(+), 12 deletions(-) diff --git a/Rego/AADConfig.rego b/Rego/AADConfig.rego index afabf2391b..083e9d68b9 100644 --- a/Rego/AADConfig.rego +++ b/Rego/AADConfig.rego @@ -268,18 +268,43 @@ tests[{ # # MS.AAD.3.1v1 #-- -# At this time we are unable to fully test for MFA due to conflicting and multiple ways to configure authentication methods -# Awaiting API changes and feature updates from Microsoft for automated checking +default PhishingResistantMFAConditionsMatch(_) := false +HasPhishingResistantMFA(Policy) := true if { + Strengths := { Strength | Strength := Policy.GrantControls.AuthenticationStrength.AllowedCombinations[_]} + AcceptableMFA := {"windowsHelloForBusiness", "fido2", "x509CertificateMultiFactor"} + count(AcceptableMFA) == count(Strengths | AcceptableMFA) +} + +PhishingResistantMFAConditionsMatch(Policy) := true if { + "All" in Policy.Conditions.Users.IncludeUsers + "All" in Policy.Conditions.Applications.IncludeApplications + count(Policy.Conditions.Applications.ExcludeApplications) == 0 + HasPhishingResistantMFA(Policy) + Policy.State == "enabled" + count(Policy.Conditions.Users.ExcludeRoles) == 0 +} + +PhishingResistantMFA[Cap.DisplayName] { + Cap := input.conditional_access_policies[_] + + # Match all simple conditions + PhishingResistantMFAConditionsMatch(Cap) + + # Only match policies with user and group exclusions if all exempted + UserExclusionsFullyExempt(Cap, "MS.AAD.3.1v1") == true + GroupExclusionsFullyExempt(Cap, "MS.AAD.3.1v1") == true +} + tests[{ - "PolicyId" : PolicyId, - "Criticality" : "Shall/Not-Implemented", - "Commandlet" : [], + "PolicyId" : "MS.AAD.3.1v1", + "Criticality" : "Shall", + "Commandlet" : ["Get-MgIdentityConditionalAccessPolicy"], "ActualValue" : [], - "ReportDetails" : NotCheckedDetails(PolicyId), - "RequirementMet" : false + "ReportDetails" : concat(". ", [ReportFullDetailsArray(PhishingResistantMFA, DescriptionString), CapLink]), + "RequirementMet" : Status }] { - PolicyId := "MS.AAD.3.1v1" - true + DescriptionString := "conditional access policy(s) found that meet(s) all requirements" + Status := count(PhishingResistantMFA) > 0 } #-- diff --git a/Testing/Unit/Rego/AAD/AADConfig_03_test.rego b/Testing/Unit/Rego/AAD/AADConfig_03_test.rego index add2a1986b..f9b6833985 100644 --- a/Testing/Unit/Rego/AAD/AADConfig_03_test.rego +++ b/Testing/Unit/Rego/AAD/AADConfig_03_test.rego @@ -6,16 +6,194 @@ import data.report.utils.NotCheckedDetails # # MS.AAD.3.1v1 #-- -test_NotImplemented_Correct_V1 if { +test_PhishingResistantAllMFA_Correct if { PolicyId := "MS.AAD.3.1v1" - Output := tests with input as { } + Output := 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" : "Test name" + } + ] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "1 conditional access policy(s) found that meet(s) all requirements:
Test name. View all CA policies." +} + +test_PhishingResistantSingleMFA_Correct if { + PolicyId := "MS.AAD.3.1v1" + + Output := tests with input as { + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"], + "ExcludeApplications" : [] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : [], + "ExcludeGroups" : [], + "ExcludeRoles" : [] + } + }, + "GrantControls" : { + "AuthenticationStrength" : { + "AllowedCombinations": [ + "x509CertificateMultiFactor" + ] + } + }, + "State" : "enabled", + "DisplayName" : "Test name" + } + ] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "1 conditional access policy(s) found that meet(s) all requirements:
Test name. View all CA policies." +} + +test_PhishingResistantMFAExcludeApp_Incorrect if { + PolicyId := "MS.AAD.3.1v1" + + Output := tests with input as { + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"], + "ExcludeApplications" : ["Some App"] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : [], + "ExcludeGroups" : [], + "ExcludeRoles" : [] + } + }, + "GrantControls" : { + "AuthenticationStrength" : { + "DisplayName": "Phishing-resistant MFA" + } + }, + "State" : "enabled", + "DisplayName" : "Test name" + } + ] + } RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == NotCheckedDetails(PolicyId) + RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." +} + +test_PhishingResistantMFAExcludeUser_Incorrect if { + PolicyId := "MS.AAD.3.1v1" + + Output := tests with input as { + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"], + "ExcludeApplications" : [] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : ["me"], + "ExcludeGroups" : [], + "ExcludeRoles" : [] + } + }, + "GrantControls" : { + "AuthenticationStrength" : { + "AllowedCombinations": [ + "windowsHelloForBusiness", + "fido2", + "x509CertificateMultiFactor" + ] + } + }, + "State" : "enabled", + "DisplayName" : "Test name" + } + ] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." +} + +test_PhishingResistantMFAExcludeGroup_Incorrect if { + PolicyId := "MS.AAD.3.1v1" + + Output := tests with input as { + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"], + "ExcludeApplications" : [] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : [], + "ExcludeGroups" : ["some"], + "ExcludeRoles" : [] + } + }, + "GrantControls" : { + "AuthenticationStrength" : { + "DisplayName": "Phishing-resistant MFA" + } + }, + "State" : "enabled", + "DisplayName" : "Test name" + } + ] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." } #-- From 27e39583535b87afb31cf8f135fa894f2b8deed8 Mon Sep 17 00:00:00 2001 From: Addam Schroll <108814318+schrolla@users.noreply.github.com> Date: Tue, 11 Jul 2023 11:42:41 -0500 Subject: [PATCH 15/33] Updated ReportDetails on tests to match patch results (#426) --- Testing/Unit/Rego/Teams/TeamsConfig_07_test.rego | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Testing/Unit/Rego/Teams/TeamsConfig_07_test.rego b/Testing/Unit/Rego/Teams/TeamsConfig_07_test.rego index b75c8fbba1..fe6ea07eea 100644 --- a/Testing/Unit/Rego/Teams/TeamsConfig_07_test.rego +++ b/Testing/Unit/Rego/Teams/TeamsConfig_07_test.rego @@ -90,7 +90,7 @@ test_AllowEmailIntoChannel_Incorrect if { count(RuleOutput) == 1 not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "1 Requirement not met: Email integration is enabled across domain: Global" + RuleOutput[0].ReportDetails == "Requirement not met" } test_AllowEmailIntoChannel_Incorrect_multi if { @@ -122,7 +122,7 @@ test_AllowEmailIntoChannel_Incorrect_multi if { count(RuleOutput) == 1 not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "2 Requirement not met: Email integration is enabled across domain: Global, Tag:AllOn" + RuleOutput[0].ReportDetails == "Requirement not met" } test_AllowEmailIntoChannel_Correct_V2 if { From 3a029ae973f78c5ae1e62cee36ddbd914d60a2b4 Mon Sep 17 00:00:00 2001 From: David Bui <105074908+buidav@users.noreply.github.com> Date: Tue, 11 Jul 2023 12:19:23 -0700 Subject: [PATCH 16/33] Address Power Platform pilot comments and substantive changes in the baseline document Part 2 (#424) * power platform baseline doc refactor * address Grant's comments * forgot to update this header * consistent Policies header --- baselines/powerplatform.md | 310 ++++++++++++++++++++----------------- 1 file changed, 169 insertions(+), 141 deletions(-) diff --git a/baselines/powerplatform.md b/baselines/powerplatform.md index d677034ed1..085f5007da 100644 --- a/baselines/powerplatform.md +++ b/baselines/powerplatform.md @@ -1,58 +1,42 @@ -# Introduction +# CISA M365 Security Configuration Baseline for Power Platform -The Microsoft Power Platform is a group of applications involving -low-code application development, business intelligence, a custom chat -bot creator, and app connectivity software. The following summarizes the -Power Platform applications and other applications frequently used by -Power Platform applications. +Microsoft Power Platform is a group of applications comprised of a +low-code application development toolkit, business intelligence software, +a custom chat bot creator, and app connectivity software. The following sections summarizes +the various Power Platform applications. -**Power Apps**: This is a low-code application development software used -to create custom business applications. The apps can be used as desktop, -mobile, and web apps. Three different types of Power Apps can be +**Power Apps**: Low-code application development software used +to create custom business applications. The apps can be developed as desktop, +mobile, and even web apps. Three different types of Power Apps can be created: -1. **Canvas Apps**: These are drag and drop style developed apps, where +1. [**Canvas Apps**](https://learn.microsoft.com/en-us/power-apps/maker/canvas-apps/): These are drag and + drop style developed apps, where users drag and add User Interface (UI) components to the screen. Users can then connect the components to data sources to display data in the canvas app. -2. **Model-Driven Apps**: These apps are developed from an existing +2. [**Model-Driven Apps**](https://learn.microsoft.com/en-us/power-apps/maker/model-driven-apps/): These are apps developed from an existing data source. They can be thought of as the inverse of a Canvas App. - For those familiar with the Model-View-Controller design pattern, - Model-Driven apps revolve around building the view and controller on - top of the model. + Since, you build the app from the source rather than building the UI and then connecting to the source like + Canvas apps. -3. **Portals**: These apps are created to be websites. +3. [**Power Pages**](https://learn.microsoft.com/en-us/power-pages/): These apps that are developed to function as either internal or external facing websites. -**Power Automate**: This is an online tool within the Microsoft 365 -applications and add-ins used to create automated workflows between apps -and services to synchronize files, get notifications and collect data. +[**Power Automate**](https://learn.microsoft.com/en-us/power-automate/): This is an online tool within Microsoft 365 and add-ins used to create automated workflows between apps +and services to synchronize files, get notifications, and collect data. -**Power Virtual Agents**: These are custom chat bots for use in the -stand-alone Power Virtual Agents web app or in a Microsoft Teams +[**Power Virtual Agents**](https://learn.microsoft.com/en-us/power-virtual-agents/): These are custom chat bots for use in the stand-alone Power Virtual Agents web app or in a Microsoft Teams channel. -**Connectors**: These are a proxy or a wrapper around an API that allows -the underlying service to be accessed from Power Automate workflows, a -Power App or Azure Logic Apps. +[**Connectors**](https://learn.microsoft.com/en-us/connectors/connector-reference/): These are proxies or wrappers around an API that allow the underlying service to be accessed from Power Automate Workflows, Power Apps, or Azure Logic Apps. -**Microsoft Dataverse**: This is a cloud database management system most +[**Microsoft Dataverse**](https://learn.microsoft.com/en-us/power-apps/maker/data-platform/): This is a cloud database management system most often used to store data in SQL-like tables. A Power App would then use a connector to connect to the Dataverse table and perform create, read, -update and delete (CRUD) operations. +update, and delete (CRUD) operations. -## Assumptions - -The **License Requirements** sections of this document assume the -organization is using an [M365 -E3](https://www.microsoft.com/en-us/microsoft-365/compare-microsoft-365-enterprise-plans) -or [G3](https://www.microsoft.com/en-us/microsoft-365/government) -license level. Therefore, only licenses not included in E3/G3 are -listed. - -## Resources - -**License Compliance and Copyright** +## License Compliance and Copyright Portions of this document are adapted from documents in Microsoft’s [Microsoft @@ -66,40 +50,57 @@ document. The United States Government has adapted selections of these documents to develop innovative and scalable configuration standards to strengthen the security of widely used cloud-based software services. -# Baseline +## Assumptions + +The **License Requirements** sections of this document assume the +organization is using an [M365 +E3](https://www.microsoft.com/en-us/microsoft-365/compare-microsoft-365-enterprise-plans) +or [G3](https://www.microsoft.com/en-us/microsoft-365/government) +license level. Therefore, only licenses not included in E3/G3 are +listed. + +# Baseline Policies -Baselines in this section are for administrative controls that apply to -all Power Platform applications at the Power Platform tenant and -environment level. Additional Power Platform security settings would be +Baseline Policies in this document are targeted towards administrative controls that apply to +Power Platform applications at either the tenant or Power Platform +environment level. Additional Power Platform security settings can be implemented at the app level, connector level, or Dataverse table level. -Refer to Microsoft documentation for those additional controls. +Refer to [Power Platform Microsoft Learn documentation](https://learn.microsoft.com/en-us/power-platform/) for those additional controls. -## 1. Power Platform Environments +## 1. Creation of Power Platform Environments Power Platform environments are used to group together, manage, and -store Power Apps and Power Virtual Agents. By default, any user in the +store Power Apps or Power Virtual Agents. By default, any user in the Azure AD Tenant can create additional environments. Enabling this control will restrict the creation of new environments to users with the following admin roles: Global admins, Dynamics 365 admins, and Power Platform admins. ### Policies + #### MS.POWERPLATFORM.1.1v1 -The ability to create additional environments SHALL be restricted to admins. -- _Rationale:_ TODO -- _Last modified:_ June 2023 +The ability to create production and sandbox environments SHALL be restricted to admins. +- _Rationale:_ Users creating additional Power Platform environments may inadvertently bypass DLP policy settings or misconfigure the security settings of their environment. +- _Last Modified:_ June 2023 +- Note: This control restricts the creation of environments to users with Global admin, Dynamics 365 service admin, Power Platform Service admins, or Delegated admin roles. + +#### MS.POWERPLATFORM.1.2v1 +The ability to create trial environments SHALL be restricted to admins. +- _Rationale:_ Users creating additional Power Platform environments may inadvertently bypass DLP policy settings or misconfigure the security settings of their environment. +- _Last Modified:_ June 2023 +- Note: This control restricts the creation of environments to users with Global admin, Dynamics 365 service admin, Power Platform Service admins, or Delegated admin roles. ### Resources - [Control who can create and manage environments in the Power Platform admin center \| Microsoft - Documents](https://docs.microsoft.com/en-us/power-platform/admin/control-environment-creation) + Learn](https://learn.microsoft.com/en-us/power-platform/admin/control-environment-creation) - [Environment Administrator \| Digital Transformation Agency of Australia](https://desktop.gov.au/blueprint/office-365.html#power-platform) -- [Microsoft Technical Documentation \| Power - Apps](https://docs.microsoft.com/en-us/power-apps/) +- [Microsoft Power Apps Documentation \| Power + Apps](https://learn.microsoft.com/en-us/power-apps/) ### License Requirements @@ -107,10 +108,9 @@ The ability to create additional environments SHALL be restricted to admins. ### Implementation -1. Sign in to the [Power Platform admin - center](https://admin.powerplatform.microsoft.com/) or for GCC - environments sign in to the [GCC Power Platform Admin - Center](https://gcc.admin.powerplatform.microsoft.us/). +#### MS.POWERPLATFORM.1.1v1 instructions: +1. Sign in to your tenant environment's respective [Power Platform admin + center](https://learn.microsoft.com/en-us/power-platform/admin/powerapps-us-government#power-apps-us-government-service-urls). 2. In the upper-right corner of the Microsoft Power Platform site, select the **Gear icon** (Settings icon). @@ -120,15 +120,14 @@ The ability to create additional environments SHALL be restricted to admins. 4. Under **Who can create production and sandbox environments**, select **Only specific admins.** -5. Under **Who can create trial environments**, select **Only specific - admins.** +#### MS.POWERPLATFORM.1.2v1 instructions: +1. Follow the instructions in the previous policy up to step **3**. -Now only Global admins, Dynamics 365 service admins, Power Platform -Service admins, and Delegated admins can create environments. +2. Under **Who can create trial environments**, select **Only specific admins.** -## 2. Data Loss Prevention Policies +## 2. Power Platform Data Loss Prevention Policies -To secure Power Platform environments Data Loss Prevention (DLP) +To secure Power Platform environments, Data Loss Prevention (DLP) policies can be created to restrict the connectors that can be used with Power Apps created in an environment. A DLP policy can be created to affect all or some environments or exclude certain environments. The @@ -142,10 +141,10 @@ cannot be blocked (e.g., Teams and SharePoint connectors). In the DLP policy, connectors can also be configured to restrict read and write permissions to the data source/service. Connectors that cannot -be blocked, also cannot be configured. Agencies should evaluate the +be blocked also cannot be configured. Agencies should evaluate the connectors and configure them to fit with agency needs and security requirements. The agency should then create a DLP policy to only allow -those connectors to be used in the Power Platform. +those connectors to be used in Power Platform. When the Azure AD tenant is created, by default, a Power Platform environment is created in Power Platform. This Power Platform @@ -155,18 +154,22 @@ default Power Platform environment. Admins can restrict users from creating apps in all other created environments. ### Policies + #### MS.POWERPLATFORM.2.1v1 -A DLP policy SHALL be created to restrict connector access in the default Power Platform environment. -- _Rationale:_ TODO -- _Last modified:_ June 2023 +A DLP policy SHALL be created to restrict connector access in the +default Power Platform environment. +- _Rationale:_ All users in the tenant have access to the default Power Platform environment. Those users may inadvertently use connectors that share sensitive information with others who should not have access to it. Users with a Power Apps need should be directed to conduct development in other Power Platform environments with DLP connector policies customized to suit the user's needs while maintaining the agency's security posture. +- _Last Modified:_ June 2023 #### MS.POWERPLATFORM.2.2v1 -Non-default environments SHOULD have at least one DLP policy that affects them. -- _Rationale:_ TODO -- _Last modified:_ June 2023 +Non-default environments SHOULD have at least one DLP policy that + affects them. +- _Rationale:_ Users may inadvertently use connectors that share sensitive information with others who should not have access to it. Data loss prevention (DLP) policies provide a way for agencies to detect and prevent unauthorized disclosures. +- _Last Modified:_ June 2023 #### MS.POWERPLATFORM.2.3v1 -All connectors except those listed below SHOULD be added to the Blocked category in the default environment policy: +All connectors except those listed below SHOULD be added to the +Blocked category in the default environment policy: - Approvals @@ -204,7 +207,7 @@ All connectors except those listed below SHOULD be added to the Blocked category - Yammer. -- _Rationale:_ TODO +- _Rationale:_ All users in the tenant have access to the default Power Platform environment. Blocking all connectors in the default environment prevents inadvertent or malicious use of connectors by users in the agency's tenant. - _Last modified:_ June 2023 ### Resources @@ -214,7 +217,7 @@ All connectors except those listed below SHOULD be added to the Blocked category Australia](https://desktop.gov.au/blueprint/office-365.html#power-apps-and-power-automate) - [Create a data loss prevention (DLP) policy \| Microsoft - Docs](https://docs.microsoft.com/en-us/power-platform/admin/create-dlp-policy) + Learn](https://learn.microsoft.com/en-us/power-platform/admin/create-dlp-policy) ### License Requirements @@ -222,19 +225,18 @@ All connectors except those listed below SHOULD be added to the Blocked category ### Implementation -1. Sign in to the [Power Platform admin - center](https://admin.powerplatform.microsoft.com/) (for GCC - environments sign in to the [GCC Power Platform Admin - Center](https://gcc.admin.powerplatform.microsoft.us/)). +#### MS.POWERPLATFORM.2.1v1 instructions: +1. Sign in to your tenant environment's respective [Power Platform admin + center](https://learn.microsoft.com/en-us/power-platform/admin/powerapps-us-government#power-apps-us-government-service-urls). -2. On the left pane, select **Policies** then **Data Policies.** +2. On the left pane, select **Policies** \> **Data Policies.** 3. Select the **+ New Policy** icon to create a new policy. 4. Give the policy a suitable agency name and click **Next.** -5. At the **Prebuilt connectors** section, select the connectors that - fit the agency’s needs. +5. At the **Prebuilt connectors** section, select the connectors that +fit the agency’s needs. 6. Select a connector and click **Move to Business.** @@ -242,25 +244,33 @@ All connectors except those listed below SHOULD be added to the Blocked category connector** at the top of the screen to change connector permissions. -8. Refer to Table 1 for those connectors to move which **Business/Non-Business** Category. +8. Refer to Table 1 for those connectors to move which **Business/Non-Business** category. -9. For the default environment, move all connectors that cannot be +9. For the default environment, move all connectors that cannot be blocked to the **Blocked** category. -10. At the bottom of the screen, select **Next** to move on. +10. At the bottom of the screen, select **Next** to move on. -11. Add a customer connector pattern that fit the agency’s needs. Click +11. Add a customer connector pattern that fit the agency’s needs. Click **Next**. -12. Define the scope of the policy. For the default environment select -**Add multiple environments** and add the default environment. +12. Define the scope of the policy. To use this policy for all environments including +ones created in the future select **Add all environments**. + +13. Otherwise for the default environment, select **Add multiple environments** and add the default environment. -13. Select the environments over which to add the policy and click **Add - to policy** at the top. +14. Select the environments over which to add the policy and click **Add +to policy** at the top. -14. Select **Next**-\> **Create Policy** to finish. +15. Select **Next**-\> **Create Policy** to finish. -## 3. Tenant Isolation +#### MS.POWERPLATFORM.2.2v1 instructions: +1. Repeat the steps above but for step **13** select the non-default environment you wish to enforce a DLP policy upon. + +#### MS.POWERPLATFORM.2.3v1 instructions: +1. Refer to steps **8** and **9** in the **MS.POWERPLATFORM.2.1v1** instructions to meet this policy. + +## 3. Power Platform Tenant Isolation Power Platform tenant isolation is different from Azure AD-wide tenant restriction. It does not impact Azure AD-based access outside of Power @@ -284,23 +294,19 @@ source. #### MS.POWERPLATFORM.3.1v1 Power Platform tenant isolation SHALL be enabled. -- _Rationale:_ TODO +- _Rationale:_ Provides an additional tenant isolation control on top of AAD tenant isolation specifically for Power Platform applications to prevent accidental or malicious cross tenant information sharing. - _Last modified:_ June 2023 #### MS.POWERPLATFORM.3.2v1 An inbound/outbound connection allowlist SHOULD be configured. -- _Rationale:_ TODO -- _Last modified:_ June 2023 - -#### MS.POWERPLATFORM.3.3v1 -The allowlist MAY be empty. -- _Rationale:_ TODO +- _Rationale:_ Depending on agency needs an allowlist can be configured to allow cross tenant collaboration via connectors. - _Last modified:_ June 2023 +- Note: The allowlist may be empty if the agency has no need for cross tenant collaboration. ### Resources - [Enable tenant isolation and configure allowlist \| Microsoft - Docs](https://docs.microsoft.com/en-us/power-platform/admin/cross-tenant-restrictions#enable-tenant-isolation-and-configure-allowlist) + Learn](https://learn.microsoft.com/en-us/power-platform/admin/cross-tenant-restrictions#enable-tenant-isolation-and-configure-allowlist) ### License Requirements @@ -308,44 +314,45 @@ The allowlist MAY be empty. ### Implementation -1. Sign in to the [Power Platform admin - center](https://admin.powerplatform.microsoft.com/) or for GCC - environments sign in to the [GCC Power Platform Admin - Center](https://gcc.admin.powerplatform.microsoft.us/). +#### MS.POWERPLATFORM.3.1v1 instructions: +1. Sign in to your tenant environment's respective [Power Platform admin + center](https://learn.microsoft.com/en-us/power-platform/admin/powerapps-us-government#power-apps-us-government-service-urls). 2. On the left pane, select **Policies -\> Tenant Isolation**. -3. The tenant isolation allowlist can be configured by using **New - tenant rule** on the Tenant Isolation page. +3. Set the slider in the center of the screen to **On** then click **Save** + on the bottom of the screen. + +#### MS.POWERPLATFORM.3.2v1 instructions: +1. Follow steps **1-2** in **MS.POWERPLATFORM.3.1v1 instructions** to +arrive at the same page. + +2. The tenant isolation allowlist can be configured by clicking **New tenant rule** +on the Tenant Isolation page. + +3. Select the **Direction** of the rule and add the **Tenant Domain or ID** this rule applies to. -4. If Tenant Isolation is switched **Off**, add or edit the rules in - the allowlist. However, these rules won't be enforced until tenant - isolation is turned **On**. +4. If Tenant Isolation is switched **Off**, these rules won't be enforced until tenant +isolation is turned **On**. -## 4. Content Security Policy +## 4. Power Apps Content Security Policy -Content Security Policy (CSP) is an added layer of security that helps +Content Security Policy (CSP) is an added security layer that helps to detect and mitigate certain types of attacks, including Cross-Site -Scripting (XSS) and data injection attacks. These attacks are used for -everything from data theft to site defacement to malware distribution. -Currently, there is no UI for editing these attributes, but there is a -plan to expose this control in the Power Platform admin center. In the -meantime, use this -[script](https://docs.microsoft.com/en-us/power-platform/admin/content-security-policy) -to apply this setting. Also, there is no current way to implement this -setting for Canvas Apps. When enabled, this setting will apply to all -current Model-driven apps at only the environment level. +Scripting (XSS), clickjacking, and data injection attacks. When enabled, this setting can apply to all +current Canvas Apps and Model-driven apps at the Power Platform environment level. + +### Policies -### Policies #### MS.POWERPLATFORM.4.1v1 -Content security policies for model-driven Power Apps SHALL be enabled. -- _Rationale:_ TODO -- _Last modified:_ June 2023 +Content Security Policy SHALL be enforced for Model-driven and Canvas Power Apps. +- _Rationale:_ Adds CSP as a defense mechanism for Power Apps against common website attacks. +- _Last Modified:_ June 2023 ### Resources - [Content Security Policy \| Microsoft - Docs](https://docs.microsoft.com/en-us/power-platform/admin/content-security-policy) + Learn](https://learn.microsoft.com/en-us/power-platform/admin/content-security-policy) ### License Requirements @@ -353,33 +360,54 @@ Content security policies for model-driven Power Apps SHALL be enabled. ### Implementation -1. Sign in to [Make Power Apps](https://make.powerapps.com) (for GCC - environments sign in to the [GCC Make Power - Apps](https://make.gov.powerapps.us) center). +#### MS.POWERPLATFORM.4.1v1 instructions: +1. Sign in to your tenant environment's respective [Power Platform admin +center](https://learn.microsoft.com/en-us/power-platform/admin/powerapps-us-government#power-apps-us-government-service-urls). + +2. On the left-hand pane click on **Environments** and then select an environment from the list. + +3. Select the **Settings** icon that appears at the top of the page. + +4. Click on **Product** then click on **Privacy + Security** from the options that appear. -2. On the left-hand pane select **Apps** and select one of the - Model-Driven Apps (if there is no available Model-Driven app, create - one). +5. At the bottom of the page under the **Content security policy** section, turn the slider **On** for **Model-driven** and **Canvas**. -3. While in the model-driven app menu with an account with entity - update permissions, such as System Administrator or Power Platform - Administrator, open the browser dev tools. +6. Repeat steps 2 - 5 for all active Power Platform environments. -4. How to open the browser dev tools depends on which browser is used. - For a chromium-based browser, right click -\> **inspect** -\> - **console**). +7. At the same location set **Enable reporting** to **On** and add an appropriate endpoint that CSP violations can be reported to. + +## 5 Power Pages Creation + +Power Pages formerly known as Power Portals are Power Apps specifically designed to act as external facing websites. By default by any user in the tenant can create a Power Page. Admins are able to restrict the creation of new Power Pages to just admins. + +### Policies + +#### MS.POWERPLATFORM.5.1v1 +The ability to create Power Pages sites SHOULD be restricted to admins. +- _Rationale:_ Users may unintentionally misconfigure their Power Pages to expose sensitive information or leave the website in a vulnerable state. +- _Last Modified:_ June 2023 + +### Resources +- [Control Portal Creation \| Microsoft + Learn](https://learn.microsoft.com/en-us/power-apps/maker/portals/control-portal-creation) + +### License Requirements + +- N/A + +### Implementation -5. Paste the JavaScript code found -[here](https://docs.microsoft.com/en-us/power-platform/admin/content-security-policy) -into the console. +#### MS.POWERPLATFORM.5.1v1 instructions: +1. This setting currently can only be enabled through the [Power Apps PowerShell modules](https://learn.microsoft.com/en-us/power-platform/admin/powerapps-powershell#installation). -6. To simply enable CSP, pass the default configuration, i.e., call the - function like so - `enableFrameAncestors(["'self'"])`. +2. After installing the Power Apps PowerShell modules, run `Add-PowerAppsAccount -Endpoint $YourTenantsEndpoint`. To authenticate to your tenant's Power Platform. +Discover the valid endpoint parameter [here](https://learn.microsoft.com/en-us/powershell/module/microsoft.powerapps.administration.powershell/add-powerappsaccount?view=pa-ps-latest#-endpoint). Commercial tenants use `-Endpoint prod`, GCC tenants use `-Endpoint usgov` and so on. -7. As an example of enabling additional origins to embed the app - - `enableFrameAncestors(["*.powerapps.com", "'self'", "abcxyz"])`. +3. Then run the following PowerShell command to disable the creation of Power Pages sites by non-administrative users. +``` +Set-TenantSettings -RequestBody @{ "disablePortalsCreationByNonAdminUsers" = $true } +``` -8. To disable CSP call - `disableCSP()`. # Acknowledgements From 7f3822de3ed69564e72213681296fb93398efdd5 Mon Sep 17 00:00:00 2001 From: Richard Crutchfield Date: Thu, 13 Jul 2023 08:38:09 -0400 Subject: [PATCH 17/33] wip --- Rego/AADConfig.rego | 48 +++-- Rego/Utils/TestUtils.rego | 34 ++++ Testing/Unit/Rego/AAD/AADConfig_03_test.rego | 183 ++++++++++++++++++- 3 files changed, 243 insertions(+), 22 deletions(-) create mode 100644 Rego/Utils/TestUtils.rego diff --git a/Rego/AADConfig.rego b/Rego/AADConfig.rego index 083e9d68b9..593b98b4ee 100644 --- a/Rego/AADConfig.rego +++ b/Rego/AADConfig.rego @@ -3,6 +3,10 @@ import future.keywords import data.report.utils.NotCheckedDetails import data.report.utils.Format import data.report.utils.ReportDetailsBoolean +import data.test.utils.IsAllUsers +import data.test.utils.IsEmptyContainer +import data.test.utils.Contains +import data.test.utils.Count ############################################################################# # The report formatting functions below are generic and used throughout AAD # @@ -268,42 +272,46 @@ tests[{ # # MS.AAD.3.1v1 #-- -default PhishingResistantMFAConditionsMatch(_) := false -HasPhishingResistantMFA(Policy) := true if { - Strengths := { Strength | Strength := Policy.GrantControls.AuthenticationStrength.AllowedCombinations[_]} - AcceptableMFA := {"windowsHelloForBusiness", "fido2", "x509CertificateMultiFactor"} - count(AcceptableMFA) == count(Strengths | AcceptableMFA) -} - -PhishingResistantMFAConditionsMatch(Policy) := true if { - "All" in Policy.Conditions.Users.IncludeUsers - "All" in Policy.Conditions.Applications.IncludeApplications - count(Policy.Conditions.Applications.ExcludeApplications) == 0 - HasPhishingResistantMFA(Policy) - Policy.State == "enabled" - count(Policy.Conditions.Users.ExcludeRoles) == 0 -} PhishingResistantMFA[Cap.DisplayName] { Cap := input.conditional_access_policies[_] - # Match all simple conditions - PhishingResistantMFAConditionsMatch(Cap) + IsEmptyContainer(Cap.Conditions.Applications.ExcludeApplications) + print("app exclusion") - # Only match policies with user and group exclusions if all exempted - UserExclusionsFullyExempt(Cap, "MS.AAD.3.1v1") == true + Cap.State == "enabled" + print("policy enabled") + + Strengths := { Strength | Strength := Cap.GrantControls.AuthenticationStrength.AllowedCombinations[_]} + print("Strengths: ", Strengths) + print("Strengths count: ", count(Strengths)) + AcceptableMFA := {"windowsHelloForBusiness", "fido2", "x509CertificateMultiFactor"} + print("Acceptable count: ", count(AcceptableMFA)) + count(Strengths) > 0 + print("Strengths count: ", count(Strengths)) + MinusSet := Strengths - AcceptableMFA + count(MinusSet) == 0 + print("Acceptable MFA strength") + + Contains(Cap.Conditions.Applications.IncludeApplications, "All") GroupExclusionsFullyExempt(Cap, "MS.AAD.3.1v1") == true + Contains(Cap.Conditions.Users.IncludeUsers, "All") + print("users: ", Contains(Cap.Conditions.Users.IncludeUsers, "All")) + UserExclusionsFullyExempt(Cap, "MS.AAD.3.1v1") == true + print("user exclusion") } tests[{ "PolicyId" : "MS.AAD.3.1v1", "Criticality" : "Shall", "Commandlet" : ["Get-MgIdentityConditionalAccessPolicy"], - "ActualValue" : [], + "ActualValue" : PhishingResistantMFA, "ReportDetails" : concat(". ", [ReportFullDetailsArray(PhishingResistantMFA, DescriptionString), CapLink]), "RequirementMet" : Status }] { DescriptionString := "conditional access policy(s) found that meet(s) all requirements" + print("Tests policy count: " , count(PhishingResistantMFA)) + print("Tests policy count: " , PhishingResistantMFA) Status := count(PhishingResistantMFA) > 0 } #-- diff --git a/Rego/Utils/TestUtils.rego b/Rego/Utils/TestUtils.rego new file mode 100644 index 0000000000..4fda5a23a5 --- /dev/null +++ b/Rego/Utils/TestUtils.rego @@ -0,0 +1,34 @@ +package test.utils +import future.keywords + +#IsEmpty(null, _) = true +#IsEmpty(a, b) if not a[b] +#IsEmpty(a, b) if a[b] == "" + +IsEmptyContainer(null) = true +IsEmptyContainer(container) := true if { + Temp := {Item | Item := container[_]} + count(Temp) == 0 +} + +IsAllUsers(null) = false +IsAllUsers(array) := true if { + not IsEmptyContainer(array) + array[_] == "All" +} else = false {true} + +Contains(null, _) = false +Contains(array, item) := true if { + not IsEmptyContainer(array) + array[_] == item +} else = false { + true +} + +Count(null) = 0 +Count(container) := Result if { + not IsEmptyContainer(container) + Result := count(container) +} else = 0 { + true +} diff --git a/Testing/Unit/Rego/AAD/AADConfig_03_test.rego b/Testing/Unit/Rego/AAD/AADConfig_03_test.rego index f9b6833985..6591e22159 100644 --- a/Testing/Unit/Rego/AAD/AADConfig_03_test.rego +++ b/Testing/Unit/Rego/AAD/AADConfig_03_test.rego @@ -84,6 +84,177 @@ test_PhishingResistantSingleMFA_Correct if { RuleOutput[0].ReportDetails == "1 conditional access policy(s) found that meet(s) all requirements:
Test name. View all CA policies." } + +test_PhishingResistantNoneMFA_Incorrect if { + PolicyId := "MS.AAD.3.1v1" + + Output := tests with input as { +"conditional_access_policies": [ + { + "Conditions": { + "Applications": { + "ApplicationFilter": { + "Mode": null, + "Rule": null + }, + "ExcludeApplications": [ + + ], + "IncludeApplications": [ + "All" + ], + "IncludeAuthenticationContextClassReferences": [], + "IncludeUserActions": [] + }, + "ClientAppTypes": [ + "all" + ], + "ClientApplications": { + "ExcludeServicePrincipals": null, + "IncludeServicePrincipals": null, + "ServicePrincipalFilter": { + "Mode": null, + "Rule": null + } + }, + "DeviceStates": { + "ExcludeStates": null, + "IncludeStates": null + }, + "Devices": { + "DeviceFilter": { + "Mode": null, + "Rule": null + }, + "ExcludeDeviceStates": null, + "ExcludeDevices": null, + "IncludeDeviceStates": null, + "IncludeDevices": null + }, + "Locations": { + "ExcludeLocations": null, + "IncludeLocations": null + }, + "Platforms": { + "ExcludePlatforms": null, + "IncludePlatforms": null + }, + "ServicePrincipalRiskLevels": null, + "SignInRiskLevels": [ + + ], + "UserRiskLevels": [ + + ], + "Users": { + "ExcludeGroups": [ + + ], + "ExcludeGuestsOrExternalUsers": { + "ExternalTenants": { + "MembershipKind": null + }, + "GuestOrExternalUserTypes": null + }, + "ExcludeRoles": [ + + ], + "ExcludeUsers": [ + "66b4d5c2-71c9-4644-8728-74e3a8324d81" + ], + "IncludeGroups": [ + + ], + "IncludeGuestsOrExternalUsers": { + "ExternalTenants": { + "MembershipKind": null + }, + "GuestOrExternalUserTypes": null + }, + "IncludeRoles": [ + "62e90394-69f5-4237-9190-012177145e10", + "e8611ab8-c189-46e8-94e1-60213ab1f814", + "fe930be7-5e62-47db-91af-98c3a49a38b1", + "f28a1f50-f6e7-4571-818b-6a12f2af6b6c", + "29232cdf-9323-42fd-ade2-1d097af3e4de", + "8ac3fc64-6eca-42ea-9e69-59f4c7b60eb2", + "9b895d92-2cd3-44c7-9d02-a6ac2d5ea5c3", + "158c047a-c907-4556-b7ef-446551a6b5f7", + "b0f54661-2d74-4c50-afa3-1ec803f12efe" + ], + "IncludeUsers": [] + } + }, + "CreatedDateTime": "/Date(1668112094045)/", + "Description": null, + "DisplayName": "Live - MFA required for Highly Privileged Roles", + "GrantControls": { + "AuthenticationStrength": { + "AllowedCombinations": [], + "CombinationConfigurations": null, + "CreatedDateTime": null, + "Description": null, + "DisplayName": null, + "Id": null, + "ModifiedDateTime": null, + "PolicyType": null, + "RequirementsSatisfied": null + }, + "BuiltInControls": [ + "mfa" + ], + "CustomAuthenticationFactors": [ + + ], + "Operator": "OR", + "TermsOfUse": [ + + ] + }, + "Id": "9e174715-5697-4695-ac39-92f4af6ac2c4", + "ModifiedDateTime": "/Date(1668112265652)/", + "SessionControls": { + "ApplicationEnforcedRestrictions": { + "IsEnabled": null + }, + "CloudAppSecurity": { + "CloudAppSecurityType": null, + "IsEnabled": null + }, + "ContinuousAccessEvaluation": { + "Mode": null + }, + "DisableResilienceDefaults": null, + "PersistentBrowser": { + "IsEnabled": null, + "Mode": null + }, + "SecureSignInSession": { + "IsEnabled": null + }, + "SignInFrequency": { + "AuthenticationType": null, + "FrequencyInterval": null, + "IsEnabled": null, + "Type": null, + "Value": null + } + }, + "State": "enabled", + "AdditionalProperties": { + + } + } +] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + #RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." +} + test_PhishingResistantMFAExcludeApp_Incorrect if { PolicyId := "MS.AAD.3.1v1" @@ -104,7 +275,11 @@ test_PhishingResistantMFAExcludeApp_Incorrect if { }, "GrantControls" : { "AuthenticationStrength" : { - "DisplayName": "Phishing-resistant MFA" + "AllowedCombinations": [ + "windowsHelloForBusiness", + "fido2", + "x509CertificateMultiFactor" + ] } }, "State" : "enabled", @@ -180,7 +355,11 @@ test_PhishingResistantMFAExcludeGroup_Incorrect if { }, "GrantControls" : { "AuthenticationStrength" : { - "DisplayName": "Phishing-resistant MFA" + "AllowedCombinations": [ + "windowsHelloForBusiness", + "fido2", + "x509CertificateMultiFactor" + ] } }, "State" : "enabled", From fbdf89749bdbb17d43503d758962500cf5d64b31 Mon Sep 17 00:00:00 2001 From: Richard Crutchfield Date: Thu, 13 Jul 2023 09:38:27 -0400 Subject: [PATCH 18/33] Implemented AAD 3.1 --- Rego/AADConfig.rego | 36 +-- Testing/Unit/Rego/AAD/AADConfig_03_test.rego | 218 ++++++------------- 2 files changed, 73 insertions(+), 181 deletions(-) diff --git a/Rego/AADConfig.rego b/Rego/AADConfig.rego index 593b98b4ee..f6a3973d84 100644 --- a/Rego/AADConfig.rego +++ b/Rego/AADConfig.rego @@ -273,46 +273,34 @@ tests[{ # MS.AAD.3.1v1 #-- -PhishingResistantMFA[Cap.DisplayName] { +MS_AAD_3_1v1_CAP[Cap.DisplayName] { Cap := input.conditional_access_policies[_] - IsEmptyContainer(Cap.Conditions.Applications.ExcludeApplications) - print("app exclusion") - Cap.State == "enabled" - print("policy enabled") + Contains(Cap.Conditions.Users.IncludeUsers, "All") + IsEmptyContainer(Cap.Conditions.Applications.ExcludeApplications) + Contains(Cap.Conditions.Applications.IncludeApplications, "All") + GroupExclusionsFullyExempt(Cap, "MS.AAD.3.1v1") == true + UserExclusionsFullyExempt(Cap, "MS.AAD.3.1v1") == true + # Strength must be at least one of acceptable with no unacceptable strengths Strengths := { Strength | Strength := Cap.GrantControls.AuthenticationStrength.AllowedCombinations[_]} - print("Strengths: ", Strengths) - print("Strengths count: ", count(Strengths)) AcceptableMFA := {"windowsHelloForBusiness", "fido2", "x509CertificateMultiFactor"} - print("Acceptable count: ", count(AcceptableMFA)) - count(Strengths) > 0 - print("Strengths count: ", count(Strengths)) MinusSet := Strengths - AcceptableMFA - count(MinusSet) == 0 - print("Acceptable MFA strength") - - Contains(Cap.Conditions.Applications.IncludeApplications, "All") - GroupExclusionsFullyExempt(Cap, "MS.AAD.3.1v1") == true - Contains(Cap.Conditions.Users.IncludeUsers, "All") - print("users: ", Contains(Cap.Conditions.Users.IncludeUsers, "All")) - UserExclusionsFullyExempt(Cap, "MS.AAD.3.1v1") == true - print("user exclusion") + Count(MinusSet) == 0 + Count(Strengths) > 0 } tests[{ "PolicyId" : "MS.AAD.3.1v1", "Criticality" : "Shall", "Commandlet" : ["Get-MgIdentityConditionalAccessPolicy"], - "ActualValue" : PhishingResistantMFA, - "ReportDetails" : concat(". ", [ReportFullDetailsArray(PhishingResistantMFA, DescriptionString), CapLink]), + "ActualValue" : MS_AAD_3_1v1_CAP, + "ReportDetails" : concat(". ", [ReportFullDetailsArray(MS_AAD_3_1v1_CAP, DescriptionString), CapLink]), "RequirementMet" : Status }] { DescriptionString := "conditional access policy(s) found that meet(s) all requirements" - print("Tests policy count: " , count(PhishingResistantMFA)) - print("Tests policy count: " , PhishingResistantMFA) - Status := count(PhishingResistantMFA) > 0 + Status := count(MS_AAD_3_1v1_CAP) > 0 } #-- diff --git a/Testing/Unit/Rego/AAD/AADConfig_03_test.rego b/Testing/Unit/Rego/AAD/AADConfig_03_test.rego index 6591e22159..7d9e178e67 100644 --- a/Testing/Unit/Rego/AAD/AADConfig_03_test.rego +++ b/Testing/Unit/Rego/AAD/AADConfig_03_test.rego @@ -84,168 +84,72 @@ test_PhishingResistantSingleMFA_Correct if { RuleOutput[0].ReportDetails == "1 conditional access policy(s) found that meet(s) all requirements:
Test name. View all CA policies." } +test_PhishingResistantExtraMFA_Incorrect if { + PolicyId := "MS.AAD.3.1v1" + + Output := tests with input as { + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"], + "ExcludeApplications" : [] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : [], + "ExcludeGroups" : [], + "ExcludeRoles" : [] + } + }, + "GrantControls" : { + "AuthenticationStrength" : { + "AllowedCombinations": [ + "x509CertificateMultiFactor", + "SuperStrength" + ] + } + }, + "State" : "enabled", + "DisplayName" : "Test name" + } + ] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + #RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." +} test_PhishingResistantNoneMFA_Incorrect if { PolicyId := "MS.AAD.3.1v1" Output := tests with input as { -"conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "ApplicationFilter": { - "Mode": null, - "Rule": null - }, - "ExcludeApplications": [ - - ], - "IncludeApplications": [ - "All" - ], - "IncludeAuthenticationContextClassReferences": [], - "IncludeUserActions": [] - }, - "ClientAppTypes": [ - "all" - ], - "ClientApplications": { - "ExcludeServicePrincipals": null, - "IncludeServicePrincipals": null, - "ServicePrincipalFilter": { - "Mode": null, - "Rule": null - } - }, - "DeviceStates": { - "ExcludeStates": null, - "IncludeStates": null - }, - "Devices": { - "DeviceFilter": { - "Mode": null, - "Rule": null - }, - "ExcludeDeviceStates": null, - "ExcludeDevices": null, - "IncludeDeviceStates": null, - "IncludeDevices": null - }, - "Locations": { - "ExcludeLocations": null, - "IncludeLocations": null - }, - "Platforms": { - "ExcludePlatforms": null, - "IncludePlatforms": null - }, - "ServicePrincipalRiskLevels": null, - "SignInRiskLevels": [ - - ], - "UserRiskLevels": [ - - ], - "Users": { - "ExcludeGroups": [ - - ], - "ExcludeGuestsOrExternalUsers": { - "ExternalTenants": { - "MembershipKind": null - }, - "GuestOrExternalUserTypes": null - }, - "ExcludeRoles": [ - - ], - "ExcludeUsers": [ - "66b4d5c2-71c9-4644-8728-74e3a8324d81" - ], - "IncludeGroups": [ - - ], - "IncludeGuestsOrExternalUsers": { - "ExternalTenants": { - "MembershipKind": null - }, - "GuestOrExternalUserTypes": null - }, - "IncludeRoles": [ - "62e90394-69f5-4237-9190-012177145e10", - "e8611ab8-c189-46e8-94e1-60213ab1f814", - "fe930be7-5e62-47db-91af-98c3a49a38b1", - "f28a1f50-f6e7-4571-818b-6a12f2af6b6c", - "29232cdf-9323-42fd-ade2-1d097af3e4de", - "8ac3fc64-6eca-42ea-9e69-59f4c7b60eb2", - "9b895d92-2cd3-44c7-9d02-a6ac2d5ea5c3", - "158c047a-c907-4556-b7ef-446551a6b5f7", - "b0f54661-2d74-4c50-afa3-1ec803f12efe" - ], - "IncludeUsers": [] - } - }, - "CreatedDateTime": "/Date(1668112094045)/", - "Description": null, - "DisplayName": "Live - MFA required for Highly Privileged Roles", - "GrantControls": { - "AuthenticationStrength": { - "AllowedCombinations": [], - "CombinationConfigurations": null, - "CreatedDateTime": null, - "Description": null, - "DisplayName": null, - "Id": null, - "ModifiedDateTime": null, - "PolicyType": null, - "RequirementsSatisfied": null - }, - "BuiltInControls": [ - "mfa" - ], - "CustomAuthenticationFactors": [ - - ], - "Operator": "OR", - "TermsOfUse": [ - - ] - }, - "Id": "9e174715-5697-4695-ac39-92f4af6ac2c4", - "ModifiedDateTime": "/Date(1668112265652)/", - "SessionControls": { - "ApplicationEnforcedRestrictions": { - "IsEnabled": null - }, - "CloudAppSecurity": { - "CloudAppSecurityType": null, - "IsEnabled": null - }, - "ContinuousAccessEvaluation": { - "Mode": null - }, - "DisableResilienceDefaults": null, - "PersistentBrowser": { - "IsEnabled": null, - "Mode": null - }, - "SecureSignInSession": { - "IsEnabled": null - }, - "SignInFrequency": { - "AuthenticationType": null, - "FrequencyInterval": null, - "IsEnabled": null, - "Type": null, - "Value": null - } - }, - "State": "enabled", - "AdditionalProperties": { - - } - } -] + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"], + "ExcludeApplications" : [] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : [], + "ExcludeGroups" : [], + "ExcludeRoles" : [] + } + }, + "GrantControls" : { + "AuthenticationStrength" : { + "AllowedCombinations": null + } + }, + "State" : "enabled", + "DisplayName" : "Test name" + } + ] } RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] From f9b3398c9f32b7afa60859a100b577a5c2523125 Mon Sep 17 00:00:00 2001 From: Richard Crutchfield Date: Tue, 11 Jul 2023 11:44:59 -0400 Subject: [PATCH 19/33] WIP --- Rego/AADConfig.rego | 43 ++++- Testing/Unit/Rego/AAD/AADConfig_03_test.rego | 184 ++++++++++++++++++- 2 files changed, 215 insertions(+), 12 deletions(-) diff --git a/Rego/AADConfig.rego b/Rego/AADConfig.rego index afabf2391b..083e9d68b9 100644 --- a/Rego/AADConfig.rego +++ b/Rego/AADConfig.rego @@ -268,18 +268,43 @@ tests[{ # # MS.AAD.3.1v1 #-- -# At this time we are unable to fully test for MFA due to conflicting and multiple ways to configure authentication methods -# Awaiting API changes and feature updates from Microsoft for automated checking +default PhishingResistantMFAConditionsMatch(_) := false +HasPhishingResistantMFA(Policy) := true if { + Strengths := { Strength | Strength := Policy.GrantControls.AuthenticationStrength.AllowedCombinations[_]} + AcceptableMFA := {"windowsHelloForBusiness", "fido2", "x509CertificateMultiFactor"} + count(AcceptableMFA) == count(Strengths | AcceptableMFA) +} + +PhishingResistantMFAConditionsMatch(Policy) := true if { + "All" in Policy.Conditions.Users.IncludeUsers + "All" in Policy.Conditions.Applications.IncludeApplications + count(Policy.Conditions.Applications.ExcludeApplications) == 0 + HasPhishingResistantMFA(Policy) + Policy.State == "enabled" + count(Policy.Conditions.Users.ExcludeRoles) == 0 +} + +PhishingResistantMFA[Cap.DisplayName] { + Cap := input.conditional_access_policies[_] + + # Match all simple conditions + PhishingResistantMFAConditionsMatch(Cap) + + # Only match policies with user and group exclusions if all exempted + UserExclusionsFullyExempt(Cap, "MS.AAD.3.1v1") == true + GroupExclusionsFullyExempt(Cap, "MS.AAD.3.1v1") == true +} + tests[{ - "PolicyId" : PolicyId, - "Criticality" : "Shall/Not-Implemented", - "Commandlet" : [], + "PolicyId" : "MS.AAD.3.1v1", + "Criticality" : "Shall", + "Commandlet" : ["Get-MgIdentityConditionalAccessPolicy"], "ActualValue" : [], - "ReportDetails" : NotCheckedDetails(PolicyId), - "RequirementMet" : false + "ReportDetails" : concat(". ", [ReportFullDetailsArray(PhishingResistantMFA, DescriptionString), CapLink]), + "RequirementMet" : Status }] { - PolicyId := "MS.AAD.3.1v1" - true + DescriptionString := "conditional access policy(s) found that meet(s) all requirements" + Status := count(PhishingResistantMFA) > 0 } #-- diff --git a/Testing/Unit/Rego/AAD/AADConfig_03_test.rego b/Testing/Unit/Rego/AAD/AADConfig_03_test.rego index add2a1986b..f9b6833985 100644 --- a/Testing/Unit/Rego/AAD/AADConfig_03_test.rego +++ b/Testing/Unit/Rego/AAD/AADConfig_03_test.rego @@ -6,16 +6,194 @@ import data.report.utils.NotCheckedDetails # # MS.AAD.3.1v1 #-- -test_NotImplemented_Correct_V1 if { +test_PhishingResistantAllMFA_Correct if { PolicyId := "MS.AAD.3.1v1" - Output := tests with input as { } + Output := 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" : "Test name" + } + ] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "1 conditional access policy(s) found that meet(s) all requirements:
Test name. View all CA policies." +} + +test_PhishingResistantSingleMFA_Correct if { + PolicyId := "MS.AAD.3.1v1" + + Output := tests with input as { + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"], + "ExcludeApplications" : [] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : [], + "ExcludeGroups" : [], + "ExcludeRoles" : [] + } + }, + "GrantControls" : { + "AuthenticationStrength" : { + "AllowedCombinations": [ + "x509CertificateMultiFactor" + ] + } + }, + "State" : "enabled", + "DisplayName" : "Test name" + } + ] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "1 conditional access policy(s) found that meet(s) all requirements:
Test name. View all CA policies." +} + +test_PhishingResistantMFAExcludeApp_Incorrect if { + PolicyId := "MS.AAD.3.1v1" + + Output := tests with input as { + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"], + "ExcludeApplications" : ["Some App"] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : [], + "ExcludeGroups" : [], + "ExcludeRoles" : [] + } + }, + "GrantControls" : { + "AuthenticationStrength" : { + "DisplayName": "Phishing-resistant MFA" + } + }, + "State" : "enabled", + "DisplayName" : "Test name" + } + ] + } RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == NotCheckedDetails(PolicyId) + RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." +} + +test_PhishingResistantMFAExcludeUser_Incorrect if { + PolicyId := "MS.AAD.3.1v1" + + Output := tests with input as { + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"], + "ExcludeApplications" : [] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : ["me"], + "ExcludeGroups" : [], + "ExcludeRoles" : [] + } + }, + "GrantControls" : { + "AuthenticationStrength" : { + "AllowedCombinations": [ + "windowsHelloForBusiness", + "fido2", + "x509CertificateMultiFactor" + ] + } + }, + "State" : "enabled", + "DisplayName" : "Test name" + } + ] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." +} + +test_PhishingResistantMFAExcludeGroup_Incorrect if { + PolicyId := "MS.AAD.3.1v1" + + Output := tests with input as { + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"], + "ExcludeApplications" : [] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : [], + "ExcludeGroups" : ["some"], + "ExcludeRoles" : [] + } + }, + "GrantControls" : { + "AuthenticationStrength" : { + "DisplayName": "Phishing-resistant MFA" + } + }, + "State" : "enabled", + "DisplayName" : "Test name" + } + ] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." } #-- From 24decbb19f21241525b4a98c8ae2741aadfa3ae9 Mon Sep 17 00:00:00 2001 From: Richard Crutchfield Date: Thu, 13 Jul 2023 08:38:09 -0400 Subject: [PATCH 20/33] wip --- Rego/AADConfig.rego | 48 +++-- Rego/Utils/TestUtils.rego | 34 ++++ Testing/Unit/Rego/AAD/AADConfig_03_test.rego | 183 ++++++++++++++++++- 3 files changed, 243 insertions(+), 22 deletions(-) create mode 100644 Rego/Utils/TestUtils.rego diff --git a/Rego/AADConfig.rego b/Rego/AADConfig.rego index 083e9d68b9..593b98b4ee 100644 --- a/Rego/AADConfig.rego +++ b/Rego/AADConfig.rego @@ -3,6 +3,10 @@ import future.keywords import data.report.utils.NotCheckedDetails import data.report.utils.Format import data.report.utils.ReportDetailsBoolean +import data.test.utils.IsAllUsers +import data.test.utils.IsEmptyContainer +import data.test.utils.Contains +import data.test.utils.Count ############################################################################# # The report formatting functions below are generic and used throughout AAD # @@ -268,42 +272,46 @@ tests[{ # # MS.AAD.3.1v1 #-- -default PhishingResistantMFAConditionsMatch(_) := false -HasPhishingResistantMFA(Policy) := true if { - Strengths := { Strength | Strength := Policy.GrantControls.AuthenticationStrength.AllowedCombinations[_]} - AcceptableMFA := {"windowsHelloForBusiness", "fido2", "x509CertificateMultiFactor"} - count(AcceptableMFA) == count(Strengths | AcceptableMFA) -} - -PhishingResistantMFAConditionsMatch(Policy) := true if { - "All" in Policy.Conditions.Users.IncludeUsers - "All" in Policy.Conditions.Applications.IncludeApplications - count(Policy.Conditions.Applications.ExcludeApplications) == 0 - HasPhishingResistantMFA(Policy) - Policy.State == "enabled" - count(Policy.Conditions.Users.ExcludeRoles) == 0 -} PhishingResistantMFA[Cap.DisplayName] { Cap := input.conditional_access_policies[_] - # Match all simple conditions - PhishingResistantMFAConditionsMatch(Cap) + IsEmptyContainer(Cap.Conditions.Applications.ExcludeApplications) + print("app exclusion") - # Only match policies with user and group exclusions if all exempted - UserExclusionsFullyExempt(Cap, "MS.AAD.3.1v1") == true + Cap.State == "enabled" + print("policy enabled") + + Strengths := { Strength | Strength := Cap.GrantControls.AuthenticationStrength.AllowedCombinations[_]} + print("Strengths: ", Strengths) + print("Strengths count: ", count(Strengths)) + AcceptableMFA := {"windowsHelloForBusiness", "fido2", "x509CertificateMultiFactor"} + print("Acceptable count: ", count(AcceptableMFA)) + count(Strengths) > 0 + print("Strengths count: ", count(Strengths)) + MinusSet := Strengths - AcceptableMFA + count(MinusSet) == 0 + print("Acceptable MFA strength") + + Contains(Cap.Conditions.Applications.IncludeApplications, "All") GroupExclusionsFullyExempt(Cap, "MS.AAD.3.1v1") == true + Contains(Cap.Conditions.Users.IncludeUsers, "All") + print("users: ", Contains(Cap.Conditions.Users.IncludeUsers, "All")) + UserExclusionsFullyExempt(Cap, "MS.AAD.3.1v1") == true + print("user exclusion") } tests[{ "PolicyId" : "MS.AAD.3.1v1", "Criticality" : "Shall", "Commandlet" : ["Get-MgIdentityConditionalAccessPolicy"], - "ActualValue" : [], + "ActualValue" : PhishingResistantMFA, "ReportDetails" : concat(". ", [ReportFullDetailsArray(PhishingResistantMFA, DescriptionString), CapLink]), "RequirementMet" : Status }] { DescriptionString := "conditional access policy(s) found that meet(s) all requirements" + print("Tests policy count: " , count(PhishingResistantMFA)) + print("Tests policy count: " , PhishingResistantMFA) Status := count(PhishingResistantMFA) > 0 } #-- diff --git a/Rego/Utils/TestUtils.rego b/Rego/Utils/TestUtils.rego new file mode 100644 index 0000000000..4fda5a23a5 --- /dev/null +++ b/Rego/Utils/TestUtils.rego @@ -0,0 +1,34 @@ +package test.utils +import future.keywords + +#IsEmpty(null, _) = true +#IsEmpty(a, b) if not a[b] +#IsEmpty(a, b) if a[b] == "" + +IsEmptyContainer(null) = true +IsEmptyContainer(container) := true if { + Temp := {Item | Item := container[_]} + count(Temp) == 0 +} + +IsAllUsers(null) = false +IsAllUsers(array) := true if { + not IsEmptyContainer(array) + array[_] == "All" +} else = false {true} + +Contains(null, _) = false +Contains(array, item) := true if { + not IsEmptyContainer(array) + array[_] == item +} else = false { + true +} + +Count(null) = 0 +Count(container) := Result if { + not IsEmptyContainer(container) + Result := count(container) +} else = 0 { + true +} diff --git a/Testing/Unit/Rego/AAD/AADConfig_03_test.rego b/Testing/Unit/Rego/AAD/AADConfig_03_test.rego index f9b6833985..6591e22159 100644 --- a/Testing/Unit/Rego/AAD/AADConfig_03_test.rego +++ b/Testing/Unit/Rego/AAD/AADConfig_03_test.rego @@ -84,6 +84,177 @@ test_PhishingResistantSingleMFA_Correct if { RuleOutput[0].ReportDetails == "1 conditional access policy(s) found that meet(s) all requirements:
Test name. View all CA policies." } + +test_PhishingResistantNoneMFA_Incorrect if { + PolicyId := "MS.AAD.3.1v1" + + Output := tests with input as { +"conditional_access_policies": [ + { + "Conditions": { + "Applications": { + "ApplicationFilter": { + "Mode": null, + "Rule": null + }, + "ExcludeApplications": [ + + ], + "IncludeApplications": [ + "All" + ], + "IncludeAuthenticationContextClassReferences": [], + "IncludeUserActions": [] + }, + "ClientAppTypes": [ + "all" + ], + "ClientApplications": { + "ExcludeServicePrincipals": null, + "IncludeServicePrincipals": null, + "ServicePrincipalFilter": { + "Mode": null, + "Rule": null + } + }, + "DeviceStates": { + "ExcludeStates": null, + "IncludeStates": null + }, + "Devices": { + "DeviceFilter": { + "Mode": null, + "Rule": null + }, + "ExcludeDeviceStates": null, + "ExcludeDevices": null, + "IncludeDeviceStates": null, + "IncludeDevices": null + }, + "Locations": { + "ExcludeLocations": null, + "IncludeLocations": null + }, + "Platforms": { + "ExcludePlatforms": null, + "IncludePlatforms": null + }, + "ServicePrincipalRiskLevels": null, + "SignInRiskLevels": [ + + ], + "UserRiskLevels": [ + + ], + "Users": { + "ExcludeGroups": [ + + ], + "ExcludeGuestsOrExternalUsers": { + "ExternalTenants": { + "MembershipKind": null + }, + "GuestOrExternalUserTypes": null + }, + "ExcludeRoles": [ + + ], + "ExcludeUsers": [ + "66b4d5c2-71c9-4644-8728-74e3a8324d81" + ], + "IncludeGroups": [ + + ], + "IncludeGuestsOrExternalUsers": { + "ExternalTenants": { + "MembershipKind": null + }, + "GuestOrExternalUserTypes": null + }, + "IncludeRoles": [ + "62e90394-69f5-4237-9190-012177145e10", + "e8611ab8-c189-46e8-94e1-60213ab1f814", + "fe930be7-5e62-47db-91af-98c3a49a38b1", + "f28a1f50-f6e7-4571-818b-6a12f2af6b6c", + "29232cdf-9323-42fd-ade2-1d097af3e4de", + "8ac3fc64-6eca-42ea-9e69-59f4c7b60eb2", + "9b895d92-2cd3-44c7-9d02-a6ac2d5ea5c3", + "158c047a-c907-4556-b7ef-446551a6b5f7", + "b0f54661-2d74-4c50-afa3-1ec803f12efe" + ], + "IncludeUsers": [] + } + }, + "CreatedDateTime": "/Date(1668112094045)/", + "Description": null, + "DisplayName": "Live - MFA required for Highly Privileged Roles", + "GrantControls": { + "AuthenticationStrength": { + "AllowedCombinations": [], + "CombinationConfigurations": null, + "CreatedDateTime": null, + "Description": null, + "DisplayName": null, + "Id": null, + "ModifiedDateTime": null, + "PolicyType": null, + "RequirementsSatisfied": null + }, + "BuiltInControls": [ + "mfa" + ], + "CustomAuthenticationFactors": [ + + ], + "Operator": "OR", + "TermsOfUse": [ + + ] + }, + "Id": "9e174715-5697-4695-ac39-92f4af6ac2c4", + "ModifiedDateTime": "/Date(1668112265652)/", + "SessionControls": { + "ApplicationEnforcedRestrictions": { + "IsEnabled": null + }, + "CloudAppSecurity": { + "CloudAppSecurityType": null, + "IsEnabled": null + }, + "ContinuousAccessEvaluation": { + "Mode": null + }, + "DisableResilienceDefaults": null, + "PersistentBrowser": { + "IsEnabled": null, + "Mode": null + }, + "SecureSignInSession": { + "IsEnabled": null + }, + "SignInFrequency": { + "AuthenticationType": null, + "FrequencyInterval": null, + "IsEnabled": null, + "Type": null, + "Value": null + } + }, + "State": "enabled", + "AdditionalProperties": { + + } + } +] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + #RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." +} + test_PhishingResistantMFAExcludeApp_Incorrect if { PolicyId := "MS.AAD.3.1v1" @@ -104,7 +275,11 @@ test_PhishingResistantMFAExcludeApp_Incorrect if { }, "GrantControls" : { "AuthenticationStrength" : { - "DisplayName": "Phishing-resistant MFA" + "AllowedCombinations": [ + "windowsHelloForBusiness", + "fido2", + "x509CertificateMultiFactor" + ] } }, "State" : "enabled", @@ -180,7 +355,11 @@ test_PhishingResistantMFAExcludeGroup_Incorrect if { }, "GrantControls" : { "AuthenticationStrength" : { - "DisplayName": "Phishing-resistant MFA" + "AllowedCombinations": [ + "windowsHelloForBusiness", + "fido2", + "x509CertificateMultiFactor" + ] } }, "State" : "enabled", From d7cbbf79acf5a130a4eb11c97717a59f679181fe Mon Sep 17 00:00:00 2001 From: Richard Crutchfield Date: Thu, 13 Jul 2023 09:38:27 -0400 Subject: [PATCH 21/33] Implemented AAD 3.1 --- Rego/AADConfig.rego | 36 +-- Testing/Unit/Rego/AAD/AADConfig_03_test.rego | 218 ++++++------------- 2 files changed, 73 insertions(+), 181 deletions(-) diff --git a/Rego/AADConfig.rego b/Rego/AADConfig.rego index 593b98b4ee..f6a3973d84 100644 --- a/Rego/AADConfig.rego +++ b/Rego/AADConfig.rego @@ -273,46 +273,34 @@ tests[{ # MS.AAD.3.1v1 #-- -PhishingResistantMFA[Cap.DisplayName] { +MS_AAD_3_1v1_CAP[Cap.DisplayName] { Cap := input.conditional_access_policies[_] - IsEmptyContainer(Cap.Conditions.Applications.ExcludeApplications) - print("app exclusion") - Cap.State == "enabled" - print("policy enabled") + Contains(Cap.Conditions.Users.IncludeUsers, "All") + IsEmptyContainer(Cap.Conditions.Applications.ExcludeApplications) + Contains(Cap.Conditions.Applications.IncludeApplications, "All") + GroupExclusionsFullyExempt(Cap, "MS.AAD.3.1v1") == true + UserExclusionsFullyExempt(Cap, "MS.AAD.3.1v1") == true + # Strength must be at least one of acceptable with no unacceptable strengths Strengths := { Strength | Strength := Cap.GrantControls.AuthenticationStrength.AllowedCombinations[_]} - print("Strengths: ", Strengths) - print("Strengths count: ", count(Strengths)) AcceptableMFA := {"windowsHelloForBusiness", "fido2", "x509CertificateMultiFactor"} - print("Acceptable count: ", count(AcceptableMFA)) - count(Strengths) > 0 - print("Strengths count: ", count(Strengths)) MinusSet := Strengths - AcceptableMFA - count(MinusSet) == 0 - print("Acceptable MFA strength") - - Contains(Cap.Conditions.Applications.IncludeApplications, "All") - GroupExclusionsFullyExempt(Cap, "MS.AAD.3.1v1") == true - Contains(Cap.Conditions.Users.IncludeUsers, "All") - print("users: ", Contains(Cap.Conditions.Users.IncludeUsers, "All")) - UserExclusionsFullyExempt(Cap, "MS.AAD.3.1v1") == true - print("user exclusion") + Count(MinusSet) == 0 + Count(Strengths) > 0 } tests[{ "PolicyId" : "MS.AAD.3.1v1", "Criticality" : "Shall", "Commandlet" : ["Get-MgIdentityConditionalAccessPolicy"], - "ActualValue" : PhishingResistantMFA, - "ReportDetails" : concat(". ", [ReportFullDetailsArray(PhishingResistantMFA, DescriptionString), CapLink]), + "ActualValue" : MS_AAD_3_1v1_CAP, + "ReportDetails" : concat(". ", [ReportFullDetailsArray(MS_AAD_3_1v1_CAP, DescriptionString), CapLink]), "RequirementMet" : Status }] { DescriptionString := "conditional access policy(s) found that meet(s) all requirements" - print("Tests policy count: " , count(PhishingResistantMFA)) - print("Tests policy count: " , PhishingResistantMFA) - Status := count(PhishingResistantMFA) > 0 + Status := count(MS_AAD_3_1v1_CAP) > 0 } #-- diff --git a/Testing/Unit/Rego/AAD/AADConfig_03_test.rego b/Testing/Unit/Rego/AAD/AADConfig_03_test.rego index 6591e22159..7d9e178e67 100644 --- a/Testing/Unit/Rego/AAD/AADConfig_03_test.rego +++ b/Testing/Unit/Rego/AAD/AADConfig_03_test.rego @@ -84,168 +84,72 @@ test_PhishingResistantSingleMFA_Correct if { RuleOutput[0].ReportDetails == "1 conditional access policy(s) found that meet(s) all requirements:
Test name. View all CA policies." } +test_PhishingResistantExtraMFA_Incorrect if { + PolicyId := "MS.AAD.3.1v1" + + Output := tests with input as { + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"], + "ExcludeApplications" : [] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : [], + "ExcludeGroups" : [], + "ExcludeRoles" : [] + } + }, + "GrantControls" : { + "AuthenticationStrength" : { + "AllowedCombinations": [ + "x509CertificateMultiFactor", + "SuperStrength" + ] + } + }, + "State" : "enabled", + "DisplayName" : "Test name" + } + ] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + #RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." +} test_PhishingResistantNoneMFA_Incorrect if { PolicyId := "MS.AAD.3.1v1" Output := tests with input as { -"conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "ApplicationFilter": { - "Mode": null, - "Rule": null - }, - "ExcludeApplications": [ - - ], - "IncludeApplications": [ - "All" - ], - "IncludeAuthenticationContextClassReferences": [], - "IncludeUserActions": [] - }, - "ClientAppTypes": [ - "all" - ], - "ClientApplications": { - "ExcludeServicePrincipals": null, - "IncludeServicePrincipals": null, - "ServicePrincipalFilter": { - "Mode": null, - "Rule": null - } - }, - "DeviceStates": { - "ExcludeStates": null, - "IncludeStates": null - }, - "Devices": { - "DeviceFilter": { - "Mode": null, - "Rule": null - }, - "ExcludeDeviceStates": null, - "ExcludeDevices": null, - "IncludeDeviceStates": null, - "IncludeDevices": null - }, - "Locations": { - "ExcludeLocations": null, - "IncludeLocations": null - }, - "Platforms": { - "ExcludePlatforms": null, - "IncludePlatforms": null - }, - "ServicePrincipalRiskLevels": null, - "SignInRiskLevels": [ - - ], - "UserRiskLevels": [ - - ], - "Users": { - "ExcludeGroups": [ - - ], - "ExcludeGuestsOrExternalUsers": { - "ExternalTenants": { - "MembershipKind": null - }, - "GuestOrExternalUserTypes": null - }, - "ExcludeRoles": [ - - ], - "ExcludeUsers": [ - "66b4d5c2-71c9-4644-8728-74e3a8324d81" - ], - "IncludeGroups": [ - - ], - "IncludeGuestsOrExternalUsers": { - "ExternalTenants": { - "MembershipKind": null - }, - "GuestOrExternalUserTypes": null - }, - "IncludeRoles": [ - "62e90394-69f5-4237-9190-012177145e10", - "e8611ab8-c189-46e8-94e1-60213ab1f814", - "fe930be7-5e62-47db-91af-98c3a49a38b1", - "f28a1f50-f6e7-4571-818b-6a12f2af6b6c", - "29232cdf-9323-42fd-ade2-1d097af3e4de", - "8ac3fc64-6eca-42ea-9e69-59f4c7b60eb2", - "9b895d92-2cd3-44c7-9d02-a6ac2d5ea5c3", - "158c047a-c907-4556-b7ef-446551a6b5f7", - "b0f54661-2d74-4c50-afa3-1ec803f12efe" - ], - "IncludeUsers": [] - } - }, - "CreatedDateTime": "/Date(1668112094045)/", - "Description": null, - "DisplayName": "Live - MFA required for Highly Privileged Roles", - "GrantControls": { - "AuthenticationStrength": { - "AllowedCombinations": [], - "CombinationConfigurations": null, - "CreatedDateTime": null, - "Description": null, - "DisplayName": null, - "Id": null, - "ModifiedDateTime": null, - "PolicyType": null, - "RequirementsSatisfied": null - }, - "BuiltInControls": [ - "mfa" - ], - "CustomAuthenticationFactors": [ - - ], - "Operator": "OR", - "TermsOfUse": [ - - ] - }, - "Id": "9e174715-5697-4695-ac39-92f4af6ac2c4", - "ModifiedDateTime": "/Date(1668112265652)/", - "SessionControls": { - "ApplicationEnforcedRestrictions": { - "IsEnabled": null - }, - "CloudAppSecurity": { - "CloudAppSecurityType": null, - "IsEnabled": null - }, - "ContinuousAccessEvaluation": { - "Mode": null - }, - "DisableResilienceDefaults": null, - "PersistentBrowser": { - "IsEnabled": null, - "Mode": null - }, - "SecureSignInSession": { - "IsEnabled": null - }, - "SignInFrequency": { - "AuthenticationType": null, - "FrequencyInterval": null, - "IsEnabled": null, - "Type": null, - "Value": null - } - }, - "State": "enabled", - "AdditionalProperties": { - - } - } -] + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"], + "ExcludeApplications" : [] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : [], + "ExcludeGroups" : [], + "ExcludeRoles" : [] + } + }, + "GrantControls" : { + "AuthenticationStrength" : { + "AllowedCombinations": null + } + }, + "State" : "enabled", + "DisplayName" : "Test name" + } + ] } RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] From f39411fb6e940724e823e6648f27efa0aee19c98 Mon Sep 17 00:00:00 2001 From: Richard Crutchfield Date: Thu, 13 Jul 2023 13:15:20 -0400 Subject: [PATCH 22/33] Update Rego/AADConfig.rego --- Rego/AADConfig.rego | 1 - 1 file changed, 1 deletion(-) diff --git a/Rego/AADConfig.rego b/Rego/AADConfig.rego index f6a3973d84..1ee68397c6 100644 --- a/Rego/AADConfig.rego +++ b/Rego/AADConfig.rego @@ -3,7 +3,6 @@ import future.keywords import data.report.utils.NotCheckedDetails import data.report.utils.Format import data.report.utils.ReportDetailsBoolean -import data.test.utils.IsAllUsers import data.test.utils.IsEmptyContainer import data.test.utils.Contains import data.test.utils.Count From e6d68cbbd6c57aad830c3324dfb2ca3445c96b68 Mon Sep 17 00:00:00 2001 From: Richard Crutchfield Date: Thu, 13 Jul 2023 15:44:15 -0400 Subject: [PATCH 23/33] Update Smoke Test to handle CAP (#418) * Fix CAP table check * Fix lint issue --- .../SmokeTest/SmokeTest001.Tests.ps1 | 4 +-- .../SmokeTest/SmokeTest002.Tests.ps1 | 26 +++++++++++++++++-- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/Testing/Functional/SmokeTest/SmokeTest001.Tests.ps1 b/Testing/Functional/SmokeTest/SmokeTest001.Tests.ps1 index 03eddc002f..e204db2c3a 100644 --- a/Testing/Functional/SmokeTest/SmokeTest001.Tests.ps1 +++ b/Testing/Functional/SmokeTest/SmokeTest001.Tests.ps1 @@ -51,11 +51,11 @@ Describe "Smoke Test: Generate Output" { Context "Invoke Scuba for $Organization" { BeforeAll { if ($PSCmdlet.ParameterSetName -eq 'Manual'){ - { Invoke-SCuBA -ProductNames "*" -M365Environment $M365Environment } | + { Invoke-SCuBA -ProductNames "*" -M365Environment $M365Environment -Quiet} | Should -Not -Throw } else { - { Invoke-SCuBA -CertificateThumbprint $Thumbprint -AppID $AppId -Organization $Organization -ProductNames "*" -M365Environment $M365Environment } | + { Invoke-SCuBA -CertificateThumbprint $Thumbprint -AppID $AppId -Organization $Organization -ProductNames "*" -M365Environment $M365Environment -Quiet} | Should -Not -Throw } $ReportFolders = Get-ChildItem . -directory -Filter "M365BaselineConformance*" | Sort-Object -Property LastWriteTime -Descending diff --git a/Testing/Functional/SmokeTest/SmokeTest002.Tests.ps1 b/Testing/Functional/SmokeTest/SmokeTest002.Tests.ps1 index 16b8bd42d0..79e47655f6 100644 --- a/Testing/Functional/SmokeTest/SmokeTest002.Tests.ps1 +++ b/Testing/Functional/SmokeTest/SmokeTest002.Tests.ps1 @@ -30,7 +30,7 @@ param ( Import-Module Selenium Describe -Tag "UI","Chrome" -Name "Test Report with for $OrganizationName" -ForEach @( - @{ Browser = "Chrome"; Driver = Start-SeChrome -Headless -Arguments @('start-maximized') 2>$null } + @{ Browser = "Chrome"; Driver = Start-SeChrome -Headless -Arguments @('start-maximized', 'AcceptInsecureCertificates') 2>$null } ){ BeforeAll { $ReportFolders = Get-ChildItem . -directory -Filter "M365BaselineConformance*" | Sort-Object -Property LastWriteTime -Descending @@ -105,12 +105,34 @@ Describe -Tag "UI","Chrome" -Name "Test Report with for $OrganizationN $Rows = Get-SeElement -Element $Table -By TagName 'tr' $Rows.Count | Should -BeGreaterThan 0 + # First Table in report is generally tenant data if ($Table.GetProperty("id") -eq "tenant-data"){ $Rows.Count | Should -BeExactly 2 $TenantDataColumns = Get-SeElement -Target $Rows[1] -By TagName "td" $Tenant = $TenantDataColumns[0].Text $Tenant | Should -Be $OrganizationName -Because "Tenant is $Tenant" - } else { + } + # AAD detailed report has a Conditional Access Policy table + elseif ($Table.GetAttribute("class") -eq "caps_table"){ + ForEach ($Row in $Rows){ + $RowHeaders = Get-SeElement -Element $Row -By TagName 'th' + $RowData = Get-SeElement -Element $Row -By TagName 'td' + + ($RowHeaders.Count -eq 0 ) -xor ($RowData.Count -eq 0) | Should -BeTrue -Because "Any given row should be homogenious" + + # NOTE: Checking for 8 columns since first is 'expand' column + if ($RowHeaders.Count -gt 0){ + $RowHeaders.Count | Should -BeExactly 8 + $RowHeaders[1].text | Should -BeLikeExactly "Name" + } + + if ($RowData.Count -gt 0){ + $RowData.Count | Should -BeExactly 8 + } + } + } + # Default is normal policy results table + else { # Control report tables ForEach ($Row in $Rows){ $RowHeaders = Get-SeElement -Element $Row -By TagName 'th' From f73e96c1288d40daea4500c07d9dfcf8af9cfff1 Mon Sep 17 00:00:00 2001 From: Alden Hilton <106177711+adhilto@users.noreply.github.com> Date: Thu, 13 Jul 2023 21:53:49 +0000 Subject: [PATCH 24/33] update MS.AAD.7.6v1 to only check for global admin (#428) --- Rego/AADConfig.rego | 6 +-- Testing/Unit/Rego/AAD/AADConfig_07_test.rego | 53 +++++++++++++++++++- 2 files changed, 54 insertions(+), 5 deletions(-) diff --git a/Rego/AADConfig.rego b/Rego/AADConfig.rego index afabf2391b..1ace61fe9a 100644 --- a/Rego/AADConfig.rego +++ b/Rego/AADConfig.rego @@ -790,11 +790,11 @@ tests[{ "Criticality" : "Should", "Commandlet" : ["Get-MgSubscribedSku", "Get-PrivilegedRole"], "ActualValue" : RolesWithoutApprovalRequired, - "ReportDetails" : ReportDetailsArrayLicenseWarning(RolesWithoutApprovalRequired, DescriptionString), + "ReportDetails" : ReportDetailsBooleanLicenseWarning(Status), "RequirementMet" : Status }] { - DescriptionString := "role(s) that do not require approval to activate found" - Conditions := [count(RolesWithoutApprovalRequired) == 0, check_if_role_rules_exist] + ApprovalNotRequired := "Global Administrator" in RolesWithoutApprovalRequired + Conditions := [ApprovalNotRequired == false, check_if_role_rules_exist] Status := count([Condition | Condition = Conditions[_]; Condition == false]) == 0 } #-- diff --git a/Testing/Unit/Rego/AAD/AADConfig_07_test.rego b/Testing/Unit/Rego/AAD/AADConfig_07_test.rego index 35d6c7d911..62d10a8fa3 100644 --- a/Testing/Unit/Rego/AAD/AADConfig_07_test.rego +++ b/Testing/Unit/Rego/AAD/AADConfig_07_test.rego @@ -418,7 +418,56 @@ test_AdditionalProperties_Correct_V2 if { count(RuleOutput) == 1 RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "0 role(s) that do not require approval to activate found" + RuleOutput[0].ReportDetails == "Requirement met" +} + +test_AdditionalProperties_Correct_V3 if { + PolicyId := "MS.AAD.7.6v1" + + Output := tests with input as { + "privileged_roles" : [ + { + "DisplayName" : "Global Administrator", + "Rules" : [ + { + "Id" : "Approval_EndUser_Assignment", + "AdditionalProperties" : { + "setting" : { + "isApprovalRequired" : true + } + } + } + ] + }, + { + "DisplayName" : "Groups Administrator", + "Rules" : [ + { + "Id" : "Approval_EndUser_Assignment", + "AdditionalProperties" : { + "setting" : { + "isApprovalRequired" : false # this shouldn't matter, only Global Admin matters for this control + } + } + } + ] + } + ], + "service_plans" : [ + { "ServicePlanName" : "EXCHANGE_S_FOUNDATION", + "ServicePlanId" : "31a0d5b2-13d0-494f-8e42-1e9c550a1b24" + }, + { "ServicePlanName" : "AAD_PREMIUM_P2", + "ServicePlanId" : "c7d91867-e1ce-4402-8d4f-22188b44b6c2" + } + ] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "Requirement met" } test_AdditionalProperties_Incorrect_V3 if { @@ -454,7 +503,7 @@ test_AdditionalProperties_Incorrect_V3 if { count(RuleOutput) == 1 not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == "1 role(s) that do not require approval to activate found:
Global Administrator" + RuleOutput[0].ReportDetails == "Requirement not met" } #-- From 34037da9e7789575146ae34fe24fecb155843450 Mon Sep 17 00:00:00 2001 From: Ted Kolovos <107076927+tkol2022@users.noreply.github.com> Date: Fri, 14 Jul 2023 10:10:02 -0400 Subject: [PATCH 25/33] Combine Sharepoint with OneDrive and address feedback from review period (#393) * draft update & merge of Sharepoint OneDrive * fixed policies wrong spelling * fixed note indent formatting * delete onedrive md file - have a combined file now * missing heading for some implementations * Added rationales for all policy items. * spelling errors and removed instructions comma * changed IDs to SHAREPOINT based on team vote * fixed duplicate ID in instructions --------- Co-authored-by: Addam Schroll --- baselines/onedrive.md | 264 --------------------- baselines/sharepoint.md | 409 -------------------------------- baselines/sharepointonedrive.md | 338 ++++++++++++++++++++++++++ 3 files changed, 338 insertions(+), 673 deletions(-) delete mode 100644 baselines/onedrive.md delete mode 100644 baselines/sharepoint.md create mode 100644 baselines/sharepointonedrive.md diff --git a/baselines/onedrive.md b/baselines/onedrive.md deleted file mode 100644 index 3840ce3fd0..0000000000 --- a/baselines/onedrive.md +++ /dev/null @@ -1,264 +0,0 @@ -# Introduction - -OneDrive for Business is a cloud-based file storage system with online -editing and collaboration tools for Microsoft Office documents and is -part of Office 365. OneDrive for Business facilitates synchronization -across multiple devices and enables secure, compliant, and intelligent -collaboration with multiple people. - -This security baseline applies guidance from industry benchmarks on how -to secure cloud solutions on Azure. - -## Assumptions - -These baseline specifications assume that the agency is using OneDrive -for Business, not personal or school versions, and allowing access using -both OneDrive application sync and the browser-based client. - -It is also assumed that the agency will use Azure Active Directory to -authenticate accounts and authorize applications. - -The **License Requirements** sections of this document assume the -organization is using an [M365 -E3](https://www.microsoft.com/en-us/microsoft-365/compare-microsoft-365-enterprise-plans) -or [G3](https://www.microsoft.com/en-us/microsoft-365/government) -license level. Therefore, only licenses not included in E3/G3 are -listed. - -## Resources - -**License Compliance and Copyright** - -Portions of this document are adapted from documents in Microsoft’s -[Microsoft -365](https://github.com/MicrosoftDocs/microsoft-365-docs/blob/public/LICENSE) -and -[Azure](https://github.com/MicrosoftDocs/azure-docs/blob/main/LICENSE) -GitHub repositories. The respective documents are subject to copyright -and are adapted under the terms of the Creative Commons Attribution 4.0 -International license. Source documents are linked throughout this -document. The United States Government has adapted selections of these -documents to develop innovative and scalable configuration standards to -strengthen the security of widely used cloud-based software services. - -# Baseline - -## 1. External Sharing - -Unauthenticated sharing (Anyone links) is used to share data without -authentication and users are free to pass it on to others outside the -agency. To prevent users from unauthenticated sharing of content, turn -off Anyone sharing for users outside the tenant when accessing content -in SharePoint, Groups, or Teams. - -### Policies - -#### MS.ONEDRIVE.1.1v1 -External sharing SHOULD be limited to Existing Guests or the more restrictive setting, Only People in your Organization. -- _Rationale:_ TODO -- _Last Modified:_ June 2023 -- _Note:_ Same Implementation in MS.SHAREPOINT.1.1V1 - -### Resources - -- [Limit accidental exposure \| Microsoft - Docs](https://learn.microsoft.com/en-us/microsoft-365/solutions/share-limit-accidental-exposure?view=o365-worldwide) - -### License Requirements - -- N/A - -### Implementation - -**Note**: OneDrive settings can be more restrictive than the SharePoint -setting, but not more permissive. - -To turn off Anyone links for the agency: - -1. Open the **SharePoint admin center**. - -2. In the left-hand navigation pane, expand **Policies,** then select - [**Sharing**](https://go.microsoft.com/fwlink/?linkid=2185222). - -3. Set the SharePoint external sharing settings to either **Existing guests** or **Only people in your organization**, then set OneDrive to either **Existing guests** or **Only people in your organization**. - -4. Click **Save**. - -To turn off Anyone links for a site: (**Default is set to organization-level settings**) - -1. In the **SharePoint admin center** left navigation pane, expand - **Sites,** and select [**Active - sites**](https://go.microsoft.com/fwlink/?linkid=2185220). - -2. Select the site to configure. - -3. In the ribbon, under **Settings**, select **More sharing settings**. - -4. Ensure that **External Sharing** is set to either **Existing guests** or **Only people in your organization**. - -5. Click **Save**. - -## 2. Expiration Date for Anyone Links - -Files that are stored in SharePoint sites, Groups, and Teams for months -and years could lead to unexpected modifications to files if shared with -unauthenticated people. Configuring expiration times for Anyone links -can help avoid unwanted changes. If Anyone links are enabled, the -expiration date of thirty days or less is necessary. - -### Policies - -#### MS.ONEDRIVE.2.1v1 -Expiration Date SHOULD Be Set for Anyone Links for 30 days or less. -- _Rationale:_ TODO -- _Last modified:_ June 2023 - -### Resources - -- [Best practices for unauthenticated sharing \| Microsoft - Docs](https://learn.microsoft.com/en-us/microsoft-365/solutions/best-practices-anonymous-sharing?view=o365-worldwide) - -### License Requirements - -- N/A - -### Implementation - -To set an expiration date for Anyone links across the agency (**Note**: -Only necessary when MS.ONEDRIVE.1.1v1 is not being implemented and OneDrive external sharing is set to Anyone). - -1. Open the **SharePoint admin center.** - -2. In the left-hand navigation pane, expand **Policies**, and then - select - [**Sharing**](https://go.microsoft.com/fwlink/?linkid=2185222). - -3. Under **Choose expiration and permissions options for Anyone links**, - select the **These links must expire within this many days** - check box. - -4. Enter the number of days in the box, and then click **Save**. - -## 3. File and Folder Links Default Sharing Settings - -The Anyone links default to allow people to edit files, as well as edit -and view files and upload new files to folders. To allow unauthenticated -sharing but keep unauthenticated people from modifying the agency's -content, consider setting the file and folder permissions to **View**. - -### Policies - -#### MS.ONEDRIVE.3.1v1 -Default Link Sharing Type SHOULD NOT Be Set to Anyone -- _Rationale:_ TODO -- _Last modified:_ June 2023 -_Note:_ Similar Implementation in MS.SHAREPOINT.2.1V1 - -#### MS.ONEDRIVE.3.2v1 -Anyone Link Permissions SHOULD Be Set to View Only -- _Rationale:_ TODO -- _Last modified:_ June 2023 - -### Resources - -- [Set link permissions \| Microsoft - Docs](https://learn.microsoft.com/en-us/microsoft-365/solutions/best-practices-anonymous-sharing?view=o365-worldwide#set-link-permissions) - -### License Requirements - -- N/A - -### Implementation - -To set the default file and folder sharing link for the organization: - -1. Open the **SharePoint admin center**. - -2. In the left-hand navigation pane, expand **Policies**, then select - **Sharing**. - -3. Under **File and folder links**, for **Choose the type of link that's selected by default when users share files and folders in SharePoint and OneDrive** - select **Only people in your organization** or **Specific people (only the people the user specifies)**. - -The set Link permission to View Only - -1. Open the **SharePoint admin center**. - -2. In the left-hand navigation pane, expand **Policies**, then select - **Sharing**. - -3. Under **File and folder links**, for **Choose the permission that's selected by default for sharing links** - select **View**. - -### Resources - -- [Set-SPOTenantSyncClientRestriction (SharePointOnlinePowerShell) \| - Microsoft - Docs](https://learn.microsoft.com/en-us/powershell/module/sharepoint-online/set-spotenantsyncclientrestriction?view=sharepoint-ps) - -### License Requirements - -- N/A - -### Implementation - -The `Set-SPOTenantSyncClientRestriction` cmdlet can be used to enable -the feature for tenancy and set the domain GUIDs in the safe recipients -list. When this feature is enabled, it can take up to 24 hours for the -change to take effect. However, any changes to the safe domains list are -reflected within five minutes. - -`Set-SPOTenantSyncClientRestriction -Enable -DomainGuids -"786548DD-877B-4760-A749-6B1EFBC1190A; -877564FF-877B-4760-A749-6B1EFBC1190A" -BlockMacSync:$false` - -# Acknowledgements - -In addition to acknowledging the important contributions of a diverse -team of Cybersecurity and Infrastructure Security Agency (CISA) experts, -CISA thanks the following federal agencies and private sector -organizations that provided input during the development of the Secure -Business Cloud Application’s security configuration baselines in -response to Section 3 of [Executive Order (EO) 14028, *Improving the -Nation’s -Cybersecurity*](https://www.federalregister.gov/documents/2021/05/17/2021-10460/improving-the-nations-cybersecurity): - -- Consumer Financial Protection Bureau (CFPB) - -- Department of the Interior (DOI) - -- National Aeronautics and Space Administration (NASA) - -- Sandia National Laboratories (Sandia) - -- U.S. Census Bureau (USCB) - -- U.S. Geological Survey (USGS) - -- U.S. Office of Personnel Management (OPM) - -- U.S. Small Business Administration (SBA) - -The cross-agency collaboration and partnerships developed during this -initiative serve as an example for solving complex problems faced by the -federal government. - -**Cybersecurity Innovation Tiger Team (CITT) Leadership** - -Beau Houser (USCB), Sanjay Gupta (SBA), Michael Witt (NASA), James -Saunders (OPM), Han Lin (Sandia), Andrew Havely (DOI). - -**CITT Authors** - -Trafenia Salzman (SBA), Benjamin McChesney (OPM), Robert Collier (USCB), -Matthew Snitchler (Sandia), Darryl Purdy (USCB), Brandon Frankens -(NASA), Brandon Goss (NASA), Nicole Bogeajis (DOI/USGS), Kevin Kelly -(DOI), Adnan Ehsan (CFPB), Michael Griffin (CFPB), Vincent Urias -(Sandia), Angela Calabaza (Sandia). - -**CITT Contributors** - -Dr. Mukesh Rohatgi (MITRE), Lee Szilagyi (MITRE), Nanda Katikaneni -(MITRE), Ted Kolovos (MITRE), Thomas Comeau (MITRE), Karen Caraway -(MITRE), Jackie Whieldon (MITRE), Jeanne Firey (MITRE), Kenneth Myers -(General Services Administration). diff --git a/baselines/sharepoint.md b/baselines/sharepoint.md deleted file mode 100644 index aebd9431ab..0000000000 --- a/baselines/sharepoint.md +++ /dev/null @@ -1,409 +0,0 @@ -# Introduction - -SharePoint Online is a web-based collaboration and document management -platform. Though highly flexible, it is primarily used to store -documents and communicate information across organizations. -Organizations can create sites, pages, document libraries, lists and -custom applications. - -In this baseline, the types of SharePoint Online users are defined as -follows (Note: these terms vary in use across Microsoft documentation -and within the context of different M365 workloads (e.g., Teams vs -SharePoint Online): - -1. **Internal users**: members of the agency’s M365 organization. - -2. **External users**: members of a different M365 organization. - -3. **Business to Business (B2B) guest users**: external users that are - formally invited to collaborate and added to the agency’s Azure - Active Directory (AAD) as guest users. These users authenticate with - their home organization/tenant and are granted access by virtue of - being listed as guest users on the tenant’s AAD. - -4. **Unmanaged users**: users that are not members of any M365 tenant - or organization (e.g., recipients of an “Anyone link.”) - - External sharing within SharePoint Online is defined as users within - an organization sharing content with people outside the organization - (external users, B2B guest users, or unmanaged users), or with - licensed users on multiple Microsoft 365 subscriptions if the agency - has more than one subscription. SharePoint has external sharing - settings at both the organizational level and the site level - (previously called the "site collection" level). To allow external - sharing on any site, it must be allowed at the organization level. - Then external sharing can be restricted for other sites. If a site's - external sharing option and the organization-level sharing option - don't match, the most restrictive value will always be applied. - - Source: - - -## Resources - -**License Compliance and Copyright** - -Portions of this document are adapted from documents in Microsoft’s -[Microsoft -365](https://github.com/MicrosoftDocs/microsoft-365-docs/blob/public/LICENSE) -and -[Azure](https://github.com/MicrosoftDocs/azure-docs/blob/main/LICENSE) -GitHub repositories. The respective documents are subject to copyright -and are adapted under the terms of the Creative Commons Attribution 4.0 -International license. Source documents are linked throughout this -document. The United States Government has adapted selections of these -documents to develop innovative and scalable configuration standards to -strengthen the security of widely used cloud-based software services. - -## Assumptions - -The **License Requirements** sections of this document assume the -organization is using an [M365 -E3](https://www.microsoft.com/en-us/microsoft-365/compare-microsoft-365-enterprise-plans) -or [G3](https://www.microsoft.com/en-us/microsoft-365/government) -license level. Therefore, only licenses not included in E3/G3 are -listed. - -# Baselines - -## 1. External Sharing - -SharePoint allows sharing with users who are outside the agency, which -is convenient but may pose a data loss or other information security -risk. This working group recommends allowlisting by domains and security -groups per interagency collaboration needs. - -**Note**: Adjusting this setting will adjust external sharing -for OneDrive and Teams to the same, selected level. OneDrive and Teams -can be less permissive (not more permissive) than SharePoint Online. - -Adding approved domains and security groups will also be reflected in -OneDrive external sharing settings. - -External access may be granted on a per-domain basis. This may be -desirable in some cases, e.g., for agency-to-agency collaboration (see -the CIO Council's [Interagency Collaboration -Program](https://community.max.gov/display/Egov/Interagency+Collaboration+Program)’s -OMB Max Site for a list of .gov domains for sharing). - -### Policies -#### MS.SHAREPOINT.1.1v1 -External sharing SHOULD be limited to Existing Guests or the more restrictive setting, Only People in your Organization. -- _Rationale:_ TODO -- _Last modified:_ June 2023 -- _Note:_ Same implementation in MS.ONEDRIVE.1.1v1 - -#### MS.SHAREPOINT.1.2v1 -External sharing SHOULD be limited to approved domains per interagency collaboration needs. -- _Rationale:_ TODO -- _Last modified:_ June 2023 - -#### MS.SHAREPOINT.1.3v1 -External sharing SHOULD be limited to approved security groups per interagency collaboration needs. -- _Rationale:_ TODO -- _Last modified:_ June 2023 - -#### MS.SHAREPOINT.1.4v1 -Guest access SHOULD be limited to the email the invitation was sent. -- _Rationale:_ TODO -- _Last modified:_ June 2023 - -### Resources - -- [Manage sharing settings \| Microsoft - Documents](https://docs.microsoft.com/en-us/sharepoint/turn-external-sharing-on-or-off) - -### License Requirements - -- N/A - -### Implementation - -MS.SHAREPOINT.1.1v1, in the **SharePoint admin center**: - -1. Select **Policies** -\> **Sharing** - -2. Adjust external sharing slider to **Existing Guests** or **Only people in your organization** - -3. Select **Save** - -MS.SHAREPOINT.1.2v1, in the **SharePoint admin center**: - -1. Select **Policies** -\> **Sharing** - -2. Expand **More external sharing settings** - -3. Select **Limit external sharing by domain** - -4. Select **Add domains** - -5. Add approved external domains - -6. Select **Save** - -MS.SHAREPOINT.1.3v1, in the **SharePoint admin center**: - -1. Select **Policies** -\> **Sharing** - -2. Expand **More external sharing settings** - -3. Select **Allow only users in specific security groups to share - externally** - -4. Select **Manage security groups** - -5. Add approved security groups - -6. Select **Save** - -MS.SHAREPOINT.1.4v1, in the **SharePoint admin center**: - -1. Select **Policies** -\> **Sharing** - -2. Expand **More external sharing settings** - -3. Select **Guests must sign in using the same account to which sharing invitations are sent** - -4. Select **Save** - -## 2. File and Folder Links Default Sharing Settings - -This policy ensures that when sharing files in SharePoint, there are -several possible scopes, including agency-wide or “anyone with the -link.” - -### Policies - -#### MS.SHAREPOINT.2.1v1 -File and folder links default sharing setting SHALL be set to Specific People (only the people the user specifies). -- _Rationale:_ TODO -- _Last modified:_ June 2023 -_Note:_ Similar implementation in MS.ONEDRIVE.3.1v1 - -### Resources - -- [File and folder links \| Microsoft - Documents](https://docs.microsoft.com/en-us/sharepoint/turn-external-sharing-on-or-off#file-and-folder-links) - -### License Requirements - -- N/A - -### Implementation - -MS.SHAREPOINT.2.1v1, in the **SharePoint admin center**: - -1. In the left-hand navigation bar, click **Policies** -\> **Sharing** - to display sharing settings - -2. Under **File and folder links**, ensure that the default link type - is set to **Specific people (only the people the user specifies)** - -3. Select **Save** - -## 3. Sensitivity Levels - -SharePoint allows sharing with users who are outside the agency, which -is convenient but may pose a data loss or other information security -risk. This baseline policy recommends, outside of the default -organizational settings, agencies evaluate each created site and -adjust sharing settings best aligned to their respective sensitivity -level. - -### Policies -#### MS.SHAREPOINT.3.1v1 -Sharing settings for specific SharePoint sites SHOULD align to their sensitivity level. -- _Rationale:_ TODO -- _Last modified:_ June 2023 - -### Resources - -- [Managing SharePoint Online Security: A Team Effort \| Microsoft - Build](https://docs.microsoft.com/en-us/microsoft-365/community/sharepoint-security-a-team-effort) - -### License Requirements - -- N/A - -### Implementation - -MS.SHAREPOINT.3.1v1, in the **SharePoint admin center**: - -1. Select **Sites** - -2. Select **Active sites** - -3. Select **Site name** - -4. Select **Settings** - -5. Select **More sharing settings** - -6. Select permissions aligning to the risk posture associated with the - sensitivity of the SharePoint site - -7. Select **Save** - -## 4. Guest Access to a Site or OneDrive - -SharePoint allows sharing with users who are outside the agency, which -is convenient but may pose a data loss or other information security -risk. This working group recommends setting an expiration time for guest -access to the site or OneDrive. - -**Note**: Adjusting this setting will adjust external sharing -for OneDrive and Teams to the same, specified expiration times. - -### Policies -#### MS.SHAREPOINT.4.1v1 -Expiration timers for guest access to a site or OneDrive SHOULD be set to 30 days or less. -- _Rationale:_ TODO -- _Last modified:_ June 2023 - -#### MS.SHAREPOINT.4.2v1 -Expiration timers for people who use a verification code SHOULD be set to 30 days or less. -- _Rationale:_ TODO -- _Last modified:_ June 2023 - -### License Requirements - -- N/A - -### Resources - -- [Managing SharePoint Online Security: A Team Effort \| Microsoft - Build](https://docs.microsoft.com/en-us/microsoft-365/community/sharepoint-security-a-team-effort) -- [Secure external sharing recipient experience \| Microsoft - Build](https://learn.microsoft.com/en-us/sharepoint/what-s-new-in-sharing-in-targeted-release) - -### Implementation - -MS.SHAREPOINT.4.1v1, in the **SharePoint admin center**: - -1. Select **Policies** -\> **Sharing** - -2. Expand **More external sharing settings** - -3. Select **Guest access to a site or OneDrive will expire - automatically after this many days** - -4. Enter “30” days or less - -5. Select **Save** - -MS.SHAREPOINT.4.2v1, in the **SharePoint admin center**: - -1. Select **Policies** -\> **Sharing** - -2. Expand **More external sharing settings** - -3. Select **People who use a verification code must reauthenticate - after this many days** - -4. Enter “30 days” or less - -5. Select **Save** - -## 5. Custom Scripts - -Allowing users to run custom scripts can potentially allow malicious -scripts to run in a trusted environment. Microsoft provides settings to -mitigate this risk by preventing users from running custom scripts. - -### Policy -#### MS.SHAREPOINT.5.1v1 -Users SHALL be prevented from running custom scripts on personal sites. -- _Rationale:_ TODO -- _Last modified:_ June 2023 - -#### MS.SHAREPOINT.5.2v1 -Users SHALL be prevented from running custom scripts on self-service created sites. -- _Rationale:_ TODO -- _Last modified:_ June 2023 - -### Resources - -- [Allow or prevent custom script \| Microsoft - Documents](https://docs.microsoft.com/en-us/sharepoint/allow-or-prevent-custom-script) - -### License Requirements - -- N/A - -### Implementation - -MS.SHAREPOINT.5.1v1, in the **SharePoint admin center**: - -1. Select **Settings** - -2. Scroll down to select **classic settings page** - -3. Scroll to the **Custom Script** setting - -4. Select **Prevent users from running custom script on personal sites** - -5. Select **Ok** - -MS.SHAREPOINT.5.1v1, in the **SharePoint admin center**: - -1. Select **Settings** - -2. Scroll down to select **classic settings page** - -3. Scroll to the **Custom Script** setting - -4. Select **Prevent users from running custom script on self-service created - sites** - -5. Select **Ok** - -# Acknowledgements - -In addition to acknowledging the important contributions of a diverse -team of Cybersecurity and Infrastructure Security Agency (CISA) experts, -CISA thanks the following federal agencies and private sector -organizations that provided input during the development of the Secure -Business Cloud Application’s security configuration baselines in -response to Section 3 of [Executive Order (EO) 14028, *Improving the -Nation’s -Cybersecurity*](https://www.federalregister.gov/documents/2021/05/17/2021-10460/improving-the-nations-cybersecurity): - -- Consumer Financial Protection Bureau (CFPB) - -- Department of the Interior (DOI) - -- National Aeronautics and Space Administration (NASA) - -- Sandia National Laboratories (Sandia) - -- U.S. Census Bureau (USCB) - -- U.S. Geological Survey (USGS) - -- U.S. Office of Personnel Management (OPM) - -- U.S. Small Business Administration (SBA) - -The cross-agency collaboration and partnerships developed during this -initiative serve as an example for solving complex problems faced by the -federal government. - -**Cybersecurity Innovation Tiger Team (CITT) Leadership** - -Beau Houser (USCB), Sanjay Gupta (SBA), Michael Witt (NASA), James -Saunders (OPM), Han Lin (Sandia), Andrew Havely (DOI). - -**CITT Authors** - -Trafenia Salzman (SBA), Benjamin McChesney (OPM), Robert Collier (USCB), -Matthew Snitchler (Sandia), Darryl Purdy (USCB), Brandon Frankens -(NASA), Brandon Goss (NASA), Nicole Bogeajis (DOI/USGS), Kevin Kelly -(DOI), Adnan Ehsan (CFPB), Michael Griffin (CFPB), Vincent Urias -(Sandia), Angela Calabaza (Sandia). - -**CITT Contributors** - -Dr. Mukesh Rohatgi (MITRE), Lee Szilagyi (MITRE), Nanda Katikaneni -(MITRE), Ted Kolovos (MITRE), Thomas Comeau (MITRE), Karen Caraway -(MITRE), Jackie Whieldon (MITRE), Jeanne Firey (MITRE), Kenneth Myers -(General Services Administration). \ No newline at end of file diff --git a/baselines/sharepointonedrive.md b/baselines/sharepointonedrive.md new file mode 100644 index 0000000000..6d3851f9ad --- /dev/null +++ b/baselines/sharepointonedrive.md @@ -0,0 +1,338 @@ +# CISA M365 Security Configuration Baseline for SharePoint Online and OneDrive + +SharePoint Online is a web-based collaboration and document management +platform. It is primarily used to collaborate on documents and communicate information in project teams. OneDrive is a cloud-based file storage system primarily used to store a user's personal files but it can also be used to share documents with others. This security baseline provides policies to help secure both of these services. + +## License Compliance and Copyright + +Portions of this document are adapted from documents in Microsoft’s +[Microsoft +365](https://github.com/MicrosoftDocs/microsoft-365-docs/blob/public/LICENSE) +and +[Azure](https://github.com/MicrosoftDocs/azure-docs/blob/main/LICENSE) +GitHub repositories. The respective documents are subject to copyright +and are adapted under the terms of the Creative Commons Attribution 4.0 +International license. Source documents are linked throughout this +document. The United States Government has adapted selections of these +documents to develop innovative and scalable configuration standards to +strengthen the security of widely used cloud-based software services. + +## Assumptions + +The **License Requirements** sections of this document assume the +organization is using an [M365 +E3](https://www.microsoft.com/en-us/microsoft-365/compare-microsoft-365-enterprise-plans) +or [G3](https://www.microsoft.com/en-us/microsoft-365/government) +license level. Therefore, only licenses not included in E3/G3 are +listed. + +# Baseline Policies + +## 1. External Sharing + +This section helps reduce security risks related to the sharing of files with users external to the agency. This includes guest users, users who use a verification code and users who access an Anyone link. + +### Policies +#### MS.SHAREPOINT.1.1v1 +External sharing for SharePoint SHALL be limited to Existing Guests or Only People in your Organization. +- _Rationale:_ Sharing information outside the organization increases the risk of unauthorized disclosure. By limiting external sharing, administrators decrease the risk of unauthorized disclosure. +- _Last modified:_ June 2023 + +#### MS.SHAREPOINT.1.2v1 +External sharing for OneDrive SHALL be limited to Existing Guests or Only People in your Organization. +- _Rationale:_ Sharing files outside the organization increases the risk of unauthorized disclosure. By limiting external sharing, administrators decrease the risk of unauthorized disclosure. +- _Last modified:_ June 2023 + +#### MS.SHAREPOINT.1.3v1 +External sharing SHALL be restricted to approved external domains per interagency collaboration needs. +- _Rationale:_ By limiting sharing to domains used for interagency collaboration purposes, administrators prevent sharing with unknown organizations and individuals. +- _Last modified:_ June 2023 +- _Note:_ This policy is only applicable if the external sharing slider on the admin page is set to any value other than Only People in your Organization. + +#### MS.SHAREPOINT.1.4v1 +Only users in approved security groups SHALL be allowed to share externally. +- _Rationale:_ By limiting sharing to approved security groups based on interagency collaboration needs, administrators ensure only approved users can use share information outside the organization. +- _Last modified:_ June 2023 +- _Note:_ This policy is only applicable if the external sharing slider on the admin page is set to any value other than Only People in your Organization. + +#### MS.SHAREPOINT.1.5v1 +Guest access SHALL be limited to the email the invitation was sent to. +- _Rationale:_ Email invitations allow external guests to access shared information. By requiring guests to sign in using the same account where the invite was sent, administrators ensure only the intended guest can use the invite. +- _Last modified:_ June 2023 +- _Note:_ This policy is only applicable if the external sharing slider on the admin page is set to any value other than Only People in your Organization. + +### Resources + +- [Overview of external sharing in SharePoint and OneDrive in Microsoft 365 \| Microsoft Documents](https://learn.microsoft.com/en-us/sharepoint/external-sharing-overview) + +- [Manage sharing settings for SharePoint and OneDrive in Microsoft 365 \| Microsoft Documents](https://docs.microsoft.com/en-us/sharepoint/turn-external-sharing-on-or-off) + +### License Requirements + +- N/A + +### Implementation + +All of the settings in this section are configured in the **SharePoint admin center**. + +#### MS.SHAREPOINT.1.1v1 instructions: + +1. Select **Policies** \> **Sharing** + +2. Adjust external sharing slider for SharePoint to **Existing Guests** or **Only people in your organization** + +3. Select **Save** + +#### MS.SHAREPOINT.1.2v1 instructions: + +1. Follow the same instructions as MS.SHAREPOINT.1.1v1 but set the slider value for OneDrive. + +#### MS.SHAREPOINT.1.3v1 instructions: + +1. Select **Policies** \> **Sharing** + +2. Expand **More external sharing settings** + +3. Select **Limit external sharing by domain** + +4. Select **Add domains** + +5. Add each approved external domain that users allowed to share files with + +6. Select **Save** + +#### MS.SHAREPOINT.1.4v1 instructions: + +1. Select **Policies** \> **Sharing** + +2. Expand **More external sharing settings** + +3. Select **Allow only users in specific security groups to share + externally** + +4. Select **Manage security groups** + +5. Add each approved security group - members of these groups will be allowed to share files externally + +6. Select **Save** + +#### MS.SHAREPOINT.1.5v1 instructions: + +1. Select **Policies** \> **Sharing** + +2. Expand **More external sharing settings** + +3. Select **Guests must sign in using the same account to which sharing invitations are sent** + +4. Select **Save** + +## 2. File and Folder Default Sharing Settings + +This section provides policies to set the scope and permissions for sharing links to secure default values. + +### Policies + +#### MS.SHAREPOINT.2.1v1 +File and folder default sharing scope SHALL be set to Specific People (only the people the user specifies). +- _Rationale:_ By making the default sharing the most restrictive, administrators prevent accidentally sharing information too broadly. +- _Last modified:_ June 2023 + +#### MS.SHAREPOINT.2.2v1 +File and folder default sharing permissions SHALL be set to View only. +- _Rationale:_ Edit access to files and folders could allow a user to make unauthorized changes. By restricting default permissions to View only, administrators prevent unintended or malicious modification. +- _Last modified:_ June 2023 + +### Resources + +- [File and folder links \| Microsoft + Documents](https://docs.microsoft.com/en-us/sharepoint/turn-external-sharing-on-or-off#file-and-folder-links) + +### License Requirements + +- N/A + +### Implementation + +All of the settings in this section are configured in the **SharePoint admin center**. + +#### MS.SHAREPOINT.2.1v1 instructions: + +1. Select **Policies** \> **Sharing** + +2. Under **File and folder links**, set the default link type to **Specific people (only the people the user specifies)** + +3. Select **Save** + +#### MS.SHAREPOINT.2.2v1 instructions: + +1. Navigate to the same location in the portal as MS.SHAREPOINT.2.1v1, but set the permission that's selected by default for sharing links to **View** + +## 3. Securing Anyone Links and Verification Code Users + +Sharing of files with external users via the usage of Anyone links or Verification codes is strongly discouraged because it provides access to data within a tenant with weak or no authentication. In the event that these features are being used, this section provides some access restrictions that could provide limited security risk mitigations. + +**Note**: The settings in this section are only applicable if an agency is using anyone links or verification code sharing. See each policy below for details. + +### Policies +#### MS.SHAREPOINT.3.1v1 +Expiration days for anyone links SHALL be set to 30 days or less. +- _Rationale:_ Anyone links may be used to provide access to information for a short period of time. Without expiration, however, access is indefinite. By setting expiration timers for anyone links, administrators prevent unintended sustained access to information. +- _Last modified:_ June 2023 +- _Note:_ This policy is only applicable if the external sharing slider on the admin center sharing page is set to Anyone. + +#### MS.SHAREPOINT.3.2v1 +The allowable file and folder permissions for anyone links SHALL be set to View only. +- _Rationale:_ Unauthorized changes to files can be made if permissions allow editing by anyone. By restricting permissions on anyone links to View only, administrators prevent anonymous file changes. +- _Last modified:_ June 2023 +- _Note:_ This policy is only applicable if the external sharing slider on the admin center sharing page is set to Anyone. + +#### MS.SHAREPOINT.3.3v1 +Reauthentication days for people who use a verification code SHALL be set to 30 days or less. +- _Rationale:_ A verification code may be given out to provide access to information for a short period of time. Without expiration, however, access is indefinite. By setting expiration timers for verification code access, administrators prevent unintended sustained access to information. +- _Last modified:_ June 2023 +- _Note:_ This policy is only applicable if the external sharing slider on the admin center sharing page is set to Anyone or New and Existing Guests. + +### License Requirements + +- N/A + +### Resources + +- [Secure external sharing recipient experience \| Microsoft + Documents](https://learn.microsoft.com/en-us/sharepoint/what-s-new-in-sharing-in-targeted-release) + +### Implementation + +All of the settings in this section are configured in the **SharePoint admin center**. + +#### MS.SHAREPOINT.3.1v1 instructions: + +1. Select **Policies** \> **Sharing** + +2. Scroll to the section **Choose expiration and permissions options for Anyone links** + +3. Select the checkbox **These links must expire within this many days** + +4. Enter “30” days or less + +5. Select **Save** + +#### MS.SHAREPOINT.3.2v1 instructions: + +1. Select **Policies** \> **Sharing** + +2. Scroll to the section **Choose expiration and permissions options for Anyone links** + +3. Set the configuration items in the section **These links can give these permissions** + +4. Set the **Files** option to **View** + +5. Set the **Folders** option to **View** + +6. Select **Save** + +#### MS.SHAREPOINT.3.3v1 instructions: + +1. Select **Policies** \> **Sharing** + +2. Expand **More external sharing settings** + +3. Select **People who use a verification code must reauthenticate after this many days** + +4. Enter “30” days or less + +5. Select **Save** + +## 4. Custom Scripts + +This section provides policies for restricting the execution of custom scripts. +å +#### MS.SHAREPOINT.4.1v1 +Users SHALL be prevented from running custom scripts on personal sites (aka OneDrive). +- _Rationale:_ Scripts on SharePoint sites run in the context of the user visiting the site and have access to everything that user can access. By preventing custom scripts on personal sites, administrators block a path for potentially malicious code execution. +- _Last modified:_ June 2023 + +#### MS.SHAREPOINT.4.2v1 +Users SHALL be prevented from running custom scripts on self-service created sites. +- _Rationale:_ Scripts on SharePoint sites run in the context of the user visiting the site and have access to everything that user can access. By preventing custom scripts on self-service created sites, administrators block a path for potentially malicious code execution. +- _Last modified:_ June 2023 + +### Resources + +- [Allow or prevent custom script \| Microsoft + Documents](https://docs.microsoft.com/en-us/sharepoint/allow-or-prevent-custom-script) + +### License Requirements + +- N/A + +### Implementation + +All of the settings in this section are configured in the **SharePoint admin center**. + +#### MS.SHAREPOINT.4.1v1 instructions: + +1. Select **Settings** + +2. Scroll down and select **classic settings page** + +3. Scroll to the **Custom Script** section + +4. Select **Prevent users from running custom script on personal sites** + +5. Select **Ok** + +#### MS.SHAREPOINT.4.2v1 instructions: + +1. Navigate to the same location in the portal as MS.SHAREPOINT.4.1v1, but select the option **Prevent users from running custom script on self-service created sites** + +# Acknowledgements + +In addition to acknowledging the important contributions of a diverse +team of Cybersecurity and Infrastructure Security Agency (CISA) experts, +CISA thanks the following federal agencies and private sector +organizations that provided input during the development of the Secure +Business Cloud Application’s security configuration baselines in +response to Section 3 of [Executive Order (EO) 14028, *Improving the +Nation’s +Cybersecurity*](https://www.federalregister.gov/documents/2021/05/17/2021-10460/improving-the-nations-cybersecurity): + +- Consumer Financial Protection Bureau (CFPB) + +- Department of the Interior (DOI) + +- National Aeronautics and Space Administration (NASA) + +- Sandia National Laboratories (Sandia) + +- U.S. Census Bureau (USCB) + +- U.S. Geological Survey (USGS) + +- U.S. Office of Personnel Management (OPM) + +- U.S. Small Business Administration (SBA) + +The cross-agency collaboration and partnerships developed during this +initiative serve as an example for solving complex problems faced by the +federal government. + +**Cybersecurity Innovation Tiger Team (CITT) Leadership** + +Beau Houser (USCB), Sanjay Gupta (SBA), Michael Witt (NASA), James +Saunders (OPM), Han Lin (Sandia), Andrew Havely (DOI). + +**CITT Authors** + +Trafenia Salzman (SBA), Benjamin McChesney (OPM), Robert Collier (USCB), +Matthew Snitchler (Sandia), Darryl Purdy (USCB), Brandon Frankens +(NASA), Brandon Goss (NASA), Nicole Bogeajis (DOI/USGS), Kevin Kelly +(DOI), Adnan Ehsan (CFPB), Michael Griffin (CFPB), Vincent Urias +(Sandia), Angela Calabaza (Sandia). + +**CITT Contributors** + +Dr. Mukesh Rohatgi (MITRE), Lee Szilagyi (MITRE), Nanda Katikaneni +(MITRE), Ted Kolovos (MITRE), Thomas Comeau (MITRE), Karen Caraway +(MITRE), Jackie Whieldon (MITRE), Jeanne Firey (MITRE), Kenneth Myers +(General Services Administration). \ No newline at end of file From fa9c0b6797b07d51837f1efbda38b623fc2a4aa3 Mon Sep 17 00:00:00 2001 From: Richard Crutchfield Date: Fri, 14 Jul 2023 12:10:17 -0400 Subject: [PATCH 26/33] Adjudicate review comments --- Rego/AADConfig.rego | 6 +++--- Rego/Utils/{TestUtils.rego => PolicyUtils.rego} | 6 +----- 2 files changed, 4 insertions(+), 8 deletions(-) rename Rego/Utils/{TestUtils.rego => PolicyUtils.rego} (85%) diff --git a/Rego/AADConfig.rego b/Rego/AADConfig.rego index 1ee68397c6..ac6957a732 100644 --- a/Rego/AADConfig.rego +++ b/Rego/AADConfig.rego @@ -3,9 +3,9 @@ import future.keywords import data.report.utils.NotCheckedDetails import data.report.utils.Format import data.report.utils.ReportDetailsBoolean -import data.test.utils.IsEmptyContainer -import data.test.utils.Contains -import data.test.utils.Count +import data.policy.utils.IsEmptyContainer +import data.policy.utils.Contains +import data.policy.utils.Count ############################################################################# # The report formatting functions below are generic and used throughout AAD # diff --git a/Rego/Utils/TestUtils.rego b/Rego/Utils/PolicyUtils.rego similarity index 85% rename from Rego/Utils/TestUtils.rego rename to Rego/Utils/PolicyUtils.rego index 4fda5a23a5..aa706c6404 100644 --- a/Rego/Utils/TestUtils.rego +++ b/Rego/Utils/PolicyUtils.rego @@ -1,10 +1,6 @@ -package test.utils +package policy.utils import future.keywords -#IsEmpty(null, _) = true -#IsEmpty(a, b) if not a[b] -#IsEmpty(a, b) if a[b] == "" - IsEmptyContainer(null) = true IsEmptyContainer(container) := true if { Temp := {Item | Item := container[_]} From cc764c0faa936d7ff7e15413ad5698998116cac0 Mon Sep 17 00:00:00 2001 From: Richard Crutchfield Date: Tue, 11 Jul 2023 11:44:59 -0400 Subject: [PATCH 27/33] WIP --- Rego/AADConfig.rego | 43 ++++- Testing/Unit/Rego/AAD/AADConfig_03_test.rego | 184 ++++++++++++++++++- 2 files changed, 215 insertions(+), 12 deletions(-) diff --git a/Rego/AADConfig.rego b/Rego/AADConfig.rego index 1ace61fe9a..1338f8ec61 100644 --- a/Rego/AADConfig.rego +++ b/Rego/AADConfig.rego @@ -268,18 +268,43 @@ tests[{ # # MS.AAD.3.1v1 #-- -# At this time we are unable to fully test for MFA due to conflicting and multiple ways to configure authentication methods -# Awaiting API changes and feature updates from Microsoft for automated checking +default PhishingResistantMFAConditionsMatch(_) := false +HasPhishingResistantMFA(Policy) := true if { + Strengths := { Strength | Strength := Policy.GrantControls.AuthenticationStrength.AllowedCombinations[_]} + AcceptableMFA := {"windowsHelloForBusiness", "fido2", "x509CertificateMultiFactor"} + count(AcceptableMFA) == count(Strengths | AcceptableMFA) +} + +PhishingResistantMFAConditionsMatch(Policy) := true if { + "All" in Policy.Conditions.Users.IncludeUsers + "All" in Policy.Conditions.Applications.IncludeApplications + count(Policy.Conditions.Applications.ExcludeApplications) == 0 + HasPhishingResistantMFA(Policy) + Policy.State == "enabled" + count(Policy.Conditions.Users.ExcludeRoles) == 0 +} + +PhishingResistantMFA[Cap.DisplayName] { + Cap := input.conditional_access_policies[_] + + # Match all simple conditions + PhishingResistantMFAConditionsMatch(Cap) + + # Only match policies with user and group exclusions if all exempted + UserExclusionsFullyExempt(Cap, "MS.AAD.3.1v1") == true + GroupExclusionsFullyExempt(Cap, "MS.AAD.3.1v1") == true +} + tests[{ - "PolicyId" : PolicyId, - "Criticality" : "Shall/Not-Implemented", - "Commandlet" : [], + "PolicyId" : "MS.AAD.3.1v1", + "Criticality" : "Shall", + "Commandlet" : ["Get-MgIdentityConditionalAccessPolicy"], "ActualValue" : [], - "ReportDetails" : NotCheckedDetails(PolicyId), - "RequirementMet" : false + "ReportDetails" : concat(". ", [ReportFullDetailsArray(PhishingResistantMFA, DescriptionString), CapLink]), + "RequirementMet" : Status }] { - PolicyId := "MS.AAD.3.1v1" - true + DescriptionString := "conditional access policy(s) found that meet(s) all requirements" + Status := count(PhishingResistantMFA) > 0 } #-- diff --git a/Testing/Unit/Rego/AAD/AADConfig_03_test.rego b/Testing/Unit/Rego/AAD/AADConfig_03_test.rego index add2a1986b..f9b6833985 100644 --- a/Testing/Unit/Rego/AAD/AADConfig_03_test.rego +++ b/Testing/Unit/Rego/AAD/AADConfig_03_test.rego @@ -6,16 +6,194 @@ import data.report.utils.NotCheckedDetails # # MS.AAD.3.1v1 #-- -test_NotImplemented_Correct_V1 if { +test_PhishingResistantAllMFA_Correct if { PolicyId := "MS.AAD.3.1v1" - Output := tests with input as { } + Output := 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" : "Test name" + } + ] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "1 conditional access policy(s) found that meet(s) all requirements:
Test name. View all CA policies." +} + +test_PhishingResistantSingleMFA_Correct if { + PolicyId := "MS.AAD.3.1v1" + + Output := tests with input as { + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"], + "ExcludeApplications" : [] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : [], + "ExcludeGroups" : [], + "ExcludeRoles" : [] + } + }, + "GrantControls" : { + "AuthenticationStrength" : { + "AllowedCombinations": [ + "x509CertificateMultiFactor" + ] + } + }, + "State" : "enabled", + "DisplayName" : "Test name" + } + ] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "1 conditional access policy(s) found that meet(s) all requirements:
Test name. View all CA policies." +} + +test_PhishingResistantMFAExcludeApp_Incorrect if { + PolicyId := "MS.AAD.3.1v1" + + Output := tests with input as { + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"], + "ExcludeApplications" : ["Some App"] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : [], + "ExcludeGroups" : [], + "ExcludeRoles" : [] + } + }, + "GrantControls" : { + "AuthenticationStrength" : { + "DisplayName": "Phishing-resistant MFA" + } + }, + "State" : "enabled", + "DisplayName" : "Test name" + } + ] + } RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] count(RuleOutput) == 1 not RuleOutput[0].RequirementMet - RuleOutput[0].ReportDetails == NotCheckedDetails(PolicyId) + RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." +} + +test_PhishingResistantMFAExcludeUser_Incorrect if { + PolicyId := "MS.AAD.3.1v1" + + Output := tests with input as { + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"], + "ExcludeApplications" : [] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : ["me"], + "ExcludeGroups" : [], + "ExcludeRoles" : [] + } + }, + "GrantControls" : { + "AuthenticationStrength" : { + "AllowedCombinations": [ + "windowsHelloForBusiness", + "fido2", + "x509CertificateMultiFactor" + ] + } + }, + "State" : "enabled", + "DisplayName" : "Test name" + } + ] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." +} + +test_PhishingResistantMFAExcludeGroup_Incorrect if { + PolicyId := "MS.AAD.3.1v1" + + Output := tests with input as { + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"], + "ExcludeApplications" : [] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : [], + "ExcludeGroups" : ["some"], + "ExcludeRoles" : [] + } + }, + "GrantControls" : { + "AuthenticationStrength" : { + "DisplayName": "Phishing-resistant MFA" + } + }, + "State" : "enabled", + "DisplayName" : "Test name" + } + ] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." } #-- From 18862f8cb46b23253184ca288910f9d1ed6349a8 Mon Sep 17 00:00:00 2001 From: Richard Crutchfield Date: Thu, 13 Jul 2023 08:38:09 -0400 Subject: [PATCH 28/33] wip --- Rego/AADConfig.rego | 48 +++-- Rego/Utils/TestUtils.rego | 34 ++++ Testing/Unit/Rego/AAD/AADConfig_03_test.rego | 183 ++++++++++++++++++- 3 files changed, 243 insertions(+), 22 deletions(-) create mode 100644 Rego/Utils/TestUtils.rego diff --git a/Rego/AADConfig.rego b/Rego/AADConfig.rego index 1338f8ec61..25f1ac2c97 100644 --- a/Rego/AADConfig.rego +++ b/Rego/AADConfig.rego @@ -3,6 +3,10 @@ import future.keywords import data.report.utils.NotCheckedDetails import data.report.utils.Format import data.report.utils.ReportDetailsBoolean +import data.test.utils.IsAllUsers +import data.test.utils.IsEmptyContainer +import data.test.utils.Contains +import data.test.utils.Count ############################################################################# # The report formatting functions below are generic and used throughout AAD # @@ -268,42 +272,46 @@ tests[{ # # MS.AAD.3.1v1 #-- -default PhishingResistantMFAConditionsMatch(_) := false -HasPhishingResistantMFA(Policy) := true if { - Strengths := { Strength | Strength := Policy.GrantControls.AuthenticationStrength.AllowedCombinations[_]} - AcceptableMFA := {"windowsHelloForBusiness", "fido2", "x509CertificateMultiFactor"} - count(AcceptableMFA) == count(Strengths | AcceptableMFA) -} - -PhishingResistantMFAConditionsMatch(Policy) := true if { - "All" in Policy.Conditions.Users.IncludeUsers - "All" in Policy.Conditions.Applications.IncludeApplications - count(Policy.Conditions.Applications.ExcludeApplications) == 0 - HasPhishingResistantMFA(Policy) - Policy.State == "enabled" - count(Policy.Conditions.Users.ExcludeRoles) == 0 -} PhishingResistantMFA[Cap.DisplayName] { Cap := input.conditional_access_policies[_] - # Match all simple conditions - PhishingResistantMFAConditionsMatch(Cap) + IsEmptyContainer(Cap.Conditions.Applications.ExcludeApplications) + print("app exclusion") - # Only match policies with user and group exclusions if all exempted - UserExclusionsFullyExempt(Cap, "MS.AAD.3.1v1") == true + Cap.State == "enabled" + print("policy enabled") + + Strengths := { Strength | Strength := Cap.GrantControls.AuthenticationStrength.AllowedCombinations[_]} + print("Strengths: ", Strengths) + print("Strengths count: ", count(Strengths)) + AcceptableMFA := {"windowsHelloForBusiness", "fido2", "x509CertificateMultiFactor"} + print("Acceptable count: ", count(AcceptableMFA)) + count(Strengths) > 0 + print("Strengths count: ", count(Strengths)) + MinusSet := Strengths - AcceptableMFA + count(MinusSet) == 0 + print("Acceptable MFA strength") + + Contains(Cap.Conditions.Applications.IncludeApplications, "All") GroupExclusionsFullyExempt(Cap, "MS.AAD.3.1v1") == true + Contains(Cap.Conditions.Users.IncludeUsers, "All") + print("users: ", Contains(Cap.Conditions.Users.IncludeUsers, "All")) + UserExclusionsFullyExempt(Cap, "MS.AAD.3.1v1") == true + print("user exclusion") } tests[{ "PolicyId" : "MS.AAD.3.1v1", "Criticality" : "Shall", "Commandlet" : ["Get-MgIdentityConditionalAccessPolicy"], - "ActualValue" : [], + "ActualValue" : PhishingResistantMFA, "ReportDetails" : concat(". ", [ReportFullDetailsArray(PhishingResistantMFA, DescriptionString), CapLink]), "RequirementMet" : Status }] { DescriptionString := "conditional access policy(s) found that meet(s) all requirements" + print("Tests policy count: " , count(PhishingResistantMFA)) + print("Tests policy count: " , PhishingResistantMFA) Status := count(PhishingResistantMFA) > 0 } #-- diff --git a/Rego/Utils/TestUtils.rego b/Rego/Utils/TestUtils.rego new file mode 100644 index 0000000000..4fda5a23a5 --- /dev/null +++ b/Rego/Utils/TestUtils.rego @@ -0,0 +1,34 @@ +package test.utils +import future.keywords + +#IsEmpty(null, _) = true +#IsEmpty(a, b) if not a[b] +#IsEmpty(a, b) if a[b] == "" + +IsEmptyContainer(null) = true +IsEmptyContainer(container) := true if { + Temp := {Item | Item := container[_]} + count(Temp) == 0 +} + +IsAllUsers(null) = false +IsAllUsers(array) := true if { + not IsEmptyContainer(array) + array[_] == "All" +} else = false {true} + +Contains(null, _) = false +Contains(array, item) := true if { + not IsEmptyContainer(array) + array[_] == item +} else = false { + true +} + +Count(null) = 0 +Count(container) := Result if { + not IsEmptyContainer(container) + Result := count(container) +} else = 0 { + true +} diff --git a/Testing/Unit/Rego/AAD/AADConfig_03_test.rego b/Testing/Unit/Rego/AAD/AADConfig_03_test.rego index f9b6833985..6591e22159 100644 --- a/Testing/Unit/Rego/AAD/AADConfig_03_test.rego +++ b/Testing/Unit/Rego/AAD/AADConfig_03_test.rego @@ -84,6 +84,177 @@ test_PhishingResistantSingleMFA_Correct if { RuleOutput[0].ReportDetails == "1 conditional access policy(s) found that meet(s) all requirements:
Test name. View all CA policies." } + +test_PhishingResistantNoneMFA_Incorrect if { + PolicyId := "MS.AAD.3.1v1" + + Output := tests with input as { +"conditional_access_policies": [ + { + "Conditions": { + "Applications": { + "ApplicationFilter": { + "Mode": null, + "Rule": null + }, + "ExcludeApplications": [ + + ], + "IncludeApplications": [ + "All" + ], + "IncludeAuthenticationContextClassReferences": [], + "IncludeUserActions": [] + }, + "ClientAppTypes": [ + "all" + ], + "ClientApplications": { + "ExcludeServicePrincipals": null, + "IncludeServicePrincipals": null, + "ServicePrincipalFilter": { + "Mode": null, + "Rule": null + } + }, + "DeviceStates": { + "ExcludeStates": null, + "IncludeStates": null + }, + "Devices": { + "DeviceFilter": { + "Mode": null, + "Rule": null + }, + "ExcludeDeviceStates": null, + "ExcludeDevices": null, + "IncludeDeviceStates": null, + "IncludeDevices": null + }, + "Locations": { + "ExcludeLocations": null, + "IncludeLocations": null + }, + "Platforms": { + "ExcludePlatforms": null, + "IncludePlatforms": null + }, + "ServicePrincipalRiskLevels": null, + "SignInRiskLevels": [ + + ], + "UserRiskLevels": [ + + ], + "Users": { + "ExcludeGroups": [ + + ], + "ExcludeGuestsOrExternalUsers": { + "ExternalTenants": { + "MembershipKind": null + }, + "GuestOrExternalUserTypes": null + }, + "ExcludeRoles": [ + + ], + "ExcludeUsers": [ + "66b4d5c2-71c9-4644-8728-74e3a8324d81" + ], + "IncludeGroups": [ + + ], + "IncludeGuestsOrExternalUsers": { + "ExternalTenants": { + "MembershipKind": null + }, + "GuestOrExternalUserTypes": null + }, + "IncludeRoles": [ + "62e90394-69f5-4237-9190-012177145e10", + "e8611ab8-c189-46e8-94e1-60213ab1f814", + "fe930be7-5e62-47db-91af-98c3a49a38b1", + "f28a1f50-f6e7-4571-818b-6a12f2af6b6c", + "29232cdf-9323-42fd-ade2-1d097af3e4de", + "8ac3fc64-6eca-42ea-9e69-59f4c7b60eb2", + "9b895d92-2cd3-44c7-9d02-a6ac2d5ea5c3", + "158c047a-c907-4556-b7ef-446551a6b5f7", + "b0f54661-2d74-4c50-afa3-1ec803f12efe" + ], + "IncludeUsers": [] + } + }, + "CreatedDateTime": "/Date(1668112094045)/", + "Description": null, + "DisplayName": "Live - MFA required for Highly Privileged Roles", + "GrantControls": { + "AuthenticationStrength": { + "AllowedCombinations": [], + "CombinationConfigurations": null, + "CreatedDateTime": null, + "Description": null, + "DisplayName": null, + "Id": null, + "ModifiedDateTime": null, + "PolicyType": null, + "RequirementsSatisfied": null + }, + "BuiltInControls": [ + "mfa" + ], + "CustomAuthenticationFactors": [ + + ], + "Operator": "OR", + "TermsOfUse": [ + + ] + }, + "Id": "9e174715-5697-4695-ac39-92f4af6ac2c4", + "ModifiedDateTime": "/Date(1668112265652)/", + "SessionControls": { + "ApplicationEnforcedRestrictions": { + "IsEnabled": null + }, + "CloudAppSecurity": { + "CloudAppSecurityType": null, + "IsEnabled": null + }, + "ContinuousAccessEvaluation": { + "Mode": null + }, + "DisableResilienceDefaults": null, + "PersistentBrowser": { + "IsEnabled": null, + "Mode": null + }, + "SecureSignInSession": { + "IsEnabled": null + }, + "SignInFrequency": { + "AuthenticationType": null, + "FrequencyInterval": null, + "IsEnabled": null, + "Type": null, + "Value": null + } + }, + "State": "enabled", + "AdditionalProperties": { + + } + } +] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + #RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." +} + test_PhishingResistantMFAExcludeApp_Incorrect if { PolicyId := "MS.AAD.3.1v1" @@ -104,7 +275,11 @@ test_PhishingResistantMFAExcludeApp_Incorrect if { }, "GrantControls" : { "AuthenticationStrength" : { - "DisplayName": "Phishing-resistant MFA" + "AllowedCombinations": [ + "windowsHelloForBusiness", + "fido2", + "x509CertificateMultiFactor" + ] } }, "State" : "enabled", @@ -180,7 +355,11 @@ test_PhishingResistantMFAExcludeGroup_Incorrect if { }, "GrantControls" : { "AuthenticationStrength" : { - "DisplayName": "Phishing-resistant MFA" + "AllowedCombinations": [ + "windowsHelloForBusiness", + "fido2", + "x509CertificateMultiFactor" + ] } }, "State" : "enabled", From 07a4cbe6da9bcd8d76744b211d6da28f0d21e47f Mon Sep 17 00:00:00 2001 From: Richard Crutchfield Date: Thu, 13 Jul 2023 09:38:27 -0400 Subject: [PATCH 29/33] Implemented AAD 3.1 --- Rego/AADConfig.rego | 36 +-- Testing/Unit/Rego/AAD/AADConfig_03_test.rego | 218 ++++++------------- 2 files changed, 73 insertions(+), 181 deletions(-) diff --git a/Rego/AADConfig.rego b/Rego/AADConfig.rego index 25f1ac2c97..3d1a68f1d9 100644 --- a/Rego/AADConfig.rego +++ b/Rego/AADConfig.rego @@ -273,46 +273,34 @@ tests[{ # MS.AAD.3.1v1 #-- -PhishingResistantMFA[Cap.DisplayName] { +MS_AAD_3_1v1_CAP[Cap.DisplayName] { Cap := input.conditional_access_policies[_] - IsEmptyContainer(Cap.Conditions.Applications.ExcludeApplications) - print("app exclusion") - Cap.State == "enabled" - print("policy enabled") + Contains(Cap.Conditions.Users.IncludeUsers, "All") + IsEmptyContainer(Cap.Conditions.Applications.ExcludeApplications) + Contains(Cap.Conditions.Applications.IncludeApplications, "All") + GroupExclusionsFullyExempt(Cap, "MS.AAD.3.1v1") == true + UserExclusionsFullyExempt(Cap, "MS.AAD.3.1v1") == true + # Strength must be at least one of acceptable with no unacceptable strengths Strengths := { Strength | Strength := Cap.GrantControls.AuthenticationStrength.AllowedCombinations[_]} - print("Strengths: ", Strengths) - print("Strengths count: ", count(Strengths)) AcceptableMFA := {"windowsHelloForBusiness", "fido2", "x509CertificateMultiFactor"} - print("Acceptable count: ", count(AcceptableMFA)) - count(Strengths) > 0 - print("Strengths count: ", count(Strengths)) MinusSet := Strengths - AcceptableMFA - count(MinusSet) == 0 - print("Acceptable MFA strength") - - Contains(Cap.Conditions.Applications.IncludeApplications, "All") - GroupExclusionsFullyExempt(Cap, "MS.AAD.3.1v1") == true - Contains(Cap.Conditions.Users.IncludeUsers, "All") - print("users: ", Contains(Cap.Conditions.Users.IncludeUsers, "All")) - UserExclusionsFullyExempt(Cap, "MS.AAD.3.1v1") == true - print("user exclusion") + Count(MinusSet) == 0 + Count(Strengths) > 0 } tests[{ "PolicyId" : "MS.AAD.3.1v1", "Criticality" : "Shall", "Commandlet" : ["Get-MgIdentityConditionalAccessPolicy"], - "ActualValue" : PhishingResistantMFA, - "ReportDetails" : concat(". ", [ReportFullDetailsArray(PhishingResistantMFA, DescriptionString), CapLink]), + "ActualValue" : MS_AAD_3_1v1_CAP, + "ReportDetails" : concat(". ", [ReportFullDetailsArray(MS_AAD_3_1v1_CAP, DescriptionString), CapLink]), "RequirementMet" : Status }] { DescriptionString := "conditional access policy(s) found that meet(s) all requirements" - print("Tests policy count: " , count(PhishingResistantMFA)) - print("Tests policy count: " , PhishingResistantMFA) - Status := count(PhishingResistantMFA) > 0 + Status := count(MS_AAD_3_1v1_CAP) > 0 } #-- diff --git a/Testing/Unit/Rego/AAD/AADConfig_03_test.rego b/Testing/Unit/Rego/AAD/AADConfig_03_test.rego index 6591e22159..7d9e178e67 100644 --- a/Testing/Unit/Rego/AAD/AADConfig_03_test.rego +++ b/Testing/Unit/Rego/AAD/AADConfig_03_test.rego @@ -84,168 +84,72 @@ test_PhishingResistantSingleMFA_Correct if { RuleOutput[0].ReportDetails == "1 conditional access policy(s) found that meet(s) all requirements:
Test name. View all CA policies." } +test_PhishingResistantExtraMFA_Incorrect if { + PolicyId := "MS.AAD.3.1v1" + + Output := tests with input as { + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"], + "ExcludeApplications" : [] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : [], + "ExcludeGroups" : [], + "ExcludeRoles" : [] + } + }, + "GrantControls" : { + "AuthenticationStrength" : { + "AllowedCombinations": [ + "x509CertificateMultiFactor", + "SuperStrength" + ] + } + }, + "State" : "enabled", + "DisplayName" : "Test name" + } + ] + } + + RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] + + count(RuleOutput) == 1 + not RuleOutput[0].RequirementMet + #RuleOutput[0].ReportDetails == "0 conditional access policy(s) found that meet(s) all requirements. View all CA policies." +} test_PhishingResistantNoneMFA_Incorrect if { PolicyId := "MS.AAD.3.1v1" Output := tests with input as { -"conditional_access_policies": [ - { - "Conditions": { - "Applications": { - "ApplicationFilter": { - "Mode": null, - "Rule": null - }, - "ExcludeApplications": [ - - ], - "IncludeApplications": [ - "All" - ], - "IncludeAuthenticationContextClassReferences": [], - "IncludeUserActions": [] - }, - "ClientAppTypes": [ - "all" - ], - "ClientApplications": { - "ExcludeServicePrincipals": null, - "IncludeServicePrincipals": null, - "ServicePrincipalFilter": { - "Mode": null, - "Rule": null - } - }, - "DeviceStates": { - "ExcludeStates": null, - "IncludeStates": null - }, - "Devices": { - "DeviceFilter": { - "Mode": null, - "Rule": null - }, - "ExcludeDeviceStates": null, - "ExcludeDevices": null, - "IncludeDeviceStates": null, - "IncludeDevices": null - }, - "Locations": { - "ExcludeLocations": null, - "IncludeLocations": null - }, - "Platforms": { - "ExcludePlatforms": null, - "IncludePlatforms": null - }, - "ServicePrincipalRiskLevels": null, - "SignInRiskLevels": [ - - ], - "UserRiskLevels": [ - - ], - "Users": { - "ExcludeGroups": [ - - ], - "ExcludeGuestsOrExternalUsers": { - "ExternalTenants": { - "MembershipKind": null - }, - "GuestOrExternalUserTypes": null - }, - "ExcludeRoles": [ - - ], - "ExcludeUsers": [ - "66b4d5c2-71c9-4644-8728-74e3a8324d81" - ], - "IncludeGroups": [ - - ], - "IncludeGuestsOrExternalUsers": { - "ExternalTenants": { - "MembershipKind": null - }, - "GuestOrExternalUserTypes": null - }, - "IncludeRoles": [ - "62e90394-69f5-4237-9190-012177145e10", - "e8611ab8-c189-46e8-94e1-60213ab1f814", - "fe930be7-5e62-47db-91af-98c3a49a38b1", - "f28a1f50-f6e7-4571-818b-6a12f2af6b6c", - "29232cdf-9323-42fd-ade2-1d097af3e4de", - "8ac3fc64-6eca-42ea-9e69-59f4c7b60eb2", - "9b895d92-2cd3-44c7-9d02-a6ac2d5ea5c3", - "158c047a-c907-4556-b7ef-446551a6b5f7", - "b0f54661-2d74-4c50-afa3-1ec803f12efe" - ], - "IncludeUsers": [] - } - }, - "CreatedDateTime": "/Date(1668112094045)/", - "Description": null, - "DisplayName": "Live - MFA required for Highly Privileged Roles", - "GrantControls": { - "AuthenticationStrength": { - "AllowedCombinations": [], - "CombinationConfigurations": null, - "CreatedDateTime": null, - "Description": null, - "DisplayName": null, - "Id": null, - "ModifiedDateTime": null, - "PolicyType": null, - "RequirementsSatisfied": null - }, - "BuiltInControls": [ - "mfa" - ], - "CustomAuthenticationFactors": [ - - ], - "Operator": "OR", - "TermsOfUse": [ - - ] - }, - "Id": "9e174715-5697-4695-ac39-92f4af6ac2c4", - "ModifiedDateTime": "/Date(1668112265652)/", - "SessionControls": { - "ApplicationEnforcedRestrictions": { - "IsEnabled": null - }, - "CloudAppSecurity": { - "CloudAppSecurityType": null, - "IsEnabled": null - }, - "ContinuousAccessEvaluation": { - "Mode": null - }, - "DisableResilienceDefaults": null, - "PersistentBrowser": { - "IsEnabled": null, - "Mode": null - }, - "SecureSignInSession": { - "IsEnabled": null - }, - "SignInFrequency": { - "AuthenticationType": null, - "FrequencyInterval": null, - "IsEnabled": null, - "Type": null, - "Value": null - } - }, - "State": "enabled", - "AdditionalProperties": { - - } - } -] + "conditional_access_policies" : [ + { + "Conditions" : { + "Applications" : { + "IncludeApplications" : ["All"], + "ExcludeApplications" : [] + }, + "Users" : { + "IncludeUsers" : ["All"], + "ExcludeUsers" : [], + "ExcludeGroups" : [], + "ExcludeRoles" : [] + } + }, + "GrantControls" : { + "AuthenticationStrength" : { + "AllowedCombinations": null + } + }, + "State" : "enabled", + "DisplayName" : "Test name" + } + ] } RuleOutput := [Result | Result = Output[_]; Result.PolicyId == PolicyId] From 98f35a903b1814597b7ad8272b6ec3ef3aa2593f Mon Sep 17 00:00:00 2001 From: Richard Crutchfield Date: Tue, 11 Jul 2023 11:44:59 -0400 Subject: [PATCH 30/33] WIP --- PowerShell/ScubaGear/RequiredVersions.ps1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/PowerShell/ScubaGear/RequiredVersions.ps1 b/PowerShell/ScubaGear/RequiredVersions.ps1 index 43acae8e41..de784385c1 100644 --- a/PowerShell/ScubaGear/RequiredVersions.ps1 +++ b/PowerShell/ScubaGear/RequiredVersions.ps1 @@ -7,7 +7,7 @@ $ModuleList = @( }, @{ ModuleName = 'ExchangeOnlineManagement' # includes Defender - ModuleVersion = [version] '3.2.0' + ModuleVersion = [version] '3.1.0' MaximumVersion = [version] '3.99.99999' }, @{ @@ -38,7 +38,7 @@ $ModuleList = @( @{ ModuleName = 'Microsoft.Graph.Authentication' ModuleVersion = [version] '1.14.0' - MaximumVersion = [version] '1.99.99999' + MaximumVersion = [version] '1.27.0' }, @{ ModuleName = 'Microsoft.Graph.DeviceManagement' #TODO: Verify is needed From b24363996a3ccb3f60a063480f734049b38bdcbb Mon Sep 17 00:00:00 2001 From: Richard Crutchfield Date: Thu, 13 Jul 2023 08:38:09 -0400 Subject: [PATCH 31/33] wip --- Rego/AADConfig.rego | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Rego/AADConfig.rego b/Rego/AADConfig.rego index 3d1a68f1d9..3ee190b73d 100644 --- a/Rego/AADConfig.rego +++ b/Rego/AADConfig.rego @@ -7,6 +7,10 @@ import data.test.utils.IsAllUsers import data.test.utils.IsEmptyContainer import data.test.utils.Contains import data.test.utils.Count +import data.test.utils.IsAllUsers +import data.test.utils.IsEmptyContainer +import data.test.utils.Contains +import data.test.utils.Count ############################################################################# # The report formatting functions below are generic and used throughout AAD # From 39e05364300cee21f12be7046c80640f8fd0d1aa Mon Sep 17 00:00:00 2001 From: Richard Crutchfield Date: Thu, 13 Jul 2023 13:15:20 -0400 Subject: [PATCH 32/33] Update Rego/AADConfig.rego --- Rego/AADConfig.rego | 1 - 1 file changed, 1 deletion(-) diff --git a/Rego/AADConfig.rego b/Rego/AADConfig.rego index 3ee190b73d..e1336e5ccb 100644 --- a/Rego/AADConfig.rego +++ b/Rego/AADConfig.rego @@ -3,7 +3,6 @@ import future.keywords import data.report.utils.NotCheckedDetails import data.report.utils.Format import data.report.utils.ReportDetailsBoolean -import data.test.utils.IsAllUsers import data.test.utils.IsEmptyContainer import data.test.utils.Contains import data.test.utils.Count From 3f34b603a6903fcb022076a34da372ac7f0a02e4 Mon Sep 17 00:00:00 2001 From: Richard Crutchfield Date: Fri, 14 Jul 2023 12:10:17 -0400 Subject: [PATCH 33/33] Adjudicate review comments --- Rego/AADConfig.rego | 10 +++------- Rego/Utils/{TestUtils.rego => PolicyUtils.rego} | 6 +----- 2 files changed, 4 insertions(+), 12 deletions(-) rename Rego/Utils/{TestUtils.rego => PolicyUtils.rego} (85%) diff --git a/Rego/AADConfig.rego b/Rego/AADConfig.rego index e1336e5ccb..ca869addfb 100644 --- a/Rego/AADConfig.rego +++ b/Rego/AADConfig.rego @@ -3,13 +3,9 @@ import future.keywords import data.report.utils.NotCheckedDetails import data.report.utils.Format import data.report.utils.ReportDetailsBoolean -import data.test.utils.IsEmptyContainer -import data.test.utils.Contains -import data.test.utils.Count -import data.test.utils.IsAllUsers -import data.test.utils.IsEmptyContainer -import data.test.utils.Contains -import data.test.utils.Count +import data.policy.utils.IsEmptyContainer +import data.policy.utils.Contains +import data.policy.utils.Count ############################################################################# # The report formatting functions below are generic and used throughout AAD # diff --git a/Rego/Utils/TestUtils.rego b/Rego/Utils/PolicyUtils.rego similarity index 85% rename from Rego/Utils/TestUtils.rego rename to Rego/Utils/PolicyUtils.rego index 4fda5a23a5..aa706c6404 100644 --- a/Rego/Utils/TestUtils.rego +++ b/Rego/Utils/PolicyUtils.rego @@ -1,10 +1,6 @@ -package test.utils +package policy.utils import future.keywords -#IsEmpty(null, _) = true -#IsEmpty(a, b) if not a[b] -#IsEmpty(a, b) if a[b] == "" - IsEmptyContainer(null) = true IsEmptyContainer(container) := true if { Temp := {Item | Item := container[_]}