diff --git a/CHANGELOG.md b/CHANGELOG.md index 732368c5..6dd22c61 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## v1.1.0 [2024-10-30] + +_What's new?_ + +- Added CIS v3.0.0 benchmark (`powerpipe benchmark run azure_compliance.benchmark.cis_v300`). ([#282](https://github.com/turbot/steampipe-mod-azure-compliance/pull/282)) + ## v1.0.1 [2024-10-24] _Bug fixes_ diff --git a/README.md b/README.md index b9431bc1..69e42ee9 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,6 @@ # Azure Compliance Mod for Powerpipe -200+ checks covering industry defined security best practices for Azure. Includes full support for `CIS v1.3`,`CIS v1.4`,`CIS v1.5`,`CIS v2.0`,`CIS v2.1`,`HIPAA HITRUST 9.2`,`NIST SP 800-53`,` NIST SP 800-171` and `PCI DSS v3.2.1` compliance benchmarks across all your Azure subscriptions. - -**Includes full support for the CIS v1.3 Azure Benchmarks**. +200+ checks covering industry defined security best practices for Azure. Includes full support for `CIS v1.3`,`CIS v1.4`,`CIS v1.5`,`CIS v2.0`,`CIS v2.1`,`CIS v3.0`,`HIPAA HITRUST 9.2`,`NIST SP 800-53`,` NIST SP 800-171` and `PCI DSS v3.2.1` compliance benchmarks across all your Azure subscriptions. Run checks in a dashboard: ![image](https://raw.githubusercontent.com/turbot/steampipe-mod-azure-compliance/main/docs/azure_compliance_dashboard.png) @@ -75,7 +73,7 @@ powerpipe benchmark list Run a benchmark: ```sh -powerpipe benchmark run azure_compliance.benchmark.cis_v200 +powerpipe benchmark run azure_compliance.benchmark.cis_v300 ``` Different output formats are also available, for more information please see @@ -95,7 +93,7 @@ vi powerpipe.ppvars Alternatively you can pass variables on the command line: ```sh -powerpipe benchmark run azure_compliance.benchmark.cis_v200 --var 'tag_dimensions=["Environment", "Owner"]' +powerpipe benchmark run azure_compliance.benchmark.cis_v300 --var 'tag_dimensions=["Environment", "Owner"]' ``` Or through environment variables: @@ -103,7 +101,7 @@ Or through environment variables: ```sh export PP_VAR_common_dimensions='["subscription_id", "connection_name", "resource_group"]' export PP_VAR_tag_dimensions='["Environment", "Owner"]' -powerpipe benchmark run azure_compliance.benchmark.cis_v200 +powerpipe benchmark run azure_compliance.benchmark.cis_v300 ``` ## Open Source & Contributing diff --git a/all_controls/compute.pp b/all_controls/compute.pp index e63d42d4..937a5862 100644 --- a/all_controls/compute.pp +++ b/all_controls/compute.pp @@ -11,6 +11,8 @@ control.arc_compute_machine_linux_log_analytics_agent_installed, control.arc_compute_machine_windows_log_analytics_agent_installed, control.compute_disk_access_uses_private_link, + control.compute_disk_data_access_auth_mode_enabled, + control.compute_disk_public_access_disabled, control.compute_disk_unattached_encrypted_with_cmk, control.compute_os_and_data_disk_encrypted_with_cmk, control.compute_os_and_data_disk_encrypted_with_cmk_and_platform_managed, @@ -47,8 +49,8 @@ control.compute_vm_scale_set_boot_diagnostics_enabled, control.compute_vm_scale_set_log_analytics_agent_installed, control.compute_vm_scale_set_logging_enabled, - control.compute_vm_scale_set_uses_managed_disks, control.compute_vm_scale_set_ssh_key_authentication_linux, + control.compute_vm_scale_set_uses_managed_disks, control.compute_vm_secure_communication_protocols_configured, control.compute_vm_ssh_key_authentication_linux, control.compute_vm_system_updates_installed, diff --git a/cis_v300/cis.pp b/cis_v300/cis.pp new file mode 100644 index 00000000..84e60abd --- /dev/null +++ b/cis_v300/cis.pp @@ -0,0 +1,28 @@ +locals { + cis_v300_common_tags = merge(local.azure_compliance_common_tags, { + cis = "true" + cis_version = "v3.0.0" + }) +} + +benchmark "cis_v300" { + title = "CIS v3.0.0" + description = "The CIS Microsoft Azure Foundations Security Benchmark provides prescriptive guidance for establishing a secure baseline configuration for Microsoft Azure." + documentation = file("./cis_v300/docs/cis_overview.md") + + children = [ + benchmark.cis_v300_2, + benchmark.cis_v300_3, + benchmark.cis_v300_4, + benchmark.cis_v300_5, + benchmark.cis_v300_6, + benchmark.cis_v300_7, + benchmark.cis_v300_8, + benchmark.cis_v300_9, + benchmark.cis_v300_10 + ] + + tags = merge(local.cis_v300_common_tags, { + type = "Benchmark" + }) +} diff --git a/cis_v300/docs/cis_overview.md b/cis_v300/docs/cis_overview.md new file mode 100644 index 00000000..dae25e4b --- /dev/null +++ b/cis_v300/docs/cis_overview.md @@ -0,0 +1,22 @@ +To obtain the latest version of the official guide, please visit http://benchmarks.cisecurity.org. + +## Overview + +The CIS Microsoft Azure Foundations Security Benchmark provides prescriptive guidance for establishing a secure baseline configuration for Microsoft Azure. + +## Profiles + +### Level 1 + +Items in this profile intend to: +- be practical and prudent; +- provide security focused best practice hardening of a technology; and +- limit impact to the utility of the technology beyond acceptable means. + +### Level 2 + +This profile extends the "Level 1" profile. Items in this profile exhibit one or more of the following characteristics: +- are intended for environments or use cases where security is more critical than manageability and usability +- acts as defense in depth measure +- may impact the utility or performance of the technology +- may include additional licensing, cost, or addition of third party software. diff --git a/cis_v300/docs/cis_v300_10.md b/cis_v300/docs/cis_v300_10.md new file mode 100644 index 00000000..3b0c8532 --- /dev/null +++ b/cis_v300/docs/cis_v300_10.md @@ -0,0 +1,3 @@ +## Overview + +This section covers security recommendations for Miscellaneous. diff --git a/cis_v300/docs/cis_v300_10_1.md b/cis_v300/docs/cis_v300_10_1.md new file mode 100644 index 00000000..2ace7e70 --- /dev/null +++ b/cis_v300/docs/cis_v300_10_1.md @@ -0,0 +1,37 @@ +## Description + +Resource Manager Locks provide a way for administrators to lock down Azure resources to prevent deletion of, or modifications to, a resource. These locks sit outside of the Role Based Access Controls (RBAC) hierarchy and, when applied, will place restrictions on the resource for all users. These locks are very useful when there is an important resource in a subscription that users should not be able to delete or change. Locks can help prevent accidental and malicious changes or deletion. + +As an administrator, it may be necessary to lock a subscription, resource group, or resource to prevent other users in the organization from accidentally deleting or modifying critical resources. The lock level can be set to to `CanNotDelete` or `ReadOnly` to achieve this purpose. + +- `CanNotDelete` means authorized users can still read and modify a resource, but they cannot delete the resource. + +- `ReadOnly` means authorized users can read a resource, but they cannot delete or update the resource. Applying this lock is similar to restricting all authorized users to the permissions granted by the Reader role. + +## Remediation + +### From Azure Portal + +1. Navigate to the specific Azure Resource or Resource Group. +2. For each mission critical resource, click on `Locks`. +3. Click `Add`. +4. Give the lock a name and a description, then select the type, `Read-only` or `Delete` as appropriate. +5. Click OK. + +### From Azure CLI + +To lock a resource, provide the name of the resource, its resource type, and its resource group name. + +```bash +az lock create --name --lock-type --resource-group --resource-name --resource-type +``` + +### From Powershell + +```bash +Get-AzResourceLock -ResourceName -ResourceType -ResourceGroupName -Locktype +``` + +### Default Value + +By default, no locks are set. diff --git a/cis_v300/docs/cis_v300_2.md b/cis_v300/docs/cis_v300_2.md new file mode 100644 index 00000000..71fe06e3 --- /dev/null +++ b/cis_v300/docs/cis_v300_2.md @@ -0,0 +1,9 @@ +## Overview + +This section covers security best practice recommendations for products in the Azure Identity services category. + +Azure Product Category Page: https://azure.microsoft.com/en-us/products/category/identity + +Many of the recommendations from this section are marked as "Manual" while the existing Azure CLI and Azure AD PowerShell support through the Azure AD Graph are being deprecated. It is now recommended to use the new Microsoft Graph PowerShell in replacement of Azure AD Graph for PowerShell and API level access. From a security posture standpoint, these recommendations are still very important and should not be discounted because they are "Manual." As automation capability is developed for this Benchmark, the related recommendations will be updated with the respective audit and remediation steps and changed to an "automated" assessment status. + +If any problems are encountered running Azure CLI or PowerShell methodologies, please refer to the Introduction section of this Benchmark where you will find additional detail on permission and required cmdlets. diff --git a/cis_v300/docs/cis_v300_2_1.md b/cis_v300/docs/cis_v300_2_1.md new file mode 100644 index 00000000..cb437424 --- /dev/null +++ b/cis_v300/docs/cis_v300_2_1.md @@ -0,0 +1,5 @@ +## Overview + +**IMPORTANT:** The Azure "Security Defaults" recommendations represent an entry-level set of recommendations (such as Multi-Factor Authentication) which will be relevant to organizations and tenants that are either just starting to use Azure, or are only utilizing a bare minimum feature set, and rely on the free license tier of Microsoft Entra ID. Security Defaults recommendations are intended to ensure that these use cases are still capable of establishing a strong baseline of secure configuration. + +**If your subscription is licensed to use Microsoft Entra ID P1 or P2, it is strongly recommended that the "Security Defaults" section (this section and the recommendations therein) be bypassed in favor of the use of "Conditional Access."** diff --git a/cis_v300/docs/cis_v300_2_10.md b/cis_v300/docs/cis_v300_2_10.md new file mode 100644 index 00000000..6695c1af --- /dev/null +++ b/cis_v300/docs/cis_v300_2_10.md @@ -0,0 +1,21 @@ +## Description + +Ensure that users are notified on their primary and alternate emails on password resets. + +User notification on password reset is a proactive way of confirming password reset activity. It helps the user to recognize unauthorized password reset activities. + +## Remediation + +### From Azure Portal + +1. From Azure Home select the Portal Menu. +2. Select `Microsoft Entra ID`. +3. Under `Manage`, select `Users`. +4. Under `Manage`, select `Password reset`. +5. Under `Manage`, select `Notifications`. +6. Set `Notify users on password resets?` to `Yes`. +7. Click `Save`. + +### Default Value + +By default, `Notify users on password resets?` is set to "Yes". diff --git a/cis_v300/docs/cis_v300_2_11.md b/cis_v300/docs/cis_v300_2_11.md new file mode 100644 index 00000000..bba0253d --- /dev/null +++ b/cis_v300/docs/cis_v300_2_11.md @@ -0,0 +1,21 @@ +## Description + +Ensure that all Global Administrators are notified if any other administrator resets their password. + +Administrator accounts are sensitive. Any password reset activity notification, when sent to all Administrators, ensures that all Global Administrators can passively confirm if such a reset is a common pattern within their group. For example, if all Administrators change their password every 30 days, any password reset activity before that may require administrator(s) to evaluate any unusual activity and confirm its origin. + +## Remediation + +### From Azure Portal + +1. From Azure Home select the Portal Menu. +2. Select `Microsoft Entra ID`. +3. Under `Manage`, select `Users`. +4. Under `Manage`, select `Password reset`. +5. Under `Manage`, select `Notifications`. +6. Set `Notify all admins when other admins reset their password?` to `Yes`. +7. Click `Save`. + +### Default Value + +By default, `Notify all admins when other admins reset their password?` is set to "No". diff --git a/cis_v300/docs/cis_v300_2_12.md b/cis_v300/docs/cis_v300_2_12.md new file mode 100644 index 00000000..491b96fe --- /dev/null +++ b/cis_v300/docs/cis_v300_2_12.md @@ -0,0 +1,21 @@ +## Description + +Require administrators to provide consent for applications before use. + +If Microsoft Entra ID is running as an identity provider for third-party applications, permissions and consent should be limited to administrators or pre-approved. Malicious applications may attempt to exfiltrate data or abuse privileged user accounts. + +## Remediation + +### From Azure Portal + +1. From Azure Home select the Portal Menu. +2. Select `Microsoft Entra ID`. +3. Under `Manage`, select `Enterprise applications`. +4. Under `Security`, select `Consent and permissions`. +5. Under `Manage`, select `User consent settings`. +6. Set `User consent for applications` to `Do not allow user consent`. +7. Click `Save`. + +### Default Value + +By default, `Users consent for applications` is set to `Allow user consent for apps`. diff --git a/cis_v300/docs/cis_v300_2_13.md b/cis_v300/docs/cis_v300_2_13.md new file mode 100644 index 00000000..27e987d0 --- /dev/null +++ b/cis_v300/docs/cis_v300_2_13.md @@ -0,0 +1,21 @@ +## Description + +Allow users to provide consent for selected permissions when a request is coming from a verified publisher. + +If Microsoft Entra ID is running as an identity provider for third-party applications, permissions and consent should be limited to administrators or pre-approved. Malicious applications may attempt to exfiltrate data or abuse privileged user accounts. + +## Remediation + +### From Azure Portal + +1. From Azure Home select the Portal Menu. +2. Select `Microsoft Entra ID`. +3. Under `Manage`, select `Enterprise applications`. +4. Under `Security`, select `Consent and permissions`. +5. Under `Manage`, select `User consent settings`. +6. Under `User consent for applications`, select `Allow user consent for apps from verified publishers, for selected permissions`. +7. Click `Save`. + +### Default Value + +By default, `User consent for applications` is set to `Allow user consent for apps`. diff --git a/cis_v300/docs/cis_v300_2_14.md b/cis_v300/docs/cis_v300_2_14.md new file mode 100644 index 00000000..887273f5 --- /dev/null +++ b/cis_v300/docs/cis_v300_2_14.md @@ -0,0 +1,27 @@ +## Description + +Require administrators or appropriately delegated users to register third-party applications. + +It is recommended to only allow an administrator to register custom-developed applications. This ensures that the application undergoes a formal security review and approval process prior to exposing Microsoft Entra ID data. Certain users like developers or other high-request users may also be delegated permissions to prevent them from waiting on an administrative user. Your organization should review your policies and decide your needs. + +## Remediation + +### From Azure Portal + +1. From Azure Home select the Portal Menu. +2. Select `Microsoft Entra ID`. +3. Under `Manage`, select `Users`. +4. Under `Manage`, select `User settings`. +5. Set `Users can register applications` to `No`. +6. Click `Save`. + +### From PowerShell + +```bash +$param = @{ AllowedToCreateApps = "$false" } +Update-MgPolicyAuthorizationPolicy -DefaultUserRolePermissions $param +``` + +### Default Value + +By default, `Users can register applications` is set to "Yes". diff --git a/cis_v300/docs/cis_v300_2_15.md b/cis_v300/docs/cis_v300_2_15.md new file mode 100644 index 00000000..bf028e94 --- /dev/null +++ b/cis_v300/docs/cis_v300_2_15.md @@ -0,0 +1,42 @@ +## Description + +Limit guest user permissions. + +Limiting guest access ensures that guest accounts do not have permission for certain directory tasks, such as enumerating users, groups or other directory resources, and cannot be assigned to administrative roles in your directory. Guest access has three levels of restriction. + +1. Guest users have the same access as members (most inclusive), +2. Guest users have limited access to properties and memberships of directory objects (default value), +3. Guest user access is restricted to properties and memberships of their own directory objects (most restrictive). + +The recommended option is the 3rd, most restrictive: "Guest user access is restricted to their own directory object". + +## Remediation + +### From Azure Portal + +1. From Azure Home select the Portal Menu. +2. Select `Microsoft Entra ID`. +3. Under `Manage`, select `External Identities`. +4. Select `External collaboration settings`. +5. Under `Guest user access`, set `Guest user access restrictions` to `Guest user access is restricted to properties and memberships of their own directory objects`. +6. Click `Save`. + +### From PowerShell + +1. Enter the following to update the policy ID: + +```bash +Update-MgPolicyAuthorizationPolicy -GuestUserRoleId "2af84b1e-32c8-42b7-82bc-daa82404023b" +``` + +2. Check the GuestUserRoleId again: + +```bash +(Get-MgPolicyAuthorizationPolicy).GuestUserRoleId +``` + +3. Ensure that the GuestUserRoleId is equal to the earlier entered value of `2af84b1e-32c8-42b7-82bc-daa82404023b`. + +### Default Value + +By default, `Guest user access restrictions` is set to `Guest users have limited access to properties and memberships of directory objects`. diff --git a/cis_v300/docs/cis_v300_2_16.md b/cis_v300/docs/cis_v300_2_16.md new file mode 100644 index 00000000..577f071a --- /dev/null +++ b/cis_v300/docs/cis_v300_2_16.md @@ -0,0 +1,31 @@ +## Description + +Restrict invitations to users with specific administrative roles only. + +Restricting invitations to users with specific administrator roles ensures that only authorized accounts have access to cloud resources. This helps to maintain "Need to Know" permissions and prevents inadvertent access to data. + +By default the setting `Guest invite restrictions` is set to `Anyone in the organization can invite guest users including guests and non-admins`. This would allow anyone within the organization to invite guests and non-admins to the tenant, posing a security risk. + +## Remediation + +### From Azure Portal + +1. From Azure Home select the Portal Menu. +2. Select `Microsoft Entra ID`. +3. Under `Manage`, select `External Identities`. +4. Select `External collaboration settings`. +5. Under `Guest invite settings`, set `Guest invite restrictions`, to `Only users assigned to specific admin roles can invite guest users`. +6. Click `Save`. + +### From Powershell + +Enter the following: + +```bash +Connect-MgGraph +Update-MgPolicyAuthorizationPolicy -AllowInvitesFrom "adminsAndGuestInviters" +``` + +### Default Value + +By default, `Guest invite restrictions` is set to `Anyone in the organization can invite guest users including guests and non-admins`. diff --git a/cis_v300/docs/cis_v300_2_17.md b/cis_v300/docs/cis_v300_2_17.md new file mode 100644 index 00000000..3f076a21 --- /dev/null +++ b/cis_v300/docs/cis_v300_2_17.md @@ -0,0 +1,22 @@ +## Description + +Restrict access to the Microsoft Entra ID administration center to administrators only. + +**NOTE**: This only affects access to the Entra ID administrator's web portal. This setting does not prohibit privileged users from using other methods such as Rest API or Powershell to obtain sensitive information from Microsoft Entra ID. + +The Microsoft Entra ID administrative center has sensitive data and permission settings. All non-administrators should be prohibited from accessing any Microsoft Entra ID data in the administration center to avoid exposure. + +## Remediation + +### From Azure Portal + +1. From Azure Home select the Portal Menu. +2. Select `Microsoft Entra ID`. +3. Under `Manage`, select `Users`. +4. Under `Manage`, select `User settings`. +5. Under `Administration centre`, set `Restrict access to Microsoft Entra admin center` to `Yes`. +6. Click `Save`. + +### Default Value + +By default, `Restrict access to Microsoft Entra admin center` is set to `No`. diff --git a/cis_v300/docs/cis_v300_2_18.md b/cis_v300/docs/cis_v300_2_18.md new file mode 100644 index 00000000..33d8916f --- /dev/null +++ b/cis_v300/docs/cis_v300_2_18.md @@ -0,0 +1,20 @@ +## Description + +Restrict access to group web interface in the Access Panel portal. + +Self-service group management enables users to create and manage security groups or Office 365 groups in Microsoft Entra ID. Unless a business requires this day-to-day delegation for some users, self-service group management should be disabled. Any user can access the Access Panel, where they can reset their passwords, view their information, etc. By default, users are also allowed to access the Group feature, which shows groups, members, related resources (SharePoint URL, Group email address, Yammer URL, and Teams URL). By setting this feature to 'Yes', users will no longer have access to the web interface, but still have access to the data using the API. This is useful to prevent non-technical users from enumerating groups-related information, but technical users will still be able to access this information using APIs. + +## Remediation + +### From Azure Portal + +1. From Azure Home select the Portal Menu. +2. Select `Microsoft Entra ID`. +3. Under `Manage`, select `Groups`. +4. Under `Settings`, select `General`. +5. Under `Self Service Group Management`, set `Restrict user ability to access groups features in My Groups` to `Yes`. +6. Click `Save`. + +### Default Value + +By default, `Restrict user ability to access groups features in the Access Pane` is set to `No`. diff --git a/cis_v300/docs/cis_v300_2_19.md b/cis_v300/docs/cis_v300_2_19.md new file mode 100644 index 00000000..f491ff8f --- /dev/null +++ b/cis_v300/docs/cis_v300_2_19.md @@ -0,0 +1,20 @@ +## Description + +Restrict security group creation to administrators only. + +When creating security groups is enabled, all users in the directory are allowed to create new security groups and add members to those groups. Unless a business requires this day-to-day delegation, security group creation should be restricted to administrators only. + +## Remediation + +### From Azure Portal + +1. From Azure Home select the Portal Menu. +2. Select `Microsoft Entra ID`. +3. Under `Manage`, select `Groups`. +4. Under `Settings`, select `General`. +5. Under `Security Groups`, set `Users can create security groups in Azure portals, API or PowerShell` to `No`. +6. Click `Save`. + +### Default Value + +By default, `Users can create security groups in Azure portals, API or PowerShell` is set to `Yes`. diff --git a/cis_v300/docs/cis_v300_2_1_1.md b/cis_v300/docs/cis_v300_2_1_1.md new file mode 100644 index 00000000..f4382736 --- /dev/null +++ b/cis_v300/docs/cis_v300_2_1_1.md @@ -0,0 +1,31 @@ +## Description + +[**IMPORTANT - Please read the section overview:** If your organization pays for Microsoft Entra ID licensing (included in Microsoft 365 E3, E5, or F5, and EM&S E3 or E5 licenses) and **CAN** use Conditional Access, ignore the recommendations in this section and proceed to the Conditional Access section.] + +Security defaults in Microsoft Entra ID make it easier to be secure and help protect your organization. Security defaults contain preconfigured security settings for common attacks. + +Security defaults is available to everyone. The goal is to ensure that all organizations have a basic level of security enabled at no extra cost. You may turn on security defaults in the Azure portal. + +Security defaults provide secure default settings that we manage on behalf of organizations to keep customers safe until they are ready to manage their own identity security settings. + +For example, doing the following: + +- Requiring all users and admins to register for MFA. +- Challenging users with MFA - when necessary, based on factors such as location, device, role, and task. +- Disabling authentication from legacy authentication clients, which can’t do MFA. + +## Remediation + +### From Azure Portal + +To enable security defaults in your directory: + +1. From Azure Home select the Portal Menu. +2. Browse to `Microsoft Entra ID` > `Properties`. +3. Select `Manage security defaults`. +4. Under `Security defaults`, select `Enabled (recommended)`. +5. Select `Save`. + +### Default Value + +If your tenant was created on or after October 22, 2019, security defaults may already be enabled in your tenant. diff --git a/cis_v300/docs/cis_v300_2_1_2.md b/cis_v300/docs/cis_v300_2_1_2.md new file mode 100644 index 00000000..2261a59c --- /dev/null +++ b/cis_v300/docs/cis_v300_2_1_2.md @@ -0,0 +1,43 @@ +## Description + +[**IMPORTANT - Please read the section overview:** If your organization pays for Microsoft Entra ID licensing (included in Microsoft 365 E3, E5, or F5, and EM&S E3 or E5 licenses) and **CAN** use Conditional Access, ignore the recommendations in this section and proceed to the Conditional Access section.] + +Enable multi-factor authentication for all roles, groups, and users that have write access or permissions to Azure resources. These include custom created objects or built-in roles such as; +- Service Co-Administrators +- Subscription Owners +- Contributors + +Multi-factor authentication requires an individual to present a minimum of two separate forms of authentication before access is granted. Multi-factor authentication provides additional assurance that the individual attempting to gain access is who they claim to be. With multi-factor authentication, an attacker would need to compromise at least two different authentication mechanisms, increasing the difficulty of compromise and thus reducing the risk. + +## Remediation + +### From Azure Portal + +1. From Azure Home select the Portal Menu. +2. Select `Microsoft Entra ID` blade. +3. Under `Manage`, click `Roles and administrators`. +4. Take note of all users with the role `Service Co-Administrators`, `Owners` or `Contributors`. +5. Return to the `Overview`. +6. Under `Manage`, click `Users`. +7. Click on the `Per-User MFA` button in the top row menu. +8. Check the box next to each noted user. +9. Click `Enable MFA`. +10. Click `Enable`. + +**Other Options within Azure Portal** + +Follow Microsoft Azure documentation and enable multi-factor authentication in your environment. + +[https://docs.microsoft.com/en-us/azure/active-directory/authentication/tutorial-enable-azure-mfa](https://docs.microsoft.com/en-us/azure/active-directory/authentication/tutorial-enable-azure-mfa) + +Enabling and configuring MFA with conditional access policy is a multi-step process. Here are some additional resources on the process within Entra ID to enable multi-factor authentication for users within your subscriptions with conditional access policy. + +[https://docs.microsoft.com/en-us/azure/active-directory/conditional-access/howto-conditional-access-policy-admin-mfa](https://docs.microsoft.com/en-us/azure/active-directory/conditional-access/howto-conditional-access-policy-admin-mfa) + +[https://docs.microsoft.com/en-us/azure/active-directory/authentication/howto-mfa-getstarted#enable-multi-factor-authentication-with-conditional-access](https://docs.microsoft.com/en-us/azure/active-directory/authentication/howto-mfa-getstarted#enable-multi-factor-authentication-with-conditional-access) + +[https://docs.microsoft.com/en-us/azure/active-directory/authentication/howto-mfa-mfasettings](https://docs.microsoft.com/en-us/azure/active-directory/authentication/howto-mfa-mfasettings) + +### Default Value + +By default, multi-factor authentication is disabled for all users. diff --git a/cis_v300/docs/cis_v300_2_1_3.md b/cis_v300/docs/cis_v300_2_1_3.md new file mode 100644 index 00000000..36b22d38 --- /dev/null +++ b/cis_v300/docs/cis_v300_2_1_3.md @@ -0,0 +1,37 @@ +## Description + +[**IMPORTANT - Please read the section overview:** If your organization pays for Microsoft Entra ID licensing (included in Microsoft 365 E3, E5, or F5, and EM&S E3 or E5 licenses) and **CAN** use Conditional Access, ignore the recommendations in this section and proceed to the Conditional Access section.] + +Enable multi-factor authentication for all non-privileged users. + +Multi-factor authentication requires an individual to present a minimum of two separate forms of authentication before access is granted. Multi-factor authentication provides additional assurance that the individual attempting to gain access is who they claim to be. With multi-factor authentication, an attacker would need to compromise at least two different authentication mechanisms, increasing the difficulty of compromise and thus reducing the risk. + +## Remediation + +### From Azure Portal + +1. From Azure Home select the Portal Menu. +2. Select `Microsoft Entra ID` blade. +3. Under `Manage`, click `Users`. +4. Click on the `Per-User MFA` button in the top row menu. +5. Check the box next to each user. +6. Click `Enable MFA`. +7. Click `Enable`. + +**Other Options within Azure Portal** + +Follow Microsoft Azure documentation and enable multi-factor authentication in your environment. + +[https://docs.microsoft.com/en-us/azure/active-directory/authentication/tutorial-enable-azure-mfa](https://docs.microsoft.com/en-us/azure/active-directory/authentication/tutorial-enable-azure-mfa) + +Enabling and configuring MFA is a multi-step process. Here are some additional resources on the process within Microsoft Entra ID: + +[https://learn.microsoft.com/en-us/entra/identity/conditional-access/howto-conditional-access-policy-admin-mfa](https://learn.microsoft.com/en-us/entra/identity/conditional-access/howto-conditional-access-policy-admin-mfa) + +[https://learn.microsoft.com/en-us/entra/identity/authentication/howto-mfa-getstarted#enable-multi-factor-authentication-with-conditional-access](https://learn.microsoft.com/en-us/entra/identity/authentication/howto-mfa-getstarted#enable-multi-factor-authentication-with-conditional-access) + +[https://learn.microsoft.com/en-us/entra/identity/authentication/howto-mfa-mfasettings](https://learn.microsoft.com/en-us/entra/identity/authentication/howto-mfa-mfasettings) + +### Default Value + +By default, multi-factor authentication is disabled for all users. diff --git a/cis_v300/docs/cis_v300_2_1_4.md b/cis_v300/docs/cis_v300_2_1_4.md new file mode 100644 index 00000000..4e9c09c7 --- /dev/null +++ b/cis_v300/docs/cis_v300_2_1_4.md @@ -0,0 +1,23 @@ +## Description + +[**IMPORTANT - Please read the section overview:** If your organization pays for Microsoft Entra ID licensing (included in Microsoft 365 E3, E5, or F5, and EM&S E3 or E5 licenses) and **CAN** use Conditional Access, ignore the recommendations in this section and proceed to the Conditional Access section.] + +Do not allow users to remember multi-factor authentication on devices. + +Remembering Multi-Factor Authentication (MFA) for devices and browsers allows users to have the option to bypass MFA for a set number of days after performing a successful sign-in using MFA. This can enhance usability by minimizing the number of times a user may need to perform two-step verification on the same device. However, if an account or device is compromised, remembering MFA for trusted devices may affect security. Hence, it is recommended that users not be allowed to bypass MFA. + +## Remediation + +### From Azure Portal + +1. From Azure Home select the Portal Menu. +2. Select `Microsoft Entra ID`. +3. Under `Manage`, click `Users`. +4. Click the `Per-user MFA` button on the top bar. +5. Click on `Service settings`. +6. Uncheck the box next to `Allow users to remember multi-factor authentication on devices they trust`. +7. Click `Save`. + +### Default Value + +By default, `Allow users to remember multi-factor authentication on devices they trust` is disabled. diff --git a/cis_v300/docs/cis_v300_2_2.md b/cis_v300/docs/cis_v300_2_2.md new file mode 100644 index 00000000..7f5d130f --- /dev/null +++ b/cis_v300/docs/cis_v300_2_2.md @@ -0,0 +1,11 @@ +## Overview + +For most Azure tenants, and certainly for organizations with a significant use of Microsoft Entra ID, Conditional Access policies are recommended and preferred. To use Conditional Access Policies, a licensing plan is required, and **Security Defaults must be disabled**. Because of the licensing requirement, all Conditional Access policies are assigned a profile of "Level 2." + +Conditional Access requires one of the following plans: + +- Microsoft Entra ID P1 or P2 +- Microsoft 365 Business Premium +- Microsoft 365 E3 or E5 +- Microsoft 365 F1, F3, F5 Security and F5 Security + Compliance +- Enterprise Mobility & Security E3 or E5. diff --git a/cis_v300/docs/cis_v300_2_20.md b/cis_v300/docs/cis_v300_2_20.md new file mode 100644 index 00000000..4f67439f --- /dev/null +++ b/cis_v300/docs/cis_v300_2_20.md @@ -0,0 +1,20 @@ +## Description + +Restrict security group management to administrators only. + +Restricting security group management to administrators only prohibits users from making changes to security groups. This ensures that security groups are appropriately managed and their management is not delegated to non-administrators. + +## Remediation + +### From Azure Portal + +1. From Azure Home select the Portal Menu. +2. Select `Microsoft Entra ID`. +3. Under `Manage`, select `Groups`. +4. Under `Settings`, select `General`. +5. Under `Self Service Group Management`, set `Owners can manage group membership requests in My Groups` to `No`. +6. Click `Save`. + +### Default Value + +By default, `Owners can manage group membership requests in My Groups` is set to `No`. diff --git a/cis_v300/docs/cis_v300_2_21.md b/cis_v300/docs/cis_v300_2_21.md new file mode 100644 index 00000000..6b6859e1 --- /dev/null +++ b/cis_v300/docs/cis_v300_2_21.md @@ -0,0 +1,20 @@ +## Description + +Restrict Microsoft 365 group creation to administrators only. + +Restricting Microsoft 365 group creation to administrators only ensures that creation of Microsoft 365 groups is controlled by the administrator. Appropriate groups should be created and managed by the administrator and group creation rights should not be delegated to any other user. + +## Remediation + +### From Azure Portal + +1. From Azure Home select the Portal Menu. +2. Select `Microsoft Entra ID`. +3. Under `Manage`, select `Groups`. +4. Under `Settings`, select `General`. +5. Under `Microsoft 365 Groups`, set `Users can create Microsoft 365 groups in Azure portals, API or PowerShell` to `No`. +6. Click `Save`. + +### Default Value + +By default, `Users can create Microsoft 365 groups in Azure portals, API or PowerShell` is set to `Yes`. diff --git a/cis_v300/docs/cis_v300_2_22.md b/cis_v300/docs/cis_v300_2_22.md new file mode 100644 index 00000000..1d7d3f28 --- /dev/null +++ b/cis_v300/docs/cis_v300_2_22.md @@ -0,0 +1,22 @@ +## Description + +**NOTE:** This recommendation is only relevant if your subscription is using Per-User MFA. If your organization is licensed to use Conditional Access, the preferred method of requiring MFA to join devices to Entra ID is to use a Conditional Access policy (see additional information below for link). + +Joining or registering devices to Microsoft Entra ID should require multi-factor authentication. + +Multi-factor authentication is recommended when adding devices to Microsoft Entra ID. When set to `Yes`, users who are adding devices from the internet must first use the second method of authentication before their device is successfully added to the directory. This ensures that rogue devices are not added to the domain using a compromised user account. + +## Remediation + +### From Azure Portal + +1. From Azure Home select the Portal Menu. +2. Select `Microsoft Entra ID`. +3. Under `Manage`, select `Devices`. +4. Under `Manage`, select `Device settings`. +5. Under `Microsoft Entra join and registration settings`, set `Require Multifactor Authentication to register or join devices with Microsoft Entra` to `Yes`. +6. Click `Save`. + +### Default Value + +By default, `Require Multifactor Authentication to register or join devices with Microsoft Entra` is set to `No`. diff --git a/cis_v300/docs/cis_v300_2_23.md b/cis_v300/docs/cis_v300_2_23.md new file mode 100644 index 00000000..8fd2fcf3 --- /dev/null +++ b/cis_v300/docs/cis_v300_2_23.md @@ -0,0 +1,42 @@ +## Description + +The principle of least privilege should be followed and only necessary privileges should be assigned instead of allowing full administrative access. + +Custom roles in Azure with administrative access can obfuscate the permissions granted and introduce complexity and blind spots to the management of privileged identities. For less mature security programs without regular identity audits, the creation of Custom roles should be avoided entirely. For more mature security programs with regular identity audits, Custom Roles should be audited for use and assignment, used minimally, and the principle of least privilege should be observed when granting permissions + +## Remediation + +### From Azure Portal + +1. From Azure Home select the Portal Menu. +2. Select `Subscriptions`. +3. Select a subscription. +4. Select `Access control (IAM)`. +5. Select `Roles`. +6. Click `Type` and select `Custom role` from the drop-down menu. +7. Check the box next to each role which grants subscription administrator privileges. +8. Select `Delete`. +9. Select `Yes`. + +### From Azure CLI + +List custom roles: + +```bash +az role definition list --custom-role-only True +``` + +Check for entries with `assignableScope` of the `subscription`, and an action of `*`. + +To remove a violating role: + +```bash +az role definition delete --name +``` + +**Note** that any role assignments must be removed before a custom role can be deleted. +Ensure impact is assessed before deleting a custom role granting subscription administrator privileges. + +### Default Value + +By default, no custom owner roles are created. diff --git a/cis_v300/docs/cis_v300_2_24.md b/cis_v300/docs/cis_v300_2_24.md new file mode 100644 index 00000000..b746147f --- /dev/null +++ b/cis_v300/docs/cis_v300_2_24.md @@ -0,0 +1,50 @@ +## Description + +Resource locking is a powerful protection mechanism that can prevent inadvertent modification/deletion of resources within Azure subscriptions/Resource Groups and is a recommended NIST configuration. + +Given the resource lock functionality is outside of standard Role Based Access Control(RBAC), it would be prudent to create a resource lock administrator role to prevent inadvertent unlocking of resources. + +## Remediation + +### From Azure Portal + +1. In the Azure portal, open a subscription or resource group where you want the custom role to be assigned. +2. Select `Access control (IAM)`. +3. Click `Add`. +4. Select `Add custom role`. +5. In the `Custom role name` field enter `Resource Lock Administrator`. +6. In the Description field enter `Can Administer Resource Locks`. +7. For Baseline permissions select `Start from scratch`. +8. Select `Next`. +9. In the Permissions tab select `Add permissions`. +10. In the Search for a permission box, type in `Microsoft.Authorization/locks` to search for permissions. +11. Click on the result. +12. Check the box next to `Permission`. +13. Select `Add`. +14. Select `Review + create`. +15. Select `Create`. +16. Assign the newly created role to the appropriate user. + +### From PowerShell: + +Below is a power shell definition for a resource lock administrator role created at an Azure Management group level + +```bash +Import-Module Az.Accounts +Connect-AzAccount + +$role = Get-AzRoleDefinition "User Access Administrator" +$role.Id = $null +$role.Name = "Resource Lock Administrator" +$role.Description = "Can Administer Resource Locks" +$role.Actions.Clear() +$role.Actions.Add("Microsoft.Authorization/locks/*") +$role.AssignableScopes.Clear() + +* Scope at the Management group level Management group + +$role.AssignableScopes.Add("/providers/Microsoft.Management/managementGroups/MG-Name") + +New-AzRoleDefinition -Role $role +Get-AzureRmRoleDefinition "Resource Lock Administrator" +``` diff --git a/cis_v300/docs/cis_v300_2_25.md b/cis_v300/docs/cis_v300_2_25.md new file mode 100644 index 00000000..be2a58e7 --- /dev/null +++ b/cis_v300/docs/cis_v300_2_25.md @@ -0,0 +1,19 @@ +## Description + +Users who are set as subscription owners are able to make administrative changes to the subscriptions and move them into and out of Microsoft Entra ID. + +Permissions to move subscriptions in and out of a Microsoft Entra tenant must only be given to appropriate administrative personnel. A subscription that is moved into a Microsoft Entra tenant may be within a folder to which other users have elevated permissions. This prevents loss of data or unapproved changes of the objects within by potential bad actors. + +## Remediation + +### From Azure Portal + +1. From the Azure Portal Home select the portal menu. +2. Select `Subscriptions`. +3. In the `Advanced options` drop-down menu, select `Manage Policies`. +4. Set `Subscription leaving Microsoft Entra tenant` and `Subscription entering Microsoft Entra tenant` to `Permit no one`. +5. Click `Save changes`. + +### Default Value + +By default `Subscription leaving Microsoft Entra tenant` and `Subscription entering Microsoft Entra tenant` are set to `Allow everyone (default)`. diff --git a/cis_v300/docs/cis_v300_2_26.md b/cis_v300/docs/cis_v300_2_26.md new file mode 100644 index 00000000..d43c0308 --- /dev/null +++ b/cis_v300/docs/cis_v300_2_26.md @@ -0,0 +1,24 @@ +## Description + +This recommendation aims to maintain a balance between security and operational efficiency by ensuring that a minimum of 2 and a maximum of 4 users are assigned the Global Administrator role in Microsoft Entra ID. Having at least two Global Administrators ensures redundancy, while limiting the number to four reduces the risk of excessive privileged access. + +The Global Administrator role has extensive privileges across all services in Microsoft Entra ID. The Global Administrator role should never be used in regular daily activities; administrators should have a regular user account for daily activities, and a separate account for administrative responsibilities. Limiting the number of Global Administrators helps mitigate the risk of unauthorized access, reduces the potential impact of human error, and aligns with the principle of least privilege to reduce the attack surface of an Azure tenant. Conversely, having at least two Global Administrators ensures that administrative functions can be performed without interruption in case of unavailability of a single admin. + +## Remediation + +### From Azure Portal + +1. From Azure Home select the Portal Menu. +2. Select `Microsoft Entra ID`. +3. Under `Manage`, select `Roles and administrators`. +4. Under `Administrative Roles`, select `Global Administrator`. + +If more than 4 users are assigned: + +1. Remove Global Administrator role for users which do not or no longer require the role. +2. Assign Global Administrator role via PIM which can be activated when required. +3. Assign more granular roles to users to conduct their duties. + +If only one user is assigned: + +1. Provide the Global Administrator role to a trusted user or create a break glass admin account. diff --git a/cis_v300/docs/cis_v300_2_2_1.md b/cis_v300/docs/cis_v300_2_2_1.md new file mode 100644 index 00000000..0910f8a1 --- /dev/null +++ b/cis_v300/docs/cis_v300_2_2_1.md @@ -0,0 +1,44 @@ +## Description + +Microsoft Entra ID Conditional Access allows an organization to configure `Named locations` and configure whether those locations are trusted or untrusted. These settings provide organizations the means to specify Geographical locations for use in conditional access policies, or define actual IP addresses and IP ranges and whether or not those IP addresses and/or ranges are trusted by the organization. + +Defining trusted source IP addresses or ranges helps organizations create and enforce Conditional Access policies around those trusted or untrusted IP addresses and ranges. Users authenticating from trusted IP addresses and/or ranges may have less access restrictions or access requirements when compared to users that try to authenticate to Microsoft Entra ID from untrusted locations or untrusted source IP addresses/ranges. + +## Remediation + +### From Azure Portal + +1. In the Azure Portal, navigate to `Microsoft Entra ID`. +2. Under `Manage`, click `Security`. +3. Under `Protect`, click `Conditional Access`. +4. Under `Manage`, click `Named locations`. +5. Within the `Named locations` blade, click on `IP ranges location`. +6. Enter a name for this location setting in the `Name` text box. +7. Click on the `+` sign. +8. Add an IP Address Range in CIDR notation inside the text box that appears. +9. Click on the `Add` button. +10. Repeat steps 7 through 9 for each IP Range that needs to be added. +11. If the information entered are trusted ranges, select the `Mark as trusted location` check box. +12. Once finished, click on `Create`. + +### From PowerShell + +Create a new trusted IP-based Named location policy + +```bash +[System.Collections.Generic.List`1[Microsoft.Open.MSGraph.Model.IpRange]]$ipRanges = @() +$ipRanges.Add("") +$ipRanges.Add("") +$ipRanges.Add("") +New-MgIdentityConditionalAccessNamedLocation -dataType "#microsoft.graph.ipNamedLocation" -DisplayName "" -IsTrusted $true -IpRanges $ipRanges +``` + +Set an existing IP-based Named location policy to trusted + +```bash +Update-MgIdentityConditionalAccessNamedLocation -PolicyId "" -dataType "#microsoft.graph.ipNamedLocation" -IsTrusted $true +``` + +### Default Value + +By default, no locations are configured under the `Named locations` blade within the Microsoft Entra ID Conditional Access blade. diff --git a/cis_v300/docs/cis_v300_2_2_2.md b/cis_v300/docs/cis_v300_2_2_2.md new file mode 100644 index 00000000..7669be93 --- /dev/null +++ b/cis_v300/docs/cis_v300_2_2_2.md @@ -0,0 +1,91 @@ +## Description + +**CAUTION**: If these policies are created without first auditing and testing the result, misconfiguration can potentially lock out administrators or create undesired access issues. + +Conditional Access Policies can be used to block access from geographic locations that are deemed out-of-scope for your organization or application. The scope and variables for this policy should be carefully examined and defined. + +Conditional Access, when used as a deny list for the tenant or subscription, is able to prevent ingress or egress of traffic to countries that are outside of the scope of interest (e.g.: customers, suppliers) or jurisdiction of an organization. This is an effective way to prevent unnecessary and long-lasting exposure to international threats such as APTs. + +## Remediation + +### From Azure Portal + +Part 1 of 2 - Create the policy and enable it in `Report-only` mode. + +1. From Azure Home open the portal menu in the top left, and select `Microsoft Entra ID`. +2. Scroll down in the menu on the left, and select `Security`. +3. Select on the left side `Conditional Access`. +4. Select `Policies`. +5. Click the `+ New policy` button, then: +6. Provide a name for the policy. +7. Under `Assignments`, select `Users` then: + - Under `Include`, select `All users`. + - Under `Exclude`, check Users and groups and only select emergency access accounts and service accounts (**NOTE**: Service accounts are excluded here because service accounts are non-interactive and cannot complete MFA). +8. Under `Assignments`, select `Target resources` then: + - Under `Include`, select `All cloud apps`. + - Leave `Exclude` blank unless you have a well defined exception. +9. Under `Conditions`, select `Locations` then: + - Select `Include`, then add entries for locations for those that should be **blocked**. + - Select `Exclude`, then add entries for those that should be allowed (**IMPORTANT**: Ensure that all Trusted Locations are in the `Exclude` list.). +10. Under `Access Controls`, select `Grant` select `Block Access`. +11. Set `Enable policy` to `Report-only`. +12. Click `Create`. + +Allow some time to pass to ensure the sign-in logs capture relevant conditional access events. These events will need to be reviewed to determine if additional considerations are necessary for your organization (e.g. legitimate locations are being blocked and investigation is needed for exception). + +**NOTE:** The policy is not yet 'live,' since `Report-only` is being used to audit the effect of the policy. + +Part 2 of 2 - Confirm that the policy is not blocking access that should be granted, then toggle to `On`. + +1. With your policy now in report-only mode, return to the Microsoft Entra blade and click on `Sign-in logs`. +2. Review the recent sign-in events - click an event then review the event details (specifically the `Report-only` tab) to ensure: + - The sign-in event you're reviewing occurred **after** turning on the policy in report-only mode. + - The policy name from step 6 above is listed in the `Policy Name` column. + - The `Result` column for the new policy shows that the policy was `Not applied` (indicating the location origin was not blocked). +3. If the above conditions are present, navigate back to the policy name in Conditional Access and open it. +4. Toggle the policy from `Report-only` to `On`. +5. Click `Save`. + +### From PowerShell + +First, set up the conditions objects values before updating an existing conditional access policy or before creating a new one. You may need to use additional PowerShell cmdlets to retrieve specific IDs such as the `Get-MgIdentityConditionalAccessNamedLocation` which outputs the `Location IDs` for use with conditional access policies. + +```bash +$conditions = New-Object -TypeName Microsoft.Open.MSGraph.Model.ConditionalAccessConditionSet + +$conditions.Applications = New-Object -TypeName Microsoft.Open.MSGraph.Model.ConditionalAccessApplicationCondition +$conditions.Applications.IncludeApplications = <"All" | "Office365" | "app ID" | @("app ID 1", "app ID 2", etc...> +$conditions.Applications.ExcludeApplications = <"Office365" | "app ID" | @("app ID 1", "app ID 2", etc...)> + +$conditions.Users = New-Object -TypeName Microsoft.Open.MSGraph.Model.ConditionalAccessUserCondition +$conditions.Users.IncludeUsers = <"All" | "None" | "GuestsOrExternalUsers" | "Specific User ID" | @("User ID 1", "User ID 2", etc.)> +$conditions.Users.ExcludeUsers = <"GuestsOrExternalUsers" | "Specific User ID" | @("User ID 1", "User ID 2", etc.)> +$conditions.Users.IncludeGroups = <"group ID" | "All" | @("Group ID 1", "Group ID 2", etc...)> +$conditions.Users.ExcludeGroups = <"group ID" | @("Group ID 1", "Group ID 2", etc...)> +$conditions.Users.IncludeRoles = <"Role ID" | "All" | @("Role ID 1", "Role ID 2", etc...)> +$conditions.Users.ExcludeRoles = <"Role ID" | @("Role ID 1", "Role ID 2", etc...)> + +$conditions.Locations = New-Object -TypeName Microsoft.Open.MSGraph.Model.ConditionalAccessLocationCondition +$conditions.Locations.IncludeLocations = <"Location ID" | @("Location ID 1", "Location ID 2", etc...) > +$conditions.Locations.ExcludeLocations = <"AllTrusted" | "Location ID" | @("Location ID 1", "Location ID 2", etc...)> + +$controls = New-Object -TypeName Microsoft.Open.MSGraph.Model.ConditionalAccessGrantControls +$controls._Operator = "OR" +$controls.BuiltInControls = "block" +``` + +Next, update the existing conditional access policy with the condition set options configured with the previous commands. + +```bash +Update-MgIdentityConditionalAccessPolicy -PolicyId -Conditions $conditions -GrantControls $controls +``` + +To create a new conditional access policy that complies with this best practice, run the following commands after creating the condition set above + +```bash +New-MgIdentityConditionalAccessPolicy -Name "Policy Name" -State -Conditions $conditions -GrantControls $controls +``` + +### Default Value + +This policy does not exist by default. diff --git a/cis_v300/docs/cis_v300_2_2_3.md b/cis_v300/docs/cis_v300_2_2_3.md new file mode 100644 index 00000000..9b217b95 --- /dev/null +++ b/cis_v300/docs/cis_v300_2_2_3.md @@ -0,0 +1,49 @@ +## Description + +Conditional Access Policies can be used to prevent the Device code authentication flow. Device code flow should be permitted only for users that regularly perform duties that explicitly require the use of Device Code to authenticate, such as utilizing Azure with PowerShell. + +Attackers use Device code flow in phishing attacks and, if successful, results in the attacker gaining access tokens and refresh tokens which are scoped to "user_impersonation", which can perform any action the user has permission to perform. + +## Remediation + +### From Azure Portal + +Part 1 of 2 - Create the policy and enable it in `Report-only` mode. + +1. From Azure Home open the portal menu in the top left and select `Microsoft Entra ID`. +2. Scroll down in the menu on the left and select `Security`. +3. Select on the left side `Conditional Access`. +4. Select `Policies`. +5. Click the `+ New policy` button, then: +6. Provide a name for the policy. +7. Under `Assignments`, select `Users` then: + - Under `Include`, select `All users`. + - Under `Exclude`, check Users and groups and only select emergency access accounts. +8. Under `Assignments`, select `Target resources` then: + - Under `Include`, select `All cloud apps`. + - Leave `Exclude` blank unless you have a well defined exception. +9. Under `Conditions` > `Authentication Flows`, set Configure to `Yes` then: + - Select `Device code flow`. + - Select `Done`. +10. Under `Access Controls` > `Grant`, select `Block Access`. +11. Set `Enable policy` to `Report-only`. +12. Click `Create`. + +Allow some time to pass to ensure the sign-in logs capture relevant conditional access events. These events will need to be reviewed to determine if additional considerations are necessary for your organization (e.g. many legitimate use cases of device code authentication are observed). + +**NOTE:** The policy is not yet 'live,' since `Report-only` is being used to audit the effect of the policy. + +Part 2 of 2 - Confirm that the policy is not blocking access that should be granted, then toggle to `On`. + +1. With your policy now in report-only mode, return to the Microsoft Entra blade and click on `Sign-in logs`. +2. Review the recent sign-in events - click an event then review the event details (specifically the `Report-only` tab) to ensure: + - The sign-in event you're reviewing occurred **after** turning on the policy in report-only mode. + - The policy name from step 6 above is listed in the `Policy Name` column. + - The `Result` column for the new policy shows that the policy was `Not applied` (indicating the device code authentication flow was not blocked). +3. If the above conditions are present, navigate back to the policy name in Conditional Access and open it. +4. Toggle the policy from `Report-only` to `On`. +5. Click `Save`. + +### Default Value + +This policy does not exist by default. diff --git a/cis_v300/docs/cis_v300_2_2_4.md b/cis_v300/docs/cis_v300_2_2_4.md new file mode 100644 index 00000000..efa57775 --- /dev/null +++ b/cis_v300/docs/cis_v300_2_2_4.md @@ -0,0 +1,33 @@ +## Description + +For designated users, they will be prompted to use their multi-factor authentication (MFA) process on login. + +Enabling multi-factor authentication is a recommended setting to limit the use of Administrative accounts to authenticated personnel. + +## Remediation + +### From Azure Portal + +1. From Azure Home open the Portal Menu in top left, and select Microsoft Entra ID. +2. Select `Security`. +3. Select `Conditional Access`. +4. Select `Policies`. +5. Click `+ New policy`. +6. Enter a name for the policy. +7. Click the blue text under `Users`. +8. Select `Select users and groups`. +9. Select administrative groups this policy should apply to and click `Select`. +10. Under `Exclude`, check `Users and groups`. +11. Select users this policy not should apply to and click `Select`. +12. Click the blue text under `Target resources`. +13. Select `All cloud apps`. +14. Click the blue text under `Grant`. +15. Under Grant access, check `Require multifactor authentication` and click `Select`. +16. Set `Enable policy` to `Report-only`. +17. Click `Create`. + +After testing the policy in report-only mode, update the `Enable policy` setting from `Report-only` to `On`. + +### Default Value + +Starting October 2024, MFA will be required for all accounts by default. diff --git a/cis_v300/docs/cis_v300_2_2_5.md b/cis_v300/docs/cis_v300_2_2_5.md new file mode 100644 index 00000000..a8e18941 --- /dev/null +++ b/cis_v300/docs/cis_v300_2_2_5.md @@ -0,0 +1,32 @@ +## Description + +For designated users, they will be prompted to use their multi-factor authentication (MFA) process on logins. + +Enabling multi-factor authentication is a recommended setting to limit the potential of accounts being compromised and limiting access to authenticated personnel. + +## Remediation + +### From Azure Portal + +1. From Azure Home open Portal menu in the top left, and select `Microsoft Entra ID`. +2. Select `Security`. +3. Select `Conditional Access`. +4. Select `Policies`. +5. Click `+ New policy`. +6. Enter a name for the policy. +7. Click the blue text under `Users`. +8. Under `Include`, select `All users`. +9. Under `Exclude`, check `Users and groups`. +10. Select users this policy should not apply to and click `Select`. +11. Click the blue text under `Target resources`. +12. Select `All cloud apps`. +13. Click the blue text under `Grant`. +14. Under `Grant access`, check `Require multifactor authentication` and click `Select`. +15. Set `Enable policy` to `Report-only`. +16. Click `Create`. + +After testing the policy in report-only mode, update the `Enable policy` setting from `Report-only` to `On`. + +### Default Value + +Starting October 2024, MFA will be required for all accounts by default. diff --git a/cis_v300/docs/cis_v300_2_2_6.md b/cis_v300/docs/cis_v300_2_2_6.md new file mode 100644 index 00000000..bcfe68a4 --- /dev/null +++ b/cis_v300/docs/cis_v300_2_2_6.md @@ -0,0 +1,37 @@ +## Description + +Entra ID tracks the behavior of sign-in events. If the Entra ID domain is licensed with P2, the sign-in behavior can be used as a detection mechanism for additional scrutiny during the sign-in event. If this policy is set up, then Risky Sign-in events will prompt users to use multi-factor authentication (MFA) tokens on login for additional verification. + +Enabling multi-factor authentication is a recommended setting to limit the potential of accounts being compromised and limiting access to authenticated personnel. Enabling this policy allows Entra ID's risk-detection mechanisms to force additional scrutiny on the login event, providing a deterrent response to potentially malicious sign-in events, and adding an additional authentication layer as a reaction to potentially malicious behavior. + +## Remediation + +### From Azure Portal + +1. From Azure Home select the Portal Menu in the top left and select `Microsoft Entra ID`. +2. Select `Security`. +3. Select `Conditional Access`. +4. Select `Policies`. +5. Click `+ New policy`. +6. Enter a name for the policy. +7. Click the blue text under `Users`. +8. Under `Include`, select `All users`. +9. Under `Exclude`, check `Users and groups`. +10. Select users this policy should not apply to and click `Select`. +11. Click the blue text under `Target resources`. +12. Select `All cloud apps`. +13. Click the blue text under `Conditions`. +14. Select `Sign-in risk`. +15. Update the `Configure` toggle to `Yes`. +16. Check the sign-in risk level this policy should apply to, e.g. `High` and `Medium`. +17. Select `Done`. +18. Click the blue text under `Grant` and check `Require multifactor authentication` then click the `Select` button. +19. Click the blue text under `Session` then check `Sign-in frequency` and select `Every time` and click the `Select` button. +20. Set `Enable policy` to `Report-only`. +21. Click `Create`. + +After testing the policy in report-only mode, update the `Enable policy` setting from `Report-only` to `On`. + +### Default Value + +MFA is not enabled by default. diff --git a/cis_v300/docs/cis_v300_2_2_7.md b/cis_v300/docs/cis_v300_2_2_7.md new file mode 100644 index 00000000..dfe0b781 --- /dev/null +++ b/cis_v300/docs/cis_v300_2_2_7.md @@ -0,0 +1,36 @@ +## Description + +This recommendation ensures that users accessing the Windows Azure Service Management API (i.e. Azure Powershell, Azure CLI, Azure Resource Manager API, etc.) are required to use multi-factor authentication (MFA) credentials when accessing resources through the Windows Azure Service Management API. + +Administrative access to the Windows Azure Service Management API should be secured with a higher level of scrutiny to authenticating mechanisms. Enabling multi-factor authentication is recommended to reduce the potential for abuse of Administrative actions, and to prevent intruders or compromised admin credentials from changing administrative settings. + +**IMPORTANT**: While this recommendation allows exceptions to specific Users or Groups, they should be very carefully tracked and reviewed for necessity on a regular interval through an Access Review process. It is important that this rule be built to include "All Users" to ensure that all users not specifically excepted will be required to use MFA to access the Azure Service Management API. + +## Remediation + +### From Azure Portal + +1. From the Azure Admin Portal dashboard, open `Microsoft Entra ID`. +2. Click `Security` in the Entra ID blade. +3. Click `Conditional Access` in the Security blade. +4. Click `Policies` in the Conditional Access blade. +5. Click `+ New policy`. +6. Enter a name for the policy. +7. Click the blue text under `Users`. +8. Under `Include`, select `All users`. +9. Under `Exclude`, check `Users and groups`. +10. Select users or groups to be exempted from this policy (e.g. break-glass emergency accounts, and non-interactive service accounts) then click the `Select` button. +11. Click the blue text under `Target resources`. +12. Under `Include`, click the `Select apps` radio button. +13. Click the blue text under `Select`. +14. Check the box next to `Windows Azure Service Management APIs` then click the `Select` button. +15. Click the blue text under `Grant`. +16. Under `Grant access` check the box for `Require multi-factor authentication` then click the `Select` button. +17. Before creating, set `Enable policy` to `Report-only`. +18. Click `Create`. + +After testing the policy in report-only mode, update the `Enable policy` setting from `Report-only` to `On`. + +### Default Value + +MFA is not enabled by default for administrative actions. diff --git a/cis_v300/docs/cis_v300_2_2_8.md b/cis_v300/docs/cis_v300_2_2_8.md new file mode 100644 index 00000000..f15015f1 --- /dev/null +++ b/cis_v300/docs/cis_v300_2_2_8.md @@ -0,0 +1,36 @@ +## Description + +This recommendation ensures that users accessing Microsoft Admin Portals (i.e. Microsoft 365 Admin, Microsoft 365 Defender, Exchange Admin Center, Azure Portal, etc.) are required to use multi-factor authentication (MFA) credentials when logging into an Admin Portal. + +Administrative Portals for Microsoft Azure should be secured with a higher level of scrutiny to authenticating mechanisms. Enabling multi-factor authentication is recommended to reduce the potential for abuse of Administrative actions, and to prevent intruders or compromised admin credentials from changing administrative settings. + +**IMPORTANT**: While this recommendation allows exceptions to specific Users or Groups, they should be very carefully tracked and reviewed for necessity on a regular interval through an Access Review process. It is important that this rule be built to include "All Users" to ensure that all users not specifically excepted will be required to use MFA to access Admin Portals. + +## Remediation + +### From Azure Portal + +1. From the Azure Admin Portal dashboard, open `Microsoft Entra ID`. +2. Click `Security` in the Entra ID blade. +3. Click `Conditional Access` in the Security blade. +4. Click `Policies` in the Conditional Access blade. +5. Click `+ New policy`. +6. Enter a name for the policy. +7. Click the blue text under `Users`. +8. Under `Include`, select `All users`. +9. Under `Exclude`, check `Users and groups`. +10. Select users or groups to be exempted from this policy (e.g. break-glass emergency accounts, and non-interactive service accounts) then click the `Select` button. +11. Click the blue text under `Target resources`. +12. Under `Include`, click the `Select apps` radio button. +13. Click the blue text under `Select`. +14. Check the box next to `Microsoft Admin Portals` then click the `Select` button. +15. Click the blue text under `Grant`. +16. Under `Grant access` check the box for `Require multifactor authentication` then click the `Select` button. +17. Before creating, set `Enable policy` to `Report-only`. +18. Click `Create`. + +After testing the policy in report-only mode, update the `Enable policy` setting from `Report-only` to `On`. + +### Default Value + +MFA is not enabled by default for administrative actions. diff --git a/cis_v300/docs/cis_v300_2_3.md b/cis_v300/docs/cis_v300_2_3.md new file mode 100644 index 00000000..216d4acd --- /dev/null +++ b/cis_v300/docs/cis_v300_2_3.md @@ -0,0 +1,34 @@ +## Description + +Require administrators or appropriately delegated users to create new tenants. + +It is recommended to only allow an administrator to create new tenants. This prevent users from creating new Microsoft Entra ID or Azure AD B2C tenants and ensures that only authorized users are able to do so. + +## Remediation + +### From Azure Portal + +1. From Azure Home select the Portal Menu. +2. Select `Microsoft Entra ID`. +3. Under `Manage`, select `Users`. +4. Under `Manage`, select `User settings`. +5. Set `Restrict non-admin users from creating tenants ` to `Yes`. +6. Click `Save`. + +### From PowerShell + +```bash +Import-Module Microsoft.Graph.Identity.SignIns + +Connect-MgGraph -Scopes 'Policy.ReadWrite.Authorization' + +Select-MgProfile -Name beta + +$params = @{ + DefaultUserRolePermissions = @{ + AllowedToCreateTenants = $false + } +} + +Update-MgPolicyAuthorizationPolicy -AuthorizationPolicyId -BodyParameter $params +``` diff --git a/cis_v300/docs/cis_v300_2_4.md b/cis_v300/docs/cis_v300_2_4.md new file mode 100644 index 00000000..e0e094eb --- /dev/null +++ b/cis_v300/docs/cis_v300_2_4.md @@ -0,0 +1,52 @@ +## Description + +Microsoft Entra ID has native and extended identity functionality allowing you to invite people from outside your organization to be guest users in your cloud account and sign in with their own work, school, or social identities. + +Guest users are typically added outside your employee on-boarding/off-boarding process and could potentially be overlooked indefinitely. To prevent this, guest users should be reviewed on a regular basis. During this audit, guest users should also be determined to not have administrative privileges. + +## Remediation + +### From Azure Portal + +1. From Azure Home select the Portal Menu. +2. Select `Microsoft Entra ID`. +3. Under `Manage`, select `Users`. +4. Click on `Add filter`. +5. Select `User type`. +6. Select `Guest` from the Value dropdown. +7. Click `Apply`. +8. Check the box next to all `Guest` users that are no longer required or are inactive. +9. Click `Delete`. +10. Click `OK`. + +### From Azure CLI + +Before deleting the user, set it to inactive using the ID from the Audit Procedure to determine if there are any dependent systems. + +```bash +az ad user update --id --account-enabled {false} +``` + +After determining that there are no dependent systems delete the user. + +```bash +Remove-AzureADUser -ObjectId +``` + +### From Azure PowerShell + +Before deleting the user, set it to inactive using the ID from the Audit Procedure to determine if there are any dependent systems. + +```bash +Set-AzureADUser -ObjectId "" -AccountEnabled false +``` + +After determining that there are no dependent systems delete the user. + +```bash +PS C:\>Remove-AzureADUser -ObjectId +``` + +### Default Value + +By default no guest users are created. diff --git a/cis_v300/docs/cis_v300_2_5.md b/cis_v300/docs/cis_v300_2_5.md new file mode 100644 index 00000000..547c8fff --- /dev/null +++ b/cis_v300/docs/cis_v300_2_5.md @@ -0,0 +1,21 @@ +## Description + +Ensures that two alternate forms of identification are provided before allowing a password reset. + +A Self-service Password Reset (SSPR) through Azure Multi-factor Authentication (MFA) ensures the user's identity is confirmed using two separate methods of identification. With multiple methods set, an attacker would have to compromise both methods before they could maliciously reset a user's password. + +## Remediation + +### From Azure Portal + +1. From Azure Home select the Portal Menu. +2. Select `Microsoft Entra ID`. +3. Under `Manage`, select `Users`. +4. Under `Manage`, select `Password reset`. +5. Select `Authentication methods`. +6. Set the `Number of methods required to reset` to `2`. +7. Click `Save`. + +### Default Value + +By default, the `Number of methods required to reset` is set to "2". diff --git a/cis_v300/docs/cis_v300_2_6.md b/cis_v300/docs/cis_v300_2_6.md new file mode 100644 index 00000000..1daa6c22 --- /dev/null +++ b/cis_v300/docs/cis_v300_2_6.md @@ -0,0 +1,21 @@ +## Description + +The account lockout threshold determines how many failed login attempts are permitted prior to placing the account in a locked-out state and initiating a variable lockout duration. + +Account lockout is a method of protecting against brute-force and password spray attacks. Once the lockout threshold has been exceeded, the account enters a locked-out state which prevents all login attempts for a variable duration. The lockout in combination with a reasonable duration reduces the total number of failed login attempts that a malicious actor can execute in a given period of time. + +## Remediation + +### From Azure Portal + +1. From Azure Home select the Portal Menu. +2. Select `Microsoft Entra ID`. +3. Under `Manage`, select `Security`. +4. Under `Manage`, select `Authentication methods`. +5. Under `Manage`, select `Password protection`. +6. Set the `Lockout threshold` to `10` or fewer. +7. Click `Save`. + +### Default Value + +By default, Lockout threshold is set to `10`. diff --git a/cis_v300/docs/cis_v300_2_7.md b/cis_v300/docs/cis_v300_2_7.md new file mode 100644 index 00000000..7e95a312 --- /dev/null +++ b/cis_v300/docs/cis_v300_2_7.md @@ -0,0 +1,21 @@ +## Description + +The account lockout duration value determines how long an account retains the status of lockout, and therefore how long before a user can continue to attempt to login after passing the lockout threshold. + +Account lockout is a method of protecting against brute-force and password spray attacks. Once the lockout threshold has been exceeded, the account enters a locked-out state which prevents all login attempts for a variable duration. The lockout in combination with a reasonable duration reduces the total number of failed login attempts that a malicious actor can execute in a given period of time. + +## Remediation + +### From Azure Portal + +1. From Azure Home select the Portal Menu. +2. Select `Microsoft Entra ID`. +3. Under `Manage`, select `Security`. +4. Under `Manage`, select `Authentication methods`. +5. Under `Manage`, select `Password protection`. +6. Set the `Lockout duration in seconds` to `60` or higher. +7. Click `Save`. + +### Default Value + +By default, Lockout duration in seconds is set to `60`. diff --git a/cis_v300/docs/cis_v300_2_8.md b/cis_v300/docs/cis_v300_2_8.md new file mode 100644 index 00000000..6301f368 --- /dev/null +++ b/cis_v300/docs/cis_v300_2_8.md @@ -0,0 +1,63 @@ +## Description + +Microsoft Azure provides a Global Banned Password policy that applies to Azure administrative and normal user accounts. This is not applied to user accounts that are synced from an on-premise Active Directory unless Microsoft Entra ID Connect is used and you enable EnforceCloudPasswordPolicyForPasswordSyncedUsers. +Please see the list in default values on the specifics of this policy. To further password security, it is recommended to further define a custom banned password policy. + +Enabling this gives your organization further customization on what secure passwords are allowed. Setting a bad password list enables your organization to fine-tune its password policy further, depending on your needs. Removing easy-to-guess passwords increases the security of access to your Azure resources. + +## Remediation + +### From Azure Portal + +1. From Azure Home select the Portal Menu. +2. Select `Microsoft Entra ID`. +3. Under `Manage`, select `Security`. +4. Under `Manage`, select `Authentication methods`. +5. Under `Manage`, select `Password protection`. +6. Set the `Enforce custom list` option to `Yes`. +7. Click in the `Custom banned password list` text box to add a string. +8. Click `Save`. + +### Default Value + +By default the custom bad password list is not 'Enabled'. +Organizational-specific terms can be added to the custom banned password list, such as the following examples: + +- Brand names +- Product names +- Locations, such as company headquarters +- Company-specific internal terms +- Abbreviations that have specific company meaning +- Months and weekdays with your company's local languages + +The default Azure bad password policy is already applied to your resources which applies the following basic requirements: + +**Characters allowed:** + +- Uppercase characters (A - Z) +- Lowercase characters (a - z) +- Numbers (0 - 9) +- Symbols: +- @ # $ % ^ & * - _ ! + = [ ] { } | \ : ' , . ? / ` ~ " ( ) ; < > +- blank space + +**Characters not allowed:** + +- Unicode characters +- Password length Passwords require +- A minimum of eight characters +- A maximum of 256 characters + +**Password complexity:** +Passwords require three out of four of the following categories: +- Uppercase characters +- Lowercase characters +- Numbers +- Symbols +Note: Password complexity check isn't required for Education tenants. + +**Password not recently used:** + +- When a user changes or resets their password, the new password can't be the same as the current or recently used passwords. +- Password isn't banned by Entra ID Password Protection. +- The password can't be on the global list of banned passwords for Azure AD Password Protection, or on the customizable list of banned passwords specific to your organization. diff --git a/cis_v300/docs/cis_v300_2_9.md b/cis_v300/docs/cis_v300_2_9.md new file mode 100644 index 00000000..43f00a8d --- /dev/null +++ b/cis_v300/docs/cis_v300_2_9.md @@ -0,0 +1,21 @@ +## Description + +Ensure that the number of days before users are asked to re-confirm their authentication information is not set to 0. + +This setting is necessary if you have setup 'Require users to register when signing in option'. If authentication re-confirmation is disabled, registered users will never be prompted to re-confirm their existing authentication information. If the authentication information for a user changes, such as a phone number or email, then the password reset information for that user reverts to the previously registered authentication information. + +## Remediation + +### From Azure Portal + +1. From Azure Home select the Portal Menu. +2. Select `Microsoft Entra ID`. +3. Under `Manage`, select `Users`. +4. Under `Manage`, select `Password reset`. +5. Under `Manage, select `Registration`. +6. Set the `Number of days before users are asked to re-confirm their authentication information` to your organization-defined frequency. +7. Click `Save`. + +### Default Value + +By default, the `Number of days before users are asked to re-confirm their authentication information` is set to "180 days". diff --git a/cis_v300/docs/cis_v300_3.md b/cis_v300/docs/cis_v300_3.md new file mode 100644 index 00000000..f1a42964 --- /dev/null +++ b/cis_v300/docs/cis_v300_3.md @@ -0,0 +1,5 @@ +## Overview + +This section covers security best practice recommendations for products in the Azure Security services category. + +Azure Product Category Page: https://azure.microsoft.com/en-us/products/category/security diff --git a/cis_v300/docs/cis_v300_3_1.md b/cis_v300/docs/cis_v300_3_1.md new file mode 100644 index 00000000..b4e43db2 --- /dev/null +++ b/cis_v300/docs/cis_v300_3_1.md @@ -0,0 +1,3 @@ +## Overview + +This subsection provides guidance on the use of Microsoft Defender for Cloud and associated product plans. This guidance is intended to ensure that - at a minimum - the protective measures offered by these plans are being considered. Organizations may find that they have existing products or services that provide the same utility as some Microsoft Defender for Cloud products. Security and Administrative personnel need to make the determination on their organization's behalf regarding which - if any - of these recommendations are relevant to their organization's needs. In consideration of the above, and because of the potential for increased cost and complexity, please be aware that all Microsoft Defender for Cloud and associated plan recommendations are profiled as "Level 2" recommendations. diff --git a/cis_v300/docs/cis_v300_3_1_1.md b/cis_v300/docs/cis_v300_3_1_1.md new file mode 100644 index 00000000..3e68e6ca --- /dev/null +++ b/cis_v300/docs/cis_v300_3_1_1.md @@ -0,0 +1,25 @@ +## Overview + +Microsoft Defender for Cloud offers foundational and advanced Cloud Security Posture Management (CSPM) solutions to protect across multi-cloud and hybrid environments. Both solutions cover PaaS as well as IaaS. CSPM provides reporting functionality on security and regulatory frameworks including NIST 800 series, ISO 27001, PCI-DSS, CIS Benchmarks and Controls, and many more. CSPM also provides the ability to create your own custom framework, but this will require significant work. Regulatory standards are reported in a compliance dashboard which offers a summarized view against deployed standards and presents the ability to download compliance reports in various formats. + +CSPM has two types of implementations: + +1. Foundational (Free): This implementation is free and enabled by default with a limited set of features including: +- Continuous assessment of the security configuration of cloud resources +- Security recommendations to fix misconfigurations and weaknesses +- Secure score summarizing current overall security posture + +2. Full CSPM (Paid): Full CSPM is a paid product offering additional functionality including: +- Identity and role assignments discovery +- Network exposure detection +- Attack path analysis +- Cloud security explorer for risk hunting +- Agentless vulnerability scanning +- Agentless secrets scanning +- Governance rules to drive timely remediation and accountability +- Regulatory compliance and industry best practices +- Data-aware security posture +- Agentless discovery for Kubernetes +- Agentless container vulnerability assessment + +It is recommended that for full CSPM a cost review is undertaken particularly if your tenant is heavy on IaaS prior to implementing and matched to security requirements. diff --git a/cis_v300/docs/cis_v300_3_1_10.md b/cis_v300/docs/cis_v300_3_1_10.md new file mode 100644 index 00000000..5e7a60b2 --- /dev/null +++ b/cis_v300/docs/cis_v300_3_1_10.md @@ -0,0 +1,18 @@ +## Description + +Ensure that the latest OS patches for all virtual machines are applied. + +Windows and Linux virtual machines should be kept updated to: +- Address a specific bug or flaw +- Improve an OS or application’s general stability +- Fix a security vulnerability + +Microsoft Defender for Cloud retrieves a list of available security and critical updates from Windows Update or Windows Server Update Services (WSUS), depending on which service is configured on a Windows VM. The security center also checks for the latest updates in Linux systems. If a VM is missing a system update, the security center will recommend system updates be applied. + +## Remediation + +Follow Microsoft Azure documentation to apply security patches from the security center. Alternatively, you can employ your own patch assessment and management tool to periodically assess, report, and install the required security patches for your OS. + +### Default Value + +By default, patches are not automatically deployed. diff --git a/cis_v300/docs/cis_v300_3_1_11.md b/cis_v300/docs/cis_v300_3_1_11.md new file mode 100644 index 00000000..da5fb861 --- /dev/null +++ b/cis_v300/docs/cis_v300_3_1_11.md @@ -0,0 +1,37 @@ +## Description + +The Microsoft Cloud Security Benchmark (or "MCSB") is an Azure Policy Initiative containing many security policies to evaluate resource configuration against best practice recommendations. If a policy in the MCSB is set with effect type `Disabled`, it is not evaluated and may prevent administrators from being informed of valuable security recommendations. + +A security policy defines the desired configuration of resources in your environment and helps ensure compliance with company or regulatory security requirements. The MCSB Policy Initiative a set of security recommendations based on best practices and is associated with every subscription by default. When a policy "Effect" is set to `Audit`, policies in the MCSB ensure that Defender for Cloud evaluates relevant resources for supported recommendations. To ensure that policies within the MCSB are not being missed when the Policy Initiative is evaluated, none of the policies should have an Effect of `Disabled`. + +## Remediation + +### From Azure Portal + +Part A - List all disabled policies + +1. From Azure Home select the Portal Menu. +2. Select `Microsoft Defender for Cloud`. +3. Under `Management`, select `Environment Settings`. +4. Select the appropriate Subscription. +5. Click on `Security policies` in the left column. +6. Click on `Microsoft cloud security benchmark`. +7. Click `Add Filter` and select `Effect`. +8. Check the `Disabled` box to search for all disabled policies. +9. Click `Apply`. + +Part B - Remediate Policy Effect + +For each policy that remains in the list: + +1. Click the blue ellipses `...` to the right of the policy name. +2. Click `Manage effect and parameters`. +3. Under Policy effect, select the `Audit` radio button. +4. Click `Save`. +5. Click `Refresh`. + +Repeat "Part B - Remediate Policy Effect" until no more policies are listed. + +### Default Value + +By default, the MCSB policy initiative is associated to all subscriptions and **most** policies will have an effect of `Audit`. Some policies will have a default effect of `Disabled`. diff --git a/cis_v300/docs/cis_v300_3_1_12.md b/cis_v300/docs/cis_v300_3_1_12.md new file mode 100644 index 00000000..9436bb9d --- /dev/null +++ b/cis_v300/docs/cis_v300_3_1_12.md @@ -0,0 +1,45 @@ +## Description + +Enable security alert emails to subscription owners. + +Enabling security alert emails to subscription owners ensures that they receive security alert emails from Microsoft. This ensures that they are aware of any potential security issues and can mitigate the risk in a timely fashion. + +## Remediation + +### From Azure Portal + +1. From Azure Home select the Portal Menu. +2. Select `Microsoft Defender for Cloud`. +3. Under `Management`, select `Environment Settings`. +4. Click on the appropriate Management Group, Subscription, or Workspace. +5. Click on `Email notifications`. +6. In the drop down of the `All users with the following roles` field select `Owner`. +7. Click `Save`. + +### From Azure CLI + +Use the below command to set `Send email also to subscription owners` to `On`. + +```bash +az account get-access-token --query "{subscription:subscription,accessToken:accessToken}" --out tsv | xargs -L1 bash -c 'curl -X PUT -H "Authorization: Bearer $1" -H "Content-Type: application/json" https://management.azure.com/subscriptions/$0/providers/Microsoft.Security/securityContacts/default1?api-version=2017-08-01-preview -d@"input.json"' +``` + +Where `input.json` contains the data below, replacing `validEmailAddress` with a single email address or multiple comma-separated email addresses: + +```json +{ + "id": "/subscriptions//providers/Microsoft.Security/securityContacts/default1", + "name": "default1", + "type": "Microsoft.Security/securityContacts", + "properties": { + "email": "", + "alertNotifications": "On", + "alertsToAdmins": "On", + "notificationsByRole": "Owner" + } +} +``` + +### Default Value + +By default, `Owner` is selected. diff --git a/cis_v300/docs/cis_v300_3_1_13.md b/cis_v300/docs/cis_v300_3_1_13.md new file mode 100644 index 00000000..0aa7fce1 --- /dev/null +++ b/cis_v300/docs/cis_v300_3_1_13.md @@ -0,0 +1,44 @@ +## Description + +Microsoft Defender for Cloud emails the subscription owners whenever a high-severity alert is triggered for their subscription. You should provide a security contact email address as an additional email address. + +Microsoft Defender for Cloud emails the Subscription Owner to notify them about security alerts. Adding your Security Contact's email address to the 'Additional email addresses' field ensures that your organization's Security Team is included in these alerts. This ensures that the proper people are aware of any potential compromise in order to mitigate the risk in a timely fashion. + +## Remediation + +### From Azure Portal + +1. From Azure Home select the Portal Menu. +2. Select `Microsoft Defender for Cloud`. +3. Under `Management`, select `Environment Settings`. +4. Click on the appropriate Management Group, Subscription, or Workspace. +5. Click on `Email notifications`. +6. Enter a valid security contact email address (or multiple addresses separated by commas) in the `Additional email addresses` field. +7. Click `Save`. + +### From Azure CLI + +Use the below command to set `Security contact emails` to `On`. + +```bash +az account get-access-token --query "{subscription:subscription,accessToken:accessToken}" --out tsv | xargs -L1 bash -c 'curl -X PUT -H "Authorization: Bearer $1" -H "Content-Type: application/json" https://management.azure.com/subscriptions/$0/providers/Microsoft.Security/securityContacts/default?api-version=2020-01-01-preview -d@"input.json"' +``` + +Where `input.json` contains the data below, replacing `validEmailAddress` with a single email address or multiple comma-separated email addresses: + +```json +{ + "id": "/subscriptions//providers/Microsoft.Security/securityContacts/default", + "name": "default", + "type": "Microsoft.Security/securityContacts", + "properties": { + "email": "", + "alertNotifications": "On", + "alertsToAdmins": "On" + } +} +``` + +### Default Value + +By default, there are no additional email addresses entered. diff --git a/cis_v300/docs/cis_v300_3_1_14.md b/cis_v300/docs/cis_v300_3_1_14.md new file mode 100644 index 00000000..ebd36c4e --- /dev/null +++ b/cis_v300/docs/cis_v300_3_1_14.md @@ -0,0 +1,44 @@ +## Description + +Enables emailing security alerts to the subscription owner or other designated security contact. + +Enabling security alert emails ensures that security alert emails are received from Microsoft. This ensures that the right people are aware of any potential security issues and are able to mitigate the risk. + +## Remediation + +### From Azure Portal + +1. From Azure Home select the Portal Menu. +2. Select `Microsoft Defender for Cloud`. +3. Under `Management`, select `Environment Settings`. +4. Click on the appropriate Management Group, Subscription, or Workspace. +5. Click on `Email notifications`. +6. Under `Notification types`, check the check box next to `Notify about alerts with the following severity (or higher):` and select `High` from the drop down menu. +7. Click `Save`. + +### From Azure CLI + +Use the below command to set `Send email notification for high severity alerts` to `On`. + +```bash +az account get-access-token --query "{subscription:subscription,accessToken:accessToken}" --out tsv | xargs -L1 bash -c 'curl -X PUT -H "Authorization: Bearer $1" -H "Content-Type: application/json" https://management.azure.com/subscriptions/<$0>/providers/Microsoft.Security/securityContacts/default1?api-version=2017-08-01-preview -d@"input.json"' +``` + +Where `input.json` contains the data below, replacing `validEmailAddress` with a single email address or multiple comma-separated email addresses: + +```json +{ + "id": "/subscriptions//providers/Microsoft.Security/securityContacts/default1", + "name": "default1", + "type": "Microsoft.Security/securityContacts", + "properties": { + "email": "", + "alertNotifications": "On", + "alertsToAdmins": "On" + } +} +``` + +### Default Value + +By default, `Notify about alerts with the following severity (or higher):` is set to `High`. diff --git a/cis_v300/docs/cis_v300_3_1_15.md b/cis_v300/docs/cis_v300_3_1_15.md new file mode 100644 index 00000000..df10dedb --- /dev/null +++ b/cis_v300/docs/cis_v300_3_1_15.md @@ -0,0 +1,21 @@ +## Description + +An organization's attack surface is the collection of assets with a public network identifier or URI that an external threat actor can see or access from outside your cloud. It is the set of points on the boundary of a system, a system element, system component, or an environment where an attacker can try to enter, cause an effect on, or extract data from, that system, system element, system component, or environment. The larger the attack surface, the harder it is to protect. + +This tool can be configured to scan your organization's online infrastructure such as specified domains, hosts, CIDR blocks, and SSL certificates, and store them in an Inventory. Inventory items can be added, reviewed, approved, and removed, and may contain enrichments ("insights") and additional information collected from the tool's different scan engines and open-source intelligence sources. + +A Defender EASM workspace will generate an Inventory of publicly exposed assets by crawling and scanning the internet using _Seeds_ you provide when setting up the tool. Seeds can be FQDNs, IP CIDR blocks, and WHOIS records. + +Defender EASM will generate Insights within 24-48 hours after Seeds are provided, and these insights include vulnerability data (CVEs), ports and protocols, and weak or expired SSL certificates that could be used by an attacker for reconnaisance or exploitation. + +Results are classified High/Medium/Low and some of them include proposed mitigations. + +This tool can monitor the externally exposed resources of an organization, provide valuable insights, and export these findings in a variety of formats (including CSV) for use in vulnerability management operations and red/purple team exercises. + +## Remediation + +To begin remediation, a Microsoft Defender EASM workspace must be created. The resources and inventory items added to this workspace will depend on your environment. + +### Default Value + +Microsoft Defender EASM is an optional, paid Azure Resource that must be created and configured inside a Subscription and Resource Group. diff --git a/cis_v300/docs/cis_v300_3_1_16.md b/cis_v300/docs/cis_v300_3_1_16.md new file mode 100644 index 00000000..6ecce6fb --- /dev/null +++ b/cis_v300/docs/cis_v300_3_1_16.md @@ -0,0 +1,38 @@ +## Description + +[**NOTE:** As of August 1, 2023 customers with an existing subscription to Defender for DNS can continue to use the service, but new subscribers will receive alerts about suspicious DNS activity as part of Defender for Servers P2.] + +Microsoft Defender for DNS scans all network traffic exiting from within a subscription. + +DNS lookups within a subscription are scanned and compared to a dynamic list of websites that might be potential security threats. These threats could be a result of a security breach within your services, thus scanning for them could prevent a potential security threat from being introduced. + +## Remediation + +### From Azure Portal + +1. Go to `Microsoft Defender for Cloud`. +2. Under `Management`, select `Environment Settings`. +3. Click on the subscription name. +4. Select the `Defender plans` blade. +5. Select `On` under `Status` for `DNS`. +6. Select `Save`. + +### From Azure CLI + +Enable Standard pricing tier for DNS: + +```bash +az security pricing create -n 'DNS' --tier 'Standard' +``` + +### From Powershell + +Enable Standard pricing tier for DNS: + +```bash +Set-AzSecurityPricing -Name 'DNS' -PricingTier 'Standard' +``` + +### Default Value + +By default, Microsoft Defender for DNS is not enabled. diff --git a/cis_v300/docs/cis_v300_3_1_1_1.md b/cis_v300/docs/cis_v300_3_1_1_1.md new file mode 100644 index 00000000..db326c23 --- /dev/null +++ b/cis_v300/docs/cis_v300_3_1_1_1.md @@ -0,0 +1,48 @@ +## Description + +Enable automatic provisioning of the monitoring agent to collect security data. + +**DEPRECATION PLANNED:** The Log Analytics Agent is slated for deprecation in August 2024. The Microsoft Defender for Endpoint agent, in tandem with new agentless capabilities will be providing replacement functionality. More detail is available here: [https://techcommunity.microsoft.com/t5/microsoft-defender-for-cloud/microsoft-defender-for-cloud-strategy-and-plan-towards-log/ba-p/3883341](https://techcommunity.microsoft.com/t5/microsoft-defender-for-cloud/microsoft-defender-for-cloud-strategy-and-plan-towards-log/ba-p/3883341). + +When `Log Analytics agent for Azure VMs` is turned on, Microsoft Defender for Cloud provisions the Microsoft Monitoring Agent on all existing supported Azure virtual machines and any new ones that are created. The Microsoft Monitoring Agent scans for various security-related configurations and events such as system updates, OS vulnerabilities, endpoint protection, and provides alerts. + +## Remediation + +### From Azure Portal + +1. From Azure Home select the Portal Menu. +2. Select `Microsoft Defender for Cloud`. +3. Under `Management`, select `Environment Settings`. +4. Select a subscription. +5. Click on `Settings & monitoring`. +6. Set the `Status` of `Log Analytics agent` to `On`. +7. Select a Workspace. +8. Click `Apply`. +9. Click `Continue`. + +Repeat the above for any additional subscriptions. + +### From Azure CLI + +Use the below command to set `Automatic provisioning of monitoring agent` to `On`. + +```bash +az account get-access-token --query "{subscription:subscription,accessToken:accessToken}" --out tsv | xargs -L1 bash -c 'curl -X PUT -H "Authorization: Bearer $1" -H "Content-Type: application/json" https://management.azure.com/subscriptions/subscriptionID/providers/Microsoft.Security/autoProvisioningSettings/default?api-version=2017-08-01-preview -d@"input.json"' +``` + +Where `input.json` contains the Request body json data as mentioned below. + +```json +{ + "id": "/subscriptions//providers/Microsoft.Security/autoProvisioningSettings/default", + "name": "default", + "type": "Microsoft.Security/autoProvisioningSettings", + "properties": { + "autoProvision": "On" + } +} +``` + +### Default Value + +By default, `Automatic provisioning of monitoring agent` is set to `On`. diff --git a/cis_v300/docs/cis_v300_3_1_1_2.md b/cis_v300/docs/cis_v300_3_1_1_2.md new file mode 100644 index 00000000..a1cc3ab1 --- /dev/null +++ b/cis_v300/docs/cis_v300_3_1_1_2.md @@ -0,0 +1,46 @@ +## Description + +This integration setting enables Microsoft Defender for Cloud Apps (formerly 'Microsoft Cloud App Security' or 'MCAS' - see additional info) to communicate with Microsoft Defender for Cloud. + +Microsoft Defender for Cloud offers an additional layer of protection by using Azure Resource Manager events, which is considered to be the control plane for Azure. By analyzing the Azure Resource Manager records, Microsoft Defender for Cloud detects unusual or potentially harmful operations in the Azure subscription environment. +Several of the preceding analytics are powered by Microsoft Defender for Cloud Apps. To benefit from these analytics, subscription must have a Cloud App Security license. + +Microsoft Defender for Cloud Apps works only with Standard Tier subscriptions. + +## Remediation + +### From Azure Portal + +1. From Azure Home select the Portal Menu. +2. Select `Microsoft Defender for Cloud`. +3. Under `Management`, select `Environment Settings`. +4. Select the subscription. +5. Select `Integrations`. +6. Check `Allow Microsoft Defender for Cloud Apps to access my data`. +7. Select `Save`. + +### From Azure CLI + +Use the below command to enable Standard pricing tier for Storage Accounts + +```bash +az account get-access-token --query "{subscription:subscription,accessToken:accessToken}" --out tsv | xargs -L1 bash -c 'curl -X PUT -H "Authorization: Bearer $1" -H "Content-Type: application/json" https://management.azure.com/subscriptions//providers/Microsoft.Security/settings/MCAS?api-version=2021-06-01 -d@"input.json"' + +``` + +Where input.json contains the Request body json data as mentioned below. + +```json +{ + "id": "/subscriptions//providers/Microsoft.Security/settings/MCAS", + "kind": "DataExportSetting", + "type": "Microsoft.Security/settings", + "properties": { + "enabled": true + } +} +``` + +### Default Value + +With Cloud App Security license, these alerts are enabled by default. diff --git a/cis_v300/docs/cis_v300_3_1_3.md b/cis_v300/docs/cis_v300_3_1_3.md new file mode 100644 index 00000000..eaa62fdd --- /dev/null +++ b/cis_v300/docs/cis_v300_3_1_3.md @@ -0,0 +1,3 @@ +## Overview + +This section covers security recommendations for Defender Plan: Servers. diff --git a/cis_v300/docs/cis_v300_3_1_3_1.md b/cis_v300/docs/cis_v300_3_1_3_1.md new file mode 100644 index 00000000..293e6221 --- /dev/null +++ b/cis_v300/docs/cis_v300_3_1_3_1.md @@ -0,0 +1,36 @@ +## Description + +Turning on Microsoft Defender for Servers enables threat detection for Servers, providing threat intelligence, anomaly detection, and behavior analytics in the Microsoft Defender for Cloud. + +Enabling Microsoft Defender for Servers allows for greater defense-in-depth, with threat detection provided by the Microsoft Security Response Center (MSRC). + +## Remediation + +### From Azure Portal + +1. Go to `Microsoft Defender for Cloud`. +2. Under `Management`, select `Environment Settings`. +3. Click on the subscription name. +4. Click `Defender plans` in the left pane. +5. Under `Cloud Workload Protection (CWP)`, locate `Server` in the Plan column, set Status to `On`. +6. Select `Save`. + +### From Azure CLI + +Run the following command: + +```bash +az security pricing create -n VirtualMachines --tier 'standard' +``` + +### From Powershell + +Run the following command: + +```bash +Set-AzSecurityPricing -Name 'VirtualMachines' -PricingTier 'Standard' +``` + +### Default Value + +By default, Microsoft Defender for Servers plan is off. diff --git a/cis_v300/docs/cis_v300_3_1_3_2.md b/cis_v300/docs/cis_v300_3_1_3_2.md new file mode 100644 index 00000000..f56fadcb --- /dev/null +++ b/cis_v300/docs/cis_v300_3_1_3_2.md @@ -0,0 +1,23 @@ +## Description + +Enable vulnerability assessment for machines on both Azure and hybrid (Arc enabled) machines. + +Vulnerability assessment for machines scans for various security-related configurations and events such as system updates, OS vulnerabilities, and endpoint protection, then produces alerts on threat and vulnerability findings. + +## Remediation + +### From Azure Portal + +1. From Azure Home select the Portal Menu. +2. Select `Microsoft Defender for Cloud`. +3. Under `Management`, select `Environment Settings`. +4. Select a subscription. +5. Click on `Settings & Monitoring`. +6. Set the `Status` of `Vulnerability assessment for machines` to `On`. +7. Click `Continue`. + +Repeat the above for any additional subscriptions. + +### Default Value + +By default, `Automatic provisioning of monitoring agent` is set to `Off`. diff --git a/cis_v300/docs/cis_v300_3_1_3_3.md b/cis_v300/docs/cis_v300_3_1_3_3.md new file mode 100644 index 00000000..e1593c39 --- /dev/null +++ b/cis_v300/docs/cis_v300_3_1_3_3.md @@ -0,0 +1,50 @@ +## Description + +The Endpoint protection component enables Microsoft Defender for Endpoint (formerly 'Advanced Threat Protection' or 'ATP' or 'WDATP' - see additional info) to communicate with Microsoft Defender for Cloud. + +**IMPORTANT:** When enabling integration between DfE & DfC it needs to be taken into account that this will have some side effects that may be undesirable. + +1. For server 2019 & above if defender is installed (default for these server SKUs) this will trigger a deployment of the new unified agent and link to any of the extended configuration in the Defender portal. +2. If the new unified agent is required for server SKUs of Win 2016 or Linux and lower there is additional integration that needs to be switched on and agents need to be aligned. + +Microsoft Defender for Endpoint integration brings comprehensive Endpoint Detection and Response (EDR) capabilities within Microsoft Defender for Cloud. This integration helps to spot abnormalities, as well as detect and respond to advanced attacks on endpoints monitored by Microsoft Defender for Cloud. + +MDE works only with Standard Tier subscriptions. + +## Remediation + +### From Azure Portal + +1. From Azure Home select the Portal Menu. +2. Go to `Microsoft Defender for Cloud`. +3. Under `Management`, select `Environment Settings`. +4. Click on the subscription name. +5. Click `Settings & monitoring`. +6. Set the `Status` for `Endpoint protection` to `On`. +7. Click `Continue`. + +### From Azure CLI + +Use the below command to enable Standard pricing tier for Storage Accounts + +```bash +az account get-access-token --query "{subscription:subscription,accessToken:accessToken}" --out tsv | xargs -L1 bash -c 'curl -X PUT -H "Authorization: Bearer $1" -H "Content-Type: application/json" https://management.azure.com/subscriptions//providers/Microsoft.Security/settings/WDATP?api-version=2021-06-01 -d@"input.json"' + +``` + +Where input.json contains the Request body json data as mentioned below. + +```json +{ + "id": "/subscriptions//providers/Microsoft.Security/settings/WDATP", + "kind": "DataExportSettings", + "type": "Microsoft.Security/settings", + "properties": { + "enabled": true + } +} +``` + +### Default Value + +By default, Endpoint protection is `off`. diff --git a/cis_v300/docs/cis_v300_3_1_3_4.md b/cis_v300/docs/cis_v300_3_1_3_4.md new file mode 100644 index 00000000..c5e42d4d --- /dev/null +++ b/cis_v300/docs/cis_v300_3_1_3_4.md @@ -0,0 +1,23 @@ +## Description + +Using disk snapshots, the agentless scanner scans for installed software, vulnerabilities, and plain text secrets. + +The Microsoft Defender for Cloud agentless machine scanner provides threat detection, vulnerability detection, and discovery of sensitive information. + +## Remediation + +### From Azure Portal + +1. From the Azure Portal `Home` page, select `Microsoft Defender for Cloud`. +2. Under `Management` select `Environment Settings`. +3. Select a subscription. +4. Under `Settings` > `Defender Plans`, click `Settings & monitoring`. +5. Under the Component column, locate the row for `Agentless scanning for machines`. +6. Select `On`. +7. Click `Continue` in the top left. + +Repeat the above for any additional subscriptions. + +### Default Value + +By default, Agentless scanning for machines is `off`. diff --git a/cis_v300/docs/cis_v300_3_1_3_5.md b/cis_v300/docs/cis_v300_3_1_3_5.md new file mode 100644 index 00000000..a1f0b919 --- /dev/null +++ b/cis_v300/docs/cis_v300_3_1_3_5.md @@ -0,0 +1,23 @@ +## Description + +File Integrity Monitoring (FIM) is a feature that monitors critical system files in Windows or Linux for potential signs of attack or compromise. + +FIM provides a detection mechanism for compromised files. When FIM is enabled, critical system files are monitored for changes that might indicate a threat actor is attempting to modify system files for lateral compromise within a host operating system. + +## Remediation + +### From Azure Portal + +1. From the Azure Portal `Home` page, select `Microsoft Defender for Cloud`. +2. Under `Management` select `Environment Settings`. +3. Select a subscription. +4. Under `Settings` > `Defender Plans`, click `Settings & monitoring`. +5. Under the Component column, locate the row for `File Integrity Monitoring`. +6. Select `On`. +7. Click `Continue` in the top left. + +Repeat the above for any additional subscriptions. + +### Default Value + +By default, File Integrity Monitoring is `Off`. diff --git a/cis_v300/docs/cis_v300_3_1_4.md b/cis_v300/docs/cis_v300_3_1_4.md new file mode 100644 index 00000000..df970588 --- /dev/null +++ b/cis_v300/docs/cis_v300_3_1_4.md @@ -0,0 +1,3 @@ +## Overview + +This section covers security recommendations for Defender Plan: Containers. diff --git a/cis_v300/docs/cis_v300_3_1_4_1.md b/cis_v300/docs/cis_v300_3_1_4_1.md new file mode 100644 index 00000000..90df8a84 --- /dev/null +++ b/cis_v300/docs/cis_v300_3_1_4_1.md @@ -0,0 +1,44 @@ +## Description + +Turning on Microsoft Defender for Containers enables threat detection for Container Registries including Kubernetes, providing threat intelligence, anomaly detection, and behavior analytics in the Microsoft Defender for Cloud. The following services will be enabled for container instances: +- Defender agent in Azure +- Azure Policy for Kubernetes +- Agentless discovery for Kubernetes +- Agentless container vulnerability assessment + +Enabling Microsoft Defender for Container Registries allows for greater defense-in-depth, with threat detection provided by the Microsoft Security Response Center (MSRC). + +## Remediation + +### From Azure Portal + +1. Go to `Microsoft Defender for Cloud`. +2. Under `Management`, select `Environment Settings`. +3. Click on the subscription name. +4. Select `Defender plans`. +5. Set `Status` to `On` for `Containers`. +6. Click `Save`. + +### From Azure CLI + +(**Note:** 'ContainerRegistry' has been deprecated and is replaced by 'Containers') + +Use the below command to enable Standard pricing tier for Containers. + +```bash +az security pricing create -n 'Containers' --tier 'standard' +``` + +### From Powershell + +(**Note:** 'ContainerRegistry' has been deprecated and is replaced by 'Containers') + +Use the below command to enable Standard pricing tier for Containers. + +```bash +Set-AzSecurityPricing -Name 'Containers' -PricingTier 'Standard' +``` + +### Default Value + +By default, Microsoft Defender for Containers is off. diff --git a/cis_v300/docs/cis_v300_3_1_4_2.md b/cis_v300/docs/cis_v300_3_1_4_2.md new file mode 100644 index 00000000..1e5fad39 --- /dev/null +++ b/cis_v300/docs/cis_v300_3_1_4_2.md @@ -0,0 +1,24 @@ +## Description + +Enable automatic discovery and configuration scanning of the Microsoft Kubernetes clusters. + +As with any compute resource, Container environments require hardening and run-time protection to ensure safe operations and detection of threats and vulnerabilities. + +## Remediation + +### From Azure Portal + +1. From the Azure Portal `Home` page, select `Microsoft Defender for Cloud`. +2. Under `Management` select `Environment Settings`. +3. Select a subscription. +4. Under `Settings` > `Defender Plans`, click `Settings & monitoring`. +5. Locate the row for `Agentless discovery for Kubernetes`. +6. Select `On`. +7. Click `Continue` in the top left. + +Repeat the above for any additional subscriptions. + +### Default Value + +By default, Microsoft Defender for Containers is `Off`. +If Defender for Containers is enabled from the Microsoft Defender for Cloud portal, auto provisioning will be enabled. diff --git a/cis_v300/docs/cis_v300_3_1_4_3.md b/cis_v300/docs/cis_v300_3_1_4_3.md new file mode 100644 index 00000000..1b25e1d4 --- /dev/null +++ b/cis_v300/docs/cis_v300_3_1_4_3.md @@ -0,0 +1,24 @@ +## Description + +Enable automatic vulnerability management for images stored in ACR or running in AKS clusters. + +Agentless vulnerability scanning will examine container images - whether running or in storage - for vulnerable configurations. + +## Remediation + +### From Azure Portal + +1. From the Azure Portal `Home` page, select `Microsoft Defender for Cloud`. +2. Under `Management` select `Environment Settings`. +3. Select a subscription. +4. Under `Settings` > `Defender Plans`, click `Settings & monitoring`. +5. Locate the row for `Agentless container vulnerability assessment`. +6. Select `On`. +7. Click `Continue` in the top left. + +Repeat the above for any additional subscriptions. + +### Default Value + +By default, Microsoft Defender for Containers is `Off`. +If Defender for Containers is enabled from the Microsoft Defender for Cloud portal, auto provisioning will be enabled. diff --git a/cis_v300/docs/cis_v300_3_1_5.md b/cis_v300/docs/cis_v300_3_1_5.md new file mode 100644 index 00000000..9ff81d24 --- /dev/null +++ b/cis_v300/docs/cis_v300_3_1_5.md @@ -0,0 +1,3 @@ +## Overview + +This section covers security recommendations for Defender Plan: Storage. diff --git a/cis_v300/docs/cis_v300_3_1_5_1.md b/cis_v300/docs/cis_v300_3_1_5_1.md new file mode 100644 index 00000000..989ea98b --- /dev/null +++ b/cis_v300/docs/cis_v300_3_1_5_1.md @@ -0,0 +1,34 @@ +## Description + +Turning on Microsoft Defender for Storage enables threat detection for Storage, providing threat intelligence, anomaly detection, and behavior analytics in the Microsoft Defender for Cloud. + +Enabling Microsoft Defender for Storage allows for greater defense-in-depth, with threat detection provided by the Microsoft Security Response Center (MSRC). + +## Remediation + +### From Azure Portal + +1. Go to `Microsoft Defender for Cloud`. +2. Under `Management`, select `Environment Settings`. +3. Click on the subscription name. +4. Select the `Defender plans` blade. +5. Set `Status` to `On` for `Storage`. +6. Select `Save`. + +### From Azure CLI + +Ensure the output of the below command is Standard + +```bash +az security pricing create -n StorageAccounts --tier 'standard' +``` + +### From Powershell + +```bash +Set-AzSecurityPricing -Name 'StorageAccounts' -PricingTier 'Standard' +``` + +### Default Value + +By default, Microsoft Defender plan is off. diff --git a/cis_v300/docs/cis_v300_3_1_6.md b/cis_v300/docs/cis_v300_3_1_6.md new file mode 100644 index 00000000..51ca39d9 --- /dev/null +++ b/cis_v300/docs/cis_v300_3_1_6.md @@ -0,0 +1,3 @@ +## Overview + +This section covers security recommendations for Defender Plan: App Service. diff --git a/cis_v300/docs/cis_v300_3_1_6_1.md b/cis_v300/docs/cis_v300_3_1_6_1.md new file mode 100644 index 00000000..8a408ecd --- /dev/null +++ b/cis_v300/docs/cis_v300_3_1_6_1.md @@ -0,0 +1,36 @@ +## Description + +Turning on Microsoft Defender for App Service enables threat detection for App Service, providing threat intelligence, anomaly detection, and behavior analytics in the Microsoft Defender for Cloud. + +Enabling Microsoft Defender for App Service allows for greater defense-in-depth, with threat detection provided by the Microsoft Security Response Center (MSRC). + +## Remediation + +### From Azure Portal + +1. Go to `Microsoft Defender for Cloud`. +2. Under `Management`, select `Environment Settings`. +3. Click on the subscription name. +4. Select `Defender plans`. +5. Set `App Service` Status to `On`. +6. Select `Save`. + +### From Azure CLI + +Run the following command: + +```bash +az security pricing create -n Appservices --tier 'standard' +``` + +### From Powershell + +Run the following command: + +```bash +Set-AzSecurityPricing -Name "AppServices" -PricingTier "Standard" +``` + +### Default Value + +By default, Microsoft Defender plan is off. diff --git a/cis_v300/docs/cis_v300_3_1_7.md b/cis_v300/docs/cis_v300_3_1_7.md new file mode 100644 index 00000000..8c54f42a --- /dev/null +++ b/cis_v300/docs/cis_v300_3_1_7.md @@ -0,0 +1,3 @@ +## Overview + +This section covers security recommendations for Defender Plan: Databases. diff --git a/cis_v300/docs/cis_v300_3_1_7_1.md b/cis_v300/docs/cis_v300_3_1_7_1.md new file mode 100644 index 00000000..fcfc42be --- /dev/null +++ b/cis_v300/docs/cis_v300_3_1_7_1.md @@ -0,0 +1,38 @@ +## Description + +Microsoft Defender for Azure Cosmos DB scans all incoming network requests for threats to your Azure Cosmos DB resources. + +In scanning Azure Cosmos DB requests within a subscription, requests are compared to a heuristic list of potential security threats. These threats could be a result of a security breach within your services, thus scanning for them could prevent a potential security threat from being introduced. + +## Remediation + +### From Azure Portal + +1. Go to `Microsoft Defender for Cloud`. +2. Under `Management`, select `Environment Settings`. +3. Click on the subscription name. +4. Select the `Defender plans` blade. +5. On the `Database` row click on `Select types >`. +6. Set the toggle switch next to `Azure Cosmos DB` to `On`. +7. Click `Continue`. +8. Click `Save`. + +### From Azure CLI + +Run the following command: + +```bash +az security pricing create -n 'CosmosDbs' --tier 'standard' +``` + +### From Powershell + +Use the below command to enable Standard pricing tier for Azure Cosmos DB + +```bash +Set-AzSecurityPricing -Name 'CosmosDbs' -PricingTier 'Standard +``` + +### Default Value + +By default, Microsoft Defender for Azure Cosmos DB is not enabled. diff --git a/cis_v300/docs/cis_v300_3_1_7_2.md b/cis_v300/docs/cis_v300_3_1_7_2.md new file mode 100644 index 00000000..2d8dd0e2 --- /dev/null +++ b/cis_v300/docs/cis_v300_3_1_7_2.md @@ -0,0 +1,38 @@ +## Description + +Turning on Microsoft Defender for Open-source relational databases enables threat detection for Open-source relational databases, providing threat intelligence, anomaly detection, and behavior analytics in the Microsoft Defender for Cloud. + +Enabling Microsoft Defender for Open-source relational databases allows for greater defense-in-depth, with threat detection provided by the Microsoft Security Response Center (MSRC). + +## Remediation + +### From Azure Portal + +1. Go to `Microsoft Defender for Cloud`. +2. Under `Management`, select `Environment Settings`. +3. Click on the subscription name. +4. Select the `Defender plans` blade. +5. Click `Select types >` in the row for `Databases`. +6. Set the toggle switch next to `Open-source relational databases` to `On`. +7. Select `Continue`. +8. Select `Save`. + +### From Azure CLI + +Run the following command: + +```bash +az security pricing create -n 'OpenSourceRelationalDatabases' --tier 'standard' +``` + +### From Powershell + +Use the below command to enable Standard pricing tier for Open-source relational databases + +```bash +set-azsecuritypricing -name "OpenSourceRelationalDatabases" -pricingtier "Standard" +``` + +### Default Value + +By default, Microsoft Defender plan is off. diff --git a/cis_v300/docs/cis_v300_3_1_7_3.md b/cis_v300/docs/cis_v300_3_1_7_3.md new file mode 100644 index 00000000..3c25f4c5 --- /dev/null +++ b/cis_v300/docs/cis_v300_3_1_7_3.md @@ -0,0 +1,38 @@ +## Description + +Turning on Microsoft Defender for Azure SQL Databases enables threat detection for Managed Instance Azure SQL databases, providing threat intelligence, anomaly detection, and behavior analytics in Microsoft Defender for Cloud. + +Enabling Microsoft Defender for Azure SQL Databases allows for greater defense-in-depth, includes functionality for discovering and classifying sensitive data, surfacing and mitigating potential database vulnerabilities, and detecting anomalous activities that could indicate a threat to your database. + +## Remediation + +### From Azure Portal + +1. Go to `Microsoft Defender for Cloud`. +2. Under `Management`, select `Environment Settings`. +3. Click on the subscription name. +4. Select the `Defender plans` blade. +5. Click `Select types >` in the row for `Databases`. +6. Set the toggle switch next to `Azure SQL Databases` to `On`. +7. Select `Continue`. +8. Select `Save`. + +### From Azure CLI + +Run the following command: + +```bash +az security pricing create -n SqlServers --tier 'standard' +``` + +### From PowerShell + +Run the following command: + +```bash +Set-AzSecurityPricing -Name 'SqlServers' -PricingTier 'Standard' +``` + +### Default Value + +By default, Microsoft Defender plan is off. diff --git a/cis_v300/docs/cis_v300_3_1_7_4.md b/cis_v300/docs/cis_v300_3_1_7_4.md new file mode 100644 index 00000000..fdd9c661 --- /dev/null +++ b/cis_v300/docs/cis_v300_3_1_7_4.md @@ -0,0 +1,38 @@ +## Description + +Turning on Microsoft Defender for SQL servers on machines enables threat detection for SQL servers on machines, providing threat intelligence, anomaly detection, and behavior analytics in Microsoft Defender for Cloud. + +Enabling Microsoft Defender for SQL servers on machines allows for greater defense-in-depth, functionality for discovering and classifying sensitive data, surfacing and mitigating potential database vulnerabilities, and detecting anomalous activities that could indicate a threat to your database. + +## Remediation + +### From Azure Portal + +1. Go to `Microsoft Defender for Cloud`. +2. Under `Management`, select `Environment Settings`. +3. Click on the subscription name. +4. Select the `Defender plans` blade. +5. Click `Select types >` in the row for `Databases`. +6. Set the toggle switch next to `SQL servers on machines` to `On`. +7. Select `Continue`. +8. Select `Save`. + +### From Azure CLI + +Run the following command: + +```bash +az security pricing create -n SqlServerVirtualMachines --tier 'standard' +``` + +### From Powershell + +Run the following command: + +```bash +Set-AzSecurityPricing -Name 'SqlServerVirtualMachines' -PricingTier 'Standard' +``` + +### Default Value + +By default, Microsoft Defender plan is off. diff --git a/cis_v300/docs/cis_v300_3_1_8.md b/cis_v300/docs/cis_v300_3_1_8.md new file mode 100644 index 00000000..07d7df57 --- /dev/null +++ b/cis_v300/docs/cis_v300_3_1_8.md @@ -0,0 +1,3 @@ +## Overview + +This section covers security recommendations for Defender Plan: Key Vault. diff --git a/cis_v300/docs/cis_v300_3_1_8_1.md b/cis_v300/docs/cis_v300_3_1_8_1.md new file mode 100644 index 00000000..e26a3128 --- /dev/null +++ b/cis_v300/docs/cis_v300_3_1_8_1.md @@ -0,0 +1,36 @@ +## Description + +Turning on Microsoft Defender for Key Vault enables threat detection for Key Vault, providing threat intelligence, anomaly detection, and behavior analytics in the Microsoft Defender for Cloud. + +Enabling Microsoft Defender for Key Vault allows for greater defense-in-depth, with threat detection provided by the Microsoft Security Response Center (MSRC). + +## Remediation + +### From Azure Portal + +1. Go to `Microsoft Defender for Cloud`. +2. Under `Management`, select `Environment Settings`. +3. Click on the subscription name. +4. Select the `Defender plans` blade. +5. Select `On` under `Status` for `Key Vault`. +6. Select `Save`. + +### From Azure CLI + +Enable Standard pricing tier for Key Vault: + +```bash +az security pricing create -n 'KeyVaults' --tier 'Standard' +``` + +### From Powershell + +Enable Standard pricing tier for Key Vault: + +```bash +Set-AzSecurityPricing -Name 'KeyVaults' -PricingTier 'Standard' +``` + +### Default Value + +By default, Microsoft Defender plan is off. diff --git a/cis_v300/docs/cis_v300_3_1_9.md b/cis_v300/docs/cis_v300_3_1_9.md new file mode 100644 index 00000000..4b869e28 --- /dev/null +++ b/cis_v300/docs/cis_v300_3_1_9.md @@ -0,0 +1,3 @@ +## Overview + +This section covers security recommendations for Defender Plan: Resource Manager. diff --git a/cis_v300/docs/cis_v300_3_1_9_1.md b/cis_v300/docs/cis_v300_3_1_9_1.md new file mode 100644 index 00000000..b5788c73 --- /dev/null +++ b/cis_v300/docs/cis_v300_3_1_9_1.md @@ -0,0 +1,36 @@ +## Description + +Microsoft Defender for Resource Manager scans incoming administrative requests to change your infrastructure from both CLI and the Azure portal. + +Scanning resource requests lets you be alerted every time there is suspicious activity in order to prevent a security threat from being introduced. + +## Remediation + +### From Azure Portal + +1. Go to `Microsoft Defender for Cloud`. +2. Under `Management`, select `Environment Settings`. +3. Click on the subscription name. +4. Select the `Defender plans` blade. +5. Select `On` under `Status` for `Resource Manager`. +6. Select `Save. + +### From Azure CLI + +Use the below command to enable Standard pricing tier for Defender for Resource Manager + +```bash +az security pricing create -n 'Arm' --tier 'Standard' +``` + +### From PowerShell + +Use the below command to enable Standard pricing tier for Defender for Resource Manager + +```bash +Set-AzSecurityPricing -Name 'Arm' -PricingTier 'Standard' +``` + +### Default Value + +By default, Microsoft Defender for Resource Manager is not enabled. diff --git a/cis_v300/docs/cis_v300_3_2.md b/cis_v300/docs/cis_v300_3_2.md new file mode 100644 index 00000000..a86122d6 --- /dev/null +++ b/cis_v300/docs/cis_v300_3_2.md @@ -0,0 +1,3 @@ +## Overview + +This section covers security recommendations for Microsoft Defender for IoT. diff --git a/cis_v300/docs/cis_v300_3_2_1.md b/cis_v300/docs/cis_v300_3_2_1.md new file mode 100644 index 00000000..236afc69 --- /dev/null +++ b/cis_v300/docs/cis_v300_3_2_1.md @@ -0,0 +1,18 @@ +## Description + +Microsoft Defender for IoT acts as a central security hub for IoT devices within your organization. + +IoT devices are very rarely patched and can be potential attack vectors for enterprise networks. Updating their network configuration to use a central security hub allows for detection of these breaches. + +## Remediation + +### From Azure Portal + +1. Go to `IoT Hub`. +2. Select a `IoT Hub` to validate. +3. Select `Overview` in `Defender for IoT`. +4. Click on `Secure your IoT solution`, and complete the onboarding. + +### Default Value + +By default, Microsoft Defender for IoT is not enabled. diff --git a/cis_v300/docs/cis_v300_3_3.md b/cis_v300/docs/cis_v300_3_3.md new file mode 100644 index 00000000..0a1dfccc --- /dev/null +++ b/cis_v300/docs/cis_v300_3_3.md @@ -0,0 +1,3 @@ +## Overview + +This section covers security recommendations to follow for the configuration and use of Azure Key Vault. diff --git a/cis_v300/docs/cis_v300_3_3_1.md b/cis_v300/docs/cis_v300_3_3_1.md new file mode 100644 index 00000000..6d0d34e0 --- /dev/null +++ b/cis_v300/docs/cis_v300_3_3_1.md @@ -0,0 +1,39 @@ +## Description + +Ensure that all Keys in Role Based Access Control (RBAC) Azure Key Vaults have an expiration date set. + +Azure Key Vault enables users to store and use cryptographic keys within the Microsoft Azure environment. The `exp` (expiration date) attribute identifies the expiration date on or after which the key MUST NOT be used for encryption of new data, wrapping of new keys, and signing. By default, keys never expire. It is thus recommended that keys be rotated in the key vault and set an explicit expiration date for all keys to help enforce the key rotation. This ensures that the keys cannot be used beyond their assigned lifetimes. + +## Remediation + +### From Azure Portal + +1. Go to `Key vaults`. +2. For each Key vault, click on `Keys`. +3. In the main pane, ensure that an appropriate `Expiration date` is set for any keys that are `Enabled`. + +### From Azure CLI + +Update the `Expiration date` for the key using the below command: + +```bash +az keyvault key set-attributes --name --vault-name --expires Y-m-d'T'H:M:S'Z' +``` + +**Note:** +To view the expiration date on all keys in a Key Vault using Microsoft API, the "List" Key permission is required. + +To update the expiration date for the keys: + +1. Go to the Key vault, click on Access Control (IAM). +2. Click on Add role assignment and assign the role of Key Vault Crypto Officer to the appropriate user. + +### From PowerShell + +```bash +Set-AzKeyVaultKeyAttribute -VaultName -Name -Expires +``` + +### Default Value + +By default, keys do not expire. diff --git a/cis_v300/docs/cis_v300_3_3_2.md b/cis_v300/docs/cis_v300_3_3_2.md new file mode 100644 index 00000000..3dc13192 --- /dev/null +++ b/cis_v300/docs/cis_v300_3_3_2.md @@ -0,0 +1,39 @@ +## Description + +Ensure that all Keys in Non Role Based Access Control (RBAC) Azure Key Vaults have an expiration date set. + +Azure Key Vault enables users to store and use cryptographic keys within the Microsoft Azure environment. The `exp` (expiration date) attribute identifies the expiration date on or after which the key MUST NOT be used for a cryptographic operation. By default, keys never expire. It is thus recommended that keys be rotated in the key vault and set an explicit expiration date for all keys. This ensures that the keys cannot be used beyond their assigned lifetimes. + +## Remediation + +### From Azure Portal + +1. Go to `Key vaults`. +2. For each Key vault, click on `Keys`. +3. In the main pane, ensure that the status of the key is `Enabled`. +4. For each enabled key, ensure that an appropriate `Expiration date` is set. + +### From Azure CLI + +Update the `Expiration date` for the key using the below command: + +```bash +az keyvault key set-attributes --name --vault-name --expires Y-m-d'T'H:M:S'Z' +``` + +**Note:** To view the expiration date on all keys in a Key Vault using Microsoft API, the `List` Key permission is required. + +To update the expiration date for the keys: + +1. Go to Key vault, click on `Access policies`. +2. Click on `Create` and add an access policy with the `Update` permission (in the Key Permissions - Key Management Operations section). + +### From PowerShell + +```bash +Set-AzKeyVaultKeyAttribute -VaultName -Name -Expires +``` + +### Default Value + +By default, keys do not expire. diff --git a/cis_v300/docs/cis_v300_3_3_3.md b/cis_v300/docs/cis_v300_3_3_3.md new file mode 100644 index 00000000..bda63cd7 --- /dev/null +++ b/cis_v300/docs/cis_v300_3_3_3.md @@ -0,0 +1,40 @@ +## Description + +Ensure that all Secrets in Role Based Access Control (RBAC) Azure Key Vaults have an expiration date set. + +The Azure Key Vault enables users to store and keep secrets within the Microsoft Azure environment. Secrets in the Azure Key Vault are octet sequences with a maximum size of 25k bytes each. The `exp` (expiration date) attribute identifies the expiration date on or after which the secret MUST NOT be used. By default, secrets never expire. It is thus recommended to rotate secrets in the key vault and set an explicit expiration date for all secrets. This ensures that the secrets cannot be used beyond their assigned lifetimes. + +## Remediation + +### From Azure Portal + +1. Go to `Key vaults`. +2. For each Key vault, click on `Secrets`. +3. In the main pane, ensure that the status of the secret is `Enabled`. +4. For each enabled secret, ensure that an appropriate `Expiration date` is set. + +### From Azure CLI + +Update the Expiration date for the secret using the below command: + +```bash +az keyvault secret set-attributes --name --vault-name --expires Y-m-d'T'H:M:S'Z' +``` + +Note: +To view the expiration date on all secrets in a Key Vault using Microsoft API, the `List Secret` permission is required. + +To update the expiration date for the secrets: + +1. Go to the Key vault, click on `Access Control (IAM)`. +2. Click on `Add role assignment` and assign the role of `Key Vault Secrets Officer` to the appropriate user. + +### From PowerShell + +```bash +Set-AzKeyVaultSecretAttribute -VaultName -Name -Expires +``` + +### Default Value + +By default, secrets do not expire. diff --git a/cis_v300/docs/cis_v300_3_3_4.md b/cis_v300/docs/cis_v300_3_3_4.md new file mode 100644 index 00000000..eb3a425f --- /dev/null +++ b/cis_v300/docs/cis_v300_3_3_4.md @@ -0,0 +1,42 @@ +## Description + +Ensure that all Secrets in Non Role Based Access Control (RBAC) Azure Key Vaults have an expiration date set. + +The Azure Key Vault enables users to store and keep secrets within the Microsoft Azure environment. Secrets in the Azure Key Vault are octet sequences with a maximum size of 25k bytes each. The `exp` (expiration date) attribute identifies the expiration date on or after which the secret MUST NOT be used. By default, secrets never expire. It is thus recommended to rotate secrets in the key vault and set an explicit expiration date for all secrets. This ensures that the secrets cannot be used beyond their assigned lifetimes. + +## Remediation + +### From Azure Portal + +1. Go to `Key vaults`. +2. For each Key vault, click on `Secrets`. +3. In the main pane, ensure that the status of the secret is `Enabled`. +4. Set an appropriate `Expiration date` on all secrets. + +### From Azure CLI + +Update the `Expiration date` for the secret using the below command: + +```bash +az keyvault secret set-attributes --name --vault-name --expires Y-m-d'T'H:M:S'Z' +``` + +Note: +To view the expiration date on all secrets in a Key Vault using Microsoft API, the `List` Secret permission is required. + +To update the expiration date for the secrets: + +1. Go to Key vault, click on `Access policies`. +2. Click on `Create` and add an access policy with the `Update` permission (in the Secret Permissions - Secret Management Operations section). + +### From PowerShell + +For each Key vault with the `EnableRbacAuthorization` setting set to `False` or empty, run the following command. + +```bash +Set-AzKeyVaultSecret -VaultName -Name -Expires +``` + +### Default Value + +By default, secrets do not expire. diff --git a/cis_v300/docs/cis_v300_3_3_5.md b/cis_v300/docs/cis_v300_3_3_5.md new file mode 100644 index 00000000..300c6f27 --- /dev/null +++ b/cis_v300/docs/cis_v300_3_3_5.md @@ -0,0 +1,49 @@ +## Description + +The Key Vault contains object keys, secrets, and certificates. Accidental unavailability of a Key Vault can cause immediate data loss or loss of security functions (authentication, validation, verification, non-repudiation, etc.) supported by the Key Vault objects. + +It is recommended the Key Vault be made recoverable by enabling the "Do Not Purge" and "Soft Delete" functions. This is in order to prevent loss of encrypted data, including storage accounts, SQL databases, and/or dependent services provided by Key Vault objects (Keys, Secrets, Certificates) etc. This may happen in the case of accidental deletion by a user or from disruptive activity by a malicious user. + +**NOTE:** In February 2025, Microsoft will enable soft-delete protection on all key vaults, and users will no longer be able to opt out of or turn off soft-delete. + +**WARNING:** A current limitation is that role assignments disappearing when Key Vault is deleted. All role assignments will need to be recreated after recovery. + +There could be scenarios where users accidentally run delete/purge commands on Key Vault or an attacker/malicious user deliberately does so in order to cause disruption. Deleting or purging a Key Vault leads to immediate data loss, as keys encrypting data and secrets/certificates allowing access/services will become non-accessible. + +There is a Key Vault property that plays a role in permanent unavailability of a Key Vault: + +`enablePurgeProtection`: Setting this parameter to "true" for a Key Vault ensures that even if Key Vault is deleted, Key Vault itself or its objects remain recoverable for the next 90 days. Key Vault/objects can either be recovered or purged (permanent deletion) during those 90 days. If no action is taken, the key vault and its objects will subsequently be purged. + +Enabling the enablePurgeProtection parameter on Key Vaults ensures that Key Vaults and their objects cannot be deleted/purged permanently. + +## Remediation + +To enable "Do Not Purge" and "Soft Delete" for a Key Vault: + +### From Azure Portal + +1. Go to `Key Vaults`. +2. For each Key Vault. +3. Click `Properties`. +4. Ensure the status of Purge protection reads `Enable purge protection (enforce a mandatory retention period for deleted vaults and vault objects)`. +Note, once enabled you cannot disable it. + +### From Azure CLI + +```bash +az resource update --id /subscriptions/xxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups//providers/Microsoft.KeyVault/vaults/ --set properties.enablePurgeProtection=true +``` + +### From PowerShell + +```bash +Update-AzKeyVault -VaultName --name --enable-rbac-authorization true +``` + +### From PowerShell + +To enable RBAC authorization on each Key Vault, run the following PowerShell command: + +```bash +Update-AzKeyVault -ResourceGroupName -VaultName -EnableRbacAuthorization $True +``` + +### Default Value + +The default value for Access control in Key Vaults is Vault Policy. diff --git a/cis_v300/docs/cis_v300_3_3_7.md b/cis_v300/docs/cis_v300_3_3_7.md new file mode 100644 index 00000000..cea362a1 --- /dev/null +++ b/cis_v300/docs/cis_v300_3_3_7.md @@ -0,0 +1,77 @@ +## Description + +Private endpoints will secure network traffic from Azure Key Vault to the resources requesting secrets and keys. + +Private endpoints will keep network requests to Azure Key Vault limited to the endpoints attached to the resources that are whitelisted to communicate with each other. Assigning the Key Vault to a network without an endpoint will allow other resources on that network to view all traffic from the Key Vault to its destination. In spite of the complexity in configuration, this is recommended for high security secrets. + +## Remediation + +**Please see the additional information about the requirements needed before starting this remediation procedure.** + +### From Azure Portal + +1. From Azure Home open the Portal Menu in the top left. +2. Select Key Vaults. +3. Select a Key Vault to audit. +4. Select `Networking` in the left column. +5. Select `Private endpoint connections` from the top row. +6. Select `+ Create`. +7. Select the subscription the Key Vault is within, and other desired configuration. +8. Select `Next`. +9. For resource type select `Microsoft.KeyVault/vaults`. +10. Select the Key Vault to associate the Private Endpoint with. +11. Select `Next`. +12. In the `Virtual Networking` field, select the network to assign the Endpoint. +13. Select other configuration options as desired, including an existing or new application security group. +14. Select `Next`. +15. Select the private DNS the Private Endpoints will use. +16. Select `Next`. +17. Optionally add `Tags`. +18. Select `Next : Review + Create`. +19. Review the information and select `Create`. Follow the Audit Procedure to determine if it has successfully applied. +20. Repeat steps 3-19 for each Key Vault. + +### From Azure CLI + +1. To create an endpoint, run the following command: + +```bash +az network private-endpoint create --resource-group --subnet --name --private-connection-resource-id "/subscriptions//resourceGroups//providers/Microsoft.KeyVault/vaults/" --group-ids vault --connection-name --location --manual-request +``` + +2. To manually approve the endpoint request, run the following command: + +```bash +az keyvault private-endpoint-connection approve --resource-group --vault-name –name +``` + +3. Determine the Private Endpoint's IP address to connect the Key Vault to the Private DNS you have previously created: + +4. Look for the property networkInterfaces then id; the value must be placed in the variable <privateEndpointNIC> within step 7. + +```bash +az network private-endpoint show -g -n +``` + +5. Look for the property networkInterfaces then id; the value must be placed on <privateEndpointNIC> in step 7. + +```bash +az network nic show --ids +``` + +6. Create a Private DNS record within the DNS Zone you created for the Private Endpoint: + +```bash +az network private-dns record-set a add-record -g -z "privatelink.vaultcore.azure.net" -n -a +``` + +7. nslookup the private endpoint to determine if the DNS record is correct: + +```bash +nslookup .vault.azure.net +nslookup .privatelink.vaultcore.azure.n +``` + +### Default Value + +By default, Private Endpoints are not enabled for any services within Azure. diff --git a/cis_v300/docs/cis_v300_3_3_8.md b/cis_v300/docs/cis_v300_3_3_8.md new file mode 100644 index 00000000..d2c054d5 --- /dev/null +++ b/cis_v300/docs/cis_v300_3_3_8.md @@ -0,0 +1,112 @@ +## Description + +Automatic Key Rotation is available in Public Preview. The currently supported applications are Key Vault, Managed Disks, and Storage accounts accessing keys within Key Vault. The number of supported applications will incrementally increased. + +Once set up, Automatic Private Key Rotation removes the need for manual administration when keys expire at intervals determined by your organization's policy. The recommended key lifetime is 2 years. Your organization should determine its own key expiration policy. + +## Remediation + +**Note:** Azure CLI and Powershell use ISO8601 flags to input timespans. Every timespan input will be in the format P<timespanInISO8601Format>(Y,M,D). The leading P is required with it denoting `period`. The (Y,M,D) are for the duration of Year, Month,and Day respectively. A time frame of 2 years, 2 months, 2 days would be (P2Y2M2D). + +### From Azure Portal + +1. From Azure Portal select the Portal Menu in the top left. +2. Select Key Vaults. +3. Select a Key Vault to audit. +4. Under `Objects` select `Keys`. +5. Select a key to audit. +6. In the top row select `Rotation policy`. +7. Select an `Expiry time`. +8. Set `Enable auto rotation` to `Enabled`. +9. Set an appropriate `Rotation option` and `Rotation time`. +10. Optionally set the `Notification time`. +11. Select `Save`. +12. Repeat steps 3-11 for each Key Vault and Key. + +### From Azure CLI + +Run the following command for each key to update its policy to be auto-rotated: + +```bash +az keyvault key rotation-policy update -n --vault-name --value +``` + +Note: It is easiest to supply the policy flags in a .json file. An example json file would be: + +```json +{ + "lifetimeActions": [ + { + "trigger": + { + "timeAfterCreate": "", + "timeBeforeExpiry" : null + }, + "action": + { + "type": "Rotate" + } + }, + { + "trigger": + { + "timeBeforeExpiry" : "" + }, + "action": + { + "type": "Notify" + } + } + ], + "attributes": + { + "expiryTime": "" + } +} +``` + +### From PowerShell + +Run the following command for each key to update its policy: + +```bash +Set-AzKeyVaultKeyRotationPolicy -VaultName test-kv -Name test-key -PolicyPath rotation_policy.json +``` + +**Note**: It is easiest to supply the policy flags in a .json file. An example json file would be: + +```bash +<# +rotation_policy.json +{ + "lifetimeActions": + [ + { + "trigger": { + "timeAfterCreate": "PM", + "timeBeforeExpiry": null + }, + "action": { + "type": "Rotate" + } + }, + { + "trigger": { + "timeBeforeExpiry": "PD" + }, + "action": { + "type": "Notify" + } + } + ], + "attributes": + { + "expiryTime": "PY" + } +} +#> +``` + +### Default Value + +By default, Automatic Key Rotation is not enabled. diff --git a/cis_v300/docs/cis_v300_4.md b/cis_v300/docs/cis_v300_4.md new file mode 100644 index 00000000..52956d2d --- /dev/null +++ b/cis_v300/docs/cis_v300_4.md @@ -0,0 +1,3 @@ +## Overview + +This section covers security recommendations to follow to set storage account policies on an Azure Subscription. An Azure storage account provides a unique namespace to store and access Azure Storage data objects. diff --git a/cis_v300/docs/cis_v300_4_1.md b/cis_v300/docs/cis_v300_4_1.md new file mode 100644 index 00000000..04382309 --- /dev/null +++ b/cis_v300/docs/cis_v300_4_1.md @@ -0,0 +1,26 @@ +## Description + +Enable data encryption in transit. + +The secure transfer option enhances the security of a storage account by only allowing requests to the storage account by a secure connection. For example, when calling REST APIs to access storage accounts, the connection must use HTTPS. Any requests using HTTP will be rejected when 'secure transfer required' is enabled. When using the Azure files service, connection without encryption will fail, including scenarios using SMB 2.1, SMB 3.0 without encryption, and some flavors of the Linux SMB client. Because Azure storage doesn’t support HTTPS for custom domain names, this option is not applied when using a custom domain name. + +## Remediation + +### From Azure Portal + +1. Go to `Storage Accounts`. +2. For each storage account, under `Settings`, click `Configuration`. +3. Set `Secure transfer required` to `Enabled`. +4. Click `Save`. + +### From Azure CLI + +Use the below command to enable `Secure transfer required` for a `Storage Account` + +```bash +az storage account update --name --resource-group --https-only true +``` + +### Default Value + +By default, `Secure transfer required` is set to `Disabled`. diff --git a/cis_v300/docs/cis_v300_4_10.md b/cis_v300/docs/cis_v300_4_10.md new file mode 100644 index 00000000..dd73fd2d --- /dev/null +++ b/cis_v300/docs/cis_v300_4_10.md @@ -0,0 +1,40 @@ +## Description + +The Azure Storage blobs contain data like ePHI or Financial, which can be secret or personal. Data that is erroneously modified or deleted by an application or other storage account user will cause data loss or unavailability. + +It is recommended that both Azure Containers with attached Blob Storage and standalone containers with Blob Storage be made recoverable by enabling the **soft delete** configuration. This is to save and recover data when blobs or blob snapshots are deleted. + +Containers and Blob Storage data can be incorrectly deleted. An attacker/malicious user may do this deliberately in order to cause disruption. Deleting an Azure Storage blob causes immediate data loss. Enabling this configuration for Azure storage ensures that even if blobs/data were deleted from the storage account, Blobs/data objects are recoverable for a particular time which is set in the "Retention policies," ranging from 7 days to 365 days. + +## Remediation + +### From Azure Portal + +1. Go to `Storage Accounts`. +2. For each Storage Account, under `Data management`, go to `Data protection`. +3. Check the box next to `Enable soft delete for blobs`. +4. Check the box next to `Enable soft delete for containers`. +5. Set the retention period for both to a sufficient length for your organization. +6. Click `Save`. + +### From Azure CLI + +Update blob storage retention days in below command + +```bash +az storage blob service-properties delete-policy update --days-retained --account-name --account-key --enable true +``` + +Update container retention with the below command + +```bash +az storage account blob-service-properties update + --enable-container-delete-retention true + --container-delete-retention-days + --account-name + --resource-group +``` + +### Default Value + +Soft delete for containers and blob storage is **enabled** by default on storage accounts created via the Azure Portal, and **disabled** by default on storage accounts created via Azure CLI or PowerShell. diff --git a/cis_v300/docs/cis_v300_4_11.md b/cis_v300/docs/cis_v300_4_11.md new file mode 100644 index 00000000..030bdbfa --- /dev/null +++ b/cis_v300/docs/cis_v300_4_11.md @@ -0,0 +1,21 @@ +## Description + +Enable sensitive data encryption at rest using Customer Managed Keys (CMK) rather than Microsoft Managed keys. + +By default, data in the storage account is encrypted using Microsoft Managed Keys at rest. All Azure Storage resources are encrypted, including blobs, disks, files, queues, and tables. All object metadata is also encrypted. If you want to control and manage this encryption key yourself, however, you can specify a customer-managed key. That key is used to protect and control access to the key that encrypts your data. You can also choose to automatically update the key version used for Azure Storage encryption whenever a new version is available in the associated Key Vault. + +While it is possible to automate the assessment of this recommendation, the assessment status for this recommendation remains 'Manual.' This is because the recommendation pertains to storage accounts that store critical data and is therefore not applicable to all storage accounts. + +## Remediation + +### From Azure Portal + +1. Go to `Storage Accounts`. +2. For each storage account, under `Security + networking`, go to `Encryption`. +3. Set `Encryption type` to `Customer-managed keys`. +4. Select an encryption key or enter a key URI. +5. Click `Save`. + +### Default Value + +By default, Encryption type is set to Microsoft Managed Keys. diff --git a/cis_v300/docs/cis_v300_4_12.md b/cis_v300/docs/cis_v300_4_12.md new file mode 100644 index 00000000..1a14c1cc --- /dev/null +++ b/cis_v300/docs/cis_v300_4_12.md @@ -0,0 +1,31 @@ +## Description + +The Storage Queue service stores messages that may be read by any client who has access to the storage account. A queue can contain an unlimited number of messages, each of which can be up to 64KB in size using version 2011-08-18 or newer. Storage Logging happens server-side and allows details for both successful and failed requests to be recorded in the storage account. These logs allow users to see the details of read, write, and delete operations against the queues. Storage Logging log entries contain the following information about individual requests: Timing information such as start time, end-to-end latency, and server latency, authentication details, concurrency information, and the sizes of the request and response messages. + +Storage Analytics logs contain detailed information about successful and failed requests to a storage service. This information can be used to monitor individual requests and to diagnose issues with a storage service. Requests are logged on a best-effort basis. + +Storage Analytics logging is not enabled by default for your storage account. + +## Remediation + +### From Azure Portal + +1. Go to `Storage Accounts`. +2. For each storage account, under `Monitoring`, click `Diagnostics settings`. +3. Select the `queue` tab indented below the storage account. +4. To create a new diagnostic setting, click `+ Add diagnostic setting`. To update an existing diagnostic setting, click `Edit setting` on the diagnostic setting. +5. Check the boxes next to `StorageRead`, `StorageWrite`, and `StorageDelete`. +6. Select an appropriate destination. +7. Click `Save`. + +### From Azure CLI + +Use the below command to enable the Storage Logging for Queue service. + +```bash +az storage logging update --account-name --account-key --services q --log rwd --retention 90 +``` + +### Default Value + +By default storage account queue services are not logged. diff --git a/cis_v300/docs/cis_v300_4_13.md b/cis_v300/docs/cis_v300_4_13.md new file mode 100644 index 00000000..02b7bc0b --- /dev/null +++ b/cis_v300/docs/cis_v300_4_13.md @@ -0,0 +1,31 @@ +## Description + +The Storage Blob service provides scalable, cost-efficient object storage in the cloud. Storage Logging happens server-side and allows details for both successful and failed requests to be recorded in the storage account. These logs allow users to see the details of read, write, and delete operations against the blobs. Storage Logging log entries contain the following information about individual requests: timing information such as start time, end-to-end latency, and server latency; authentication details; concurrency information; and the sizes of the request and response messages. + +Storage Analytics logs contain detailed information about successful and failed requests to a storage service. This information can be used to monitor each individual request to a storage service for increased security or diagnostics. Requests are logged on a best-effort basis. + +Storage Analytics logging is not enabled by default for your storage account. + +## Remediation + +### From Azure Portal + +1. Go to `Storage Accounts`. +2. For each storage account, under `Monitoring`, click `Diagnostics settings`. +3. Select the `blob` tab indented below the storage account. +4. To create a new diagnostic setting, click `+ Add diagnostic setting`. To update an existing diagnostic setting, click `Edit setting` on the diagnostic setting. +5. Check the boxes next to `StorageRead`, `StorageWrite`, and `StorageDelete`. +6. Select an appropriate destination. +7. Click `Save`. + +### From Azure CLI + +Use the below command to enable the Storage Logging for Blob service. + +```bash +az storage logging update --account-name --account-key --services b --log rwd --retention 90 +``` + +### Default Value + +By default, storage account blob service logging is disabled for read, write, and delete operations. diff --git a/cis_v300/docs/cis_v300_4_14.md b/cis_v300/docs/cis_v300_4_14.md new file mode 100644 index 00000000..e250f56f --- /dev/null +++ b/cis_v300/docs/cis_v300_4_14.md @@ -0,0 +1,31 @@ +## Description + +Azure Table storage is a service that stores structured NoSQL data in the cloud, providing a key/attribute store with a schema-less design. Storage Logging happens server-side and allows details for both successful and failed requests to be recorded in the storage account. These logs allow users to see the details of read, write, and delete operations against the tables. Storage Logging log entries contain the following information about individual requests: timing information such as start time, end-to-end latency, and server latency; authentication details; concurrency information; and the sizes of the request and response messages. + +Storage Analytics logs contain detailed information about successful and failed requests to a storage service. This information can be used to monitor each individual request to a storage service for increased security or diagnostics. Requests are logged on a best-effort basis. + +Storage Analytics logging is not enabled by default for your storage account. + +## Remediation + +### From Azure Portal + +1. Go to `Storage Accounts`. +2. For each storage account, under `Monitoring`, click `Diagnostics settings`. +3. Select the `table` tab indented below the storage account. +4. To create a new diagnostic setting, click `+ Add diagnostic setting`. To update an existing diagnostic setting, click `Edit setting` on the diagnostic setting. +5. Check the boxes next to `StorageRead`, `StorageWrite`, and `StorageDelete`. +6. Select an appropriate destination. +7. Click `Save`. + +### From Azure CLI + +Use the below command to enable the Storage Logging for Table service. + +```bash +az storage logging update --account-name --account-key --services t --log rwd --retention 90 +``` + +### Default Value + +By default, storage account table service logging is disabled for read, write, an delete operations. diff --git a/cis_v300/docs/cis_v300_4_15.md b/cis_v300/docs/cis_v300_4_15.md new file mode 100644 index 00000000..252ed6c8 --- /dev/null +++ b/cis_v300/docs/cis_v300_4_15.md @@ -0,0 +1,39 @@ +## Description + +In some cases, Azure Storage sets the minimum TLS version to be version 1.0 by default. TLS 1.0 is a legacy version and has known vulnerabilities. This minimum TLS version can be configured to be later protocols such as TLS 1.2. + +TLS 1.0 has known vulnerabilities and has been replaced by later versions of the TLS protocol. Continued use of this legacy protocol affects the security of data in transit. + +## Remediation + +### From Azure Portal + +1. Go to `Storage Accounts`. +2. For each storage account, under `Settings`, click `Configuration`. +3. Set the `Minimum TLS version` to `Version 1.2`. +4. Click `Save`. + +### From Azure CLI + +```bash +az storage account update \ + --name \ + --resource-group \ + --min-tls-version TLS1_2 +``` + +### From PowerShell + +To set the minimum TLS version, run the following command: + +```bash +Set-AzStorageAccount -AccountName ` + -ResourceGroupName ` + -MinimumTlsVersion TLS1_2 +``` + +### Default Value + +If a storage account is created through the portal, the MinimumTlsVersion property for that storage account will be set to TLS 1.2. + +If a storage account is created through PowerShell or CLI, the MinimumTlsVersion property for that storage account will not be set, and defaults to TLS 1.0. diff --git a/cis_v300/docs/cis_v300_4_16.md b/cis_v300/docs/cis_v300_4_16.md new file mode 100644 index 00000000..8e868e8d --- /dev/null +++ b/cis_v300/docs/cis_v300_4_16.md @@ -0,0 +1,27 @@ +## Description + +Cross Tenant Replication in Azure allows data to be replicated across multiple Azure tenants. While this feature can be beneficial for data sharing and availability, it also poses a significant security risk if not properly managed. Unauthorized data access, data leakage, and compliance violations are potential risks. Disabling Cross Tenant Replication ensures that data is not inadvertently replicated across different tenant boundaries without explicit authorization. + +Disabling Cross Tenant Replication minimizes the risk of unauthorized data access and ensures that data governance policies are strictly adhered to. This control is especially critical for organizations with stringent data security and privacy requirements, as it prevents the accidental sharing of sensitive information. + +## Remediation + +### From Azure Portal + +1. Go to `Storage Accounts`. +2. For each storage account, under `Data management`, click `Object replication`. +3. Click `Advanced settings`. +4. Uncheck `Allow cross-tenant replication`. +5. Click `OK`. + +### From Azure CLI + +Replace the information within <> with appropriate values: + +```bash +az storage account update --name --resource-group --allow-cross-tenant-replication false +``` + +### Default Value + +For new storage accounts created after Dec 15, 2023 cross tenant replication is not enabled. diff --git a/cis_v300/docs/cis_v300_4_17.md b/cis_v300/docs/cis_v300_4_17.md new file mode 100644 index 00000000..4e9b76f2 --- /dev/null +++ b/cis_v300/docs/cis_v300_4_17.md @@ -0,0 +1,30 @@ +## Description + +The Azure Storage setting ‘Allow Blob Anonymous Access’ (aka "allowBlobPublicAccess") controls whether anonymous access is allowed for blob data in a storage account. When this property is set to True, it enables public read access to blob data, which can be convenient for sharing data but may carry security risks. When set to False, it disallows public access to blob data, providing a more secure storage environment. + +If "Allow Blob Anonymous Access" is enabled, blobs can be accessed by adding the blob name to the URL to see the contents. An attacker can enumerate a blob using methods, such as brute force, and access them. + +Exfiltration of data by brute force enumeration of items from a storage account may occur if this setting is set to 'Enabled'. + +## Remediation + +### From Azure Portal + +1. Go to `Storage Accounts`. +2. For each storage account, under `Settings`, click `Configuration`. +3. Set `Allow Blob Anonymous Access` to `Disabled`. +4. Click `Save`. + +### From Powershell + +For every storage account in scope, run the following: + +```bash +$storageAccount = Get-AzStorageAccount -ResourceGroupName "" -Name "" +$storageAccount.AllowBlobPublicAccess = $false +Set-AzStorageAccount -InputObject $storageAccount +``` + +### Default Value + +Disabled diff --git a/cis_v300/docs/cis_v300_4_2.md b/cis_v300/docs/cis_v300_4_2.md new file mode 100644 index 00000000..3be387f2 --- /dev/null +++ b/cis_v300/docs/cis_v300_4_2.md @@ -0,0 +1,46 @@ +## Description + +Enabling encryption at the hardware level on top of the default software encryption for Storage Accounts accessing Azure storage solutions. + +Azure Storage automatically encrypts all data in a storage account at the network level using 256-bit AES encryption, which is one of the strongest, FIPS 140-2-compliant block ciphers available. Customers who require higher levels of assurance that their data is secure can also enable 256-bit AES encryption at the Azure Storage infrastructure level for double encryption. Double encryption of Azure Storage data protects against a scenario where one of the encryption algorithms or keys may be compromised. Similarly, data is encrypted even before network transmission and in all backups. In this scenario, the additional layer of encryption continues to protect your data. For the most secure implementation of key based encryption, it is recommended to use a Customer Managed asymmetric RSA 2048 Key in Azure Key Vault. + +## Remediation + +### From Azure Portal + +1. During Storage Account creation, in the `Encryption` tab, check the box next to `Enable infrastructure encryption`. + +### From Azure CLI + +Replace the information within <> with appropriate values: + +```bash +az storage account create \ + --name \ + --resource-group \ + --location \ + --sku Standard_RAGRS \ + --kind StorageV2 \ + --require-infrastructure-encryption +``` + +### From PowerShell + +Replace the information within <> with appropriate values: + +```bash +New-AzStorageAccount -ResourceGroupName ` + -AccountName ` + -Location ` + -SkuName "Standard_RAGRS" ` + -Kind StorageV2 ` + -RequireInfrastructureEncryption +``` + +**Enabling Infrastructure Encryption after Storage Account Creation** + +If infrastructure encryption was not enabled on blob storage creation, there is no ***official*** way to enable it. Please see the additional information section. + +### Default Value + +By default, Infrastructure Encryption is disabled in blob creation. diff --git a/cis_v300/docs/cis_v300_4_3.md b/cis_v300/docs/cis_v300_4_3.md new file mode 100644 index 00000000..8f19d63b --- /dev/null +++ b/cis_v300/docs/cis_v300_4_3.md @@ -0,0 +1,38 @@ +## Description + +Access Keys authenticate application access requests to data contained in Storage Accounts. A periodic rotation of these keys is recommended to ensure that potentially compromised keys cannot result in a long-term exploitable credential. The "Rotation Reminder" is an automatic reminder feature for a manual procedure. + +Reminders such as those generated by this recommendation will help maintain a regular and healthy cadence for activities which improve the overall efficacy of a security program. + +Cryptographic key rotation periods will vary depending on your organization's security requirements and the type of data which is being stored in the Storage Account. For example, PCI DSS mandates that cryptographic keys be replaced or rotated 'regularly,' and advises that keys for static data stores be rotated every 'few months.' + +For the purposes of this recommendation, 90 days will prescribed for the reminder. Review and adjustment of the 90 day period is recommended, and may even be necessary. Your organization's security requirements should dictate the appropriate setting. + +## Remediation + +### From Azure Portal + +1. Go to `Storage Accounts`. +2. For each Storage Account that is not compliant, under `Security + networking`, go to `Access keys`. +3. Click `Set rotation reminder`. +4. Check `Enable key rotation reminders`. +5. In the `Send reminders` field select `Custom`, then set the `Remind me every` field to `90` and the period drop down to `Days`. +6. Click `Save`. + +### From Powershell + +```bash +$rgName = +$accountName = +$account = Get-AzStorageAccount -ResourceGroupName $rgName -Name $accountName +if ($account.KeyCreationTime.Key1 -eq $null -or $account.KeyCreationTime.Key2 -eq $null){ + Write-output ("You must regenerate both keys at least once before setting expiration policy") +} else { + $account = Set-AzStorageAccount -ResourceGroupName $rgName -Name $accountName -KeyExpirationPeriodInDay 90 +} +$account.KeyPolicy.KeyExpirationPeriodInDays +``` + +### Default Value + +By default, Key rotation reminders is not configured. diff --git a/cis_v300/docs/cis_v300_4_4.md b/cis_v300/docs/cis_v300_4_4.md new file mode 100644 index 00000000..95de2788 --- /dev/null +++ b/cis_v300/docs/cis_v300_4_4.md @@ -0,0 +1,23 @@ +## Description + +For increased security, regenerate storage account access keys periodically. + +When a storage account is created, Azure generates two 512-bit storage access keys which are used for authentication when the storage account is accessed. Rotating these keys periodically ensures that any inadvertent access or exposure does not result from the compromise of these keys. + +Cryptographic key rotation periods will vary depending on your organization's security requirements and the type of data which is being stored in the Storage Account. For example, PCI DSS mandates that cryptographic keys be replaced or rotated 'regularly,' and advises that keys for static data stores be rotated every 'few months.' + +For the purposes of this recommendation, 90 days will prescribed for the reminder. Review and adjustment of the 90 day period is recommended, and may even be necessary. Your organization's security requirements should dictate the appropriate setting. + +## Remediation + +### From Azure Portal + +1. Go to `Storage Accounts`. +2. For each Storage Account with outdated keys, under `Security + networking`, go to `Access keys`. +3. Click `Rotate key` next to the outdated key, then click `Yes` to the prompt confirming that you want to regenerate the access key. + +After Azure regenerates the Access Key, you can confirm that `Access keys` reflects a `Last rotated` date of `(0 days ago)`. + +### Default Value + +By default, access keys are not regenerated periodically. diff --git a/cis_v300/docs/cis_v300_4_5.md b/cis_v300/docs/cis_v300_4_5.md new file mode 100644 index 00000000..e8cabcac --- /dev/null +++ b/cis_v300/docs/cis_v300_4_5.md @@ -0,0 +1,21 @@ +## Description + +Expire shared access signature tokens within an hour. + +A shared access signature (SAS) is a URI that grants restricted access rights to Azure Storage resources. A shared access signature can be provided to clients who should not be trusted with the storage account key but for whom it may be necessary to delegate access to certain storage account resources. Providing a shared access signature URI to these clients allows them access to a resource for a specified period of time. This time should be set as low as possible and preferably no longer than an hour. + +## Remediation + +When generating shared access signature tokens, use start and end time such that it falls within an hour. + +### From Azure Portal + +1. Go to Storage Accounts. +2. For each storage account where a shared access signature is required, under `Security + networking`, go to `Shared access signature`. +3. Select the appropriate `Allowed resource types`. +4. Set the `Start and expiry date/time` to be within one hour. +5. Click `Generate SAS and connection string`. + +### Default Value + +By default, expiration for shared access signature is set to 8 hours. diff --git a/cis_v300/docs/cis_v300_4_6.md b/cis_v300/docs/cis_v300_4_6.md new file mode 100644 index 00000000..505b5a24 --- /dev/null +++ b/cis_v300/docs/cis_v300_4_6.md @@ -0,0 +1,37 @@ +## Description + +Disallowing public network access for a storage account overrides the public access settings for individual containers in that storage account for Azure Resource Manager Deployment Model storage accounts. Azure Storage accounts that use the classic deployment model will be retired on August 31, 2024. + +The default network configuration for a storage account permits a user with appropriate permissions to configure public network access to containers and blobs in a storage account. Keep in mind that public access to a container is always turned off by default and must be explicitly configured to permit anonymous requests. It grants read-only access to these resources without sharing the account key, and without requiring a shared access signature. +It is recommended not to provide public network access to storage accounts until, and unless, it is strongly desired. A shared access signature token or Azure AD RBAC should be used for providing controlled and timed access to blob containers. + +## Remediation + +### From Azure Portal + +First, follow Microsoft documentation and create shared access signature tokens for your blob containers. Then, + +1. Go to `Storage Accounts`. +2. For each storage account, under the `Security + networking` section, click `Networking`. +3. Set `Public network access` to `Disabled`. +4. Click `Save`. + +### From Azure CLI + +Set 'Public Network Access' to `Disabled` on the storage account + +```bash +az storage account update --name --resource-group --public-network-access Disabled +``` + +### From PowerShell + +For each Storage Account, run the following to set the `PublicNetworkAccess` setting to `Disabled` + +```bash +Set-AzStorageAccount -ResourceGroupName -Name -PublicNetworkAccess Disabled +``` + +### Default Value + +By default, `Public Network Access` is set to `Enabled from all networks` for the Storage Account. diff --git a/cis_v300/docs/cis_v300_4_7.md b/cis_v300/docs/cis_v300_4_7.md new file mode 100644 index 00000000..b85a94b3 --- /dev/null +++ b/cis_v300/docs/cis_v300_4_7.md @@ -0,0 +1,28 @@ +## Description + +Restricting default network access helps to provide a new layer of security, since storage accounts accept connections from clients on any network. To limit access to selected networks, the default action must be changed. + +Storage accounts should be configured to deny access to traffic from all networks (including internet traffic). Access can be granted to traffic from specific Azure Virtual networks, allowing a secure network boundary for specific applications to be built. Access can also be granted to public internet IP address ranges to enable connections from specific internet or on-premises clients. When network rules are configured, only applications from allowed networks can access a storage account. When calling from an allowed network, applications continue to require proper authorization (a valid access key or SAS token) to access the storage account. + +## Remediation + +### From Azure Portal + +1. Go to `Storage Accounts`. +2. For each storage account, under `Security + networking`, click `Networking`. +3. Click the `Firewalls and virtual networks` heading. +4. Set `Public network access` to `Enabled from selected virtual networks and IP addresses`. +5. Add rules to allow traffic from specific networks and IP addresses. +6. Click `Save`. + +### From Azure CLI + +Use the below command to update `default-action` to `Deny`. + +```bash +az storage account update --name --resource-group --default-action Deny +``` + +### Default Value + +By default, Storage Accounts will accept connections from clients on any network. diff --git a/cis_v300/docs/cis_v300_4_8.md b/cis_v300/docs/cis_v300_4_8.md new file mode 100644 index 00000000..3a1f94f9 --- /dev/null +++ b/cis_v300/docs/cis_v300_4_8.md @@ -0,0 +1,30 @@ +## Description + +_NOTE:_ This recommendation assumes that the `Public network access` parameter is set to `Enabled from selected virtual networks and IP addresses`. Please ensure the prerequisite recommendation has been implemented before proceeding: +- Ensure Default Network Access Rule for Storage Accounts is Set to Deny. + +Some Azure services that interact with storage accounts operate from networks that can't be granted access through network rules. To help this type of service work as intended, allow the set of trusted Azure services to bypass the network rules. These services will then use strong authentication to access the storage account. If the `Allow Azure services on the trusted services list to access this storage account` exception is enabled, the following services are granted access to the storage account: Azure Backup, Azure Data Box, Azure DevTest Labs, Azure Event Grid, Azure Event Hubs, Azure File Sync, Azure HDInsight, Azure Import/Export, Azure Monitor, Azure Networking Services, and Azure Site Recovery (when registered in the subscription). + +Turning on firewall rules for a storage account will block access to incoming requests for data, including from other Azure services. We can re-enable this functionality by allowing access to `trusted Azure services` through networking exceptions. + +## Remediation + +### From Azure Portal + +1. Go to `Storage Accounts`. +2. For each storage account, under `Security + networking`, click `Networking`. +3. Click on the `Firewalls and virtual networks` heading. +4. Under `Exceptions`, check the box next to `Allow Azure services on the trusted services list to access this storage account`. +5. Click `Save`. + +### From Azure CLI + +Use the below command to update `bypass` to `Azure services`. + +```bash +az storage account update --name --resource-group --bypass AzureServices +``` + +### Default Value + +By default, Storage Accounts will accept connections from clients on any network. diff --git a/cis_v300/docs/cis_v300_4_9.md b/cis_v300/docs/cis_v300_4_9.md new file mode 100644 index 00000000..cf17ede8 --- /dev/null +++ b/cis_v300/docs/cis_v300_4_9.md @@ -0,0 +1,80 @@ +## Description + +Use private endpoints for your Azure Storage accounts to allow clients and services to securely access data located over a network via an encrypted Private Link. To do this, the private endpoint uses an IP address from the VNet for each service. Network traffic between disparate services securely traverses encrypted over the VNet. This VNet can also link addressing space, extending your network and accessing resources on it. Similarly, it can be a tunnel through public networks to connect remote infrastructures together. This creates further security through segmenting network traffic and preventing outside sources from accessing it. + +Securing traffic between services through encryption protects the data from easy interception and reading. + +## Remediation + +### From Azure Portal + +1. Open the `Storage Accounts` blade. +2. For each listed Storage Account, perform the following: +3. Under the `Security + networking` heading, click on `Networking`. +4. Click on the `Private endpoint connections` tab at the top of the networking window. +5. Click the `+ Private endpoint` button. +6. In the `1 - Basics` tab/step: + - `Enter a name` that will be easily recognizable as associated with the Storage Account (*Note*: The "Network Interface Name" will be automatically completed, but you can customize it if needed.). + - Ensure that the `Region` matches the region of the Storage Account. + - Click `Next`. + +7. In the `2 - Resource` tab/step: + - Select the `target sub-resource` based on what type of storage resource is being made available. + - Click `Next`. + +8. In the `3 - Virtual Network` tab/step: + - Select the `Virtual network` that your Storage Account will be connecting to. + - Select the `Subnet` that your Storage Account will be connecting to. + - (Optional) Select other network settings as appropriate for your environment. + - Click `Next`. + +9. In the `4 - DNS` tab/step: + - (Optional) Select other DNS settings as appropriate for your environment. + - Click `Next`. + +10. In the `5 - Tags` tab/step: + - (Optional) Set any tags that are relevant to your organization. + - Click `Next`. + +11. In the `6 - Review + create` tab/step: + - A validation attempt will be made and after a few moments it should indicate `Validation Passed` - if it does not pass, double-check your settings before beginning more in depth troubleshooting. + - If validation has passed, click `Create` then wait for a few minutes for the scripted deployment to complete. + +Repeat the above procedure for each Private Endpoint required within every Storage Account. + +### From PowerShell + +```bash + +$storageAccount = Get-AzStorageAccount -ResourceGroupName '' -Name '' + +$privateEndpointConnection = @{ + Name = 'connectionName' + PrivateLinkServiceId = $storageAccount.Id + GroupID = "blob|blob_secondary|file|file_secondary|table|table_secondary|queue|queue_secondary|web|web_secondary|dfs|dfs_secondary" +} + +$privateLinkServiceConnection = New-AzPrivateLinkServiceConnection @privateEndpointConnection + +$virtualNetDetails = Get-AzVirtualNetwork -ResourceGroupName '' -Name '' + +$privateEndpoint = @{ + ResourceGroupName = '' + Name = '' + Location = '' + Subnet = $virtualNetDetails.Subnets[0] + PrivateLinkServiceConnection = $privateLinkServiceConnection +} + +New-AzPrivateEndpoint @privateEndpoint +``` + +### From Azure CLI + +```bash +az network private-endpoint create --resource-group --name --vnet-name --subnet --private-connection-resource-id --connection-name --group-id +``` + +### Default Value + +By default, Private Endpoints are not created for Storage Accounts. diff --git a/cis_v300/docs/cis_v300_5.md b/cis_v300/docs/cis_v300_5.md new file mode 100644 index 00000000..6dad9d2d --- /dev/null +++ b/cis_v300/docs/cis_v300_5.md @@ -0,0 +1,3 @@ +## Overview + +This section covers security recommendations to follow to set general database services policies on an Azure Subscription. Subsections will address specific database types. diff --git a/cis_v300/docs/cis_v300_5_1.md b/cis_v300/docs/cis_v300_5_1.md new file mode 100644 index 00000000..93870f15 --- /dev/null +++ b/cis_v300/docs/cis_v300_5_1.md @@ -0,0 +1,5 @@ +## Overview + +This section covers security best practice recommendations for Azure SQL Database. + +Azure Product Page: https://azure.microsoft.com/en-us/products/azure-sql/database/ diff --git a/cis_v300/docs/cis_v300_5_1_1.md b/cis_v300/docs/cis_v300_5_1_1.md new file mode 100644 index 00000000..acf472c3 --- /dev/null +++ b/cis_v300/docs/cis_v300_5_1_1.md @@ -0,0 +1,51 @@ +## Description + +Enable auditing on SQL Servers. + +The Azure platform allows a SQL server to be created as a service. Enabling auditing at the server level ensures that all existing and newly created databases on the SQL server instance are audited. +Auditing policy applied on the SQL database does not override auditing policy and settings applied on the particular SQL server where the database is hosted. + +Auditing tracks database events and writes them to an audit log in the Azure storage account. It also helps to maintain regulatory compliance, understand database activity, and gain insight into discrepancies and anomalies that could indicate business concerns or suspected security violations. + +## Remediation + +### From Azure Portal + +1. Go to `SQL servers`. +2. Select the SQL server instance. +3. Under `Security`, click `Auditing`. +4. Click the toggle next to `Enable Azure SQL Auditing`. +5. Select an Audit log destination. +6. Click `Save`. + +### From PowerShell + +Get the list of all SQL Servers + +```bash +Get-AzSqlServer +``` + +For each Server, enable auditing and set the retention for at least 90 days. + +### Log Analytics Example + +```bash +Set-AzSqlServerAudit -ResourceGroupName -ServerName -RetentionInDays -LogAnalyticsTargetState Enabled -WorkspaceResourceId "/subscriptions//resourceGroups/insights-integration/providers/Microsoft.OperationalInsights/workspaces/ +``` + +### Event Hub Example + +```bash +Set-AzSqlServerAudit -ResourceGroupName "" -ServerName "" -EventHubTargetState Enabled -EventHubName "" -EventHubAuthorizationRuleResourceId "" +``` + +### Blob Storage Example + +```bash +Set-AzSqlServerAudit -ResourceGroupName "" -ServerName "" -BlobStorageTargetState Enabled -StorageAccountResourceId "/subscriptions//resourceGroups//providers/Microsoft.Storage/storageAccounts/" +``` + +### Default Value + +By default, `Enable Azure SQL Auditing` is set to `Off`. diff --git a/cis_v300/docs/cis_v300_5_1_2.md b/cis_v300/docs/cis_v300_5_1_2.md new file mode 100644 index 00000000..533a924e --- /dev/null +++ b/cis_v300/docs/cis_v300_5_1_2.md @@ -0,0 +1,74 @@ +## Description + +Ensure that no SQL Databases allow ingress from 0.0.0.0/0 (ANY IP). + +Azure SQL Server includes a firewall to block access to unauthorized connections. More granular IP addresses can be defined by referencing the range of addresses available from specific datacenters. + +By default, for a SQL server, a Firewall exists with StartIp of 0.0.0.0 and EndIP of 0.0.0.0 allowing access to all the Azure services. + +Additionally, a custom rule can be set up with StartIp of 0.0.0.0 and EndIP of 255.255.255.255 allowing access from ANY IP over the Internet. + +In order to reduce the potential attack surface for a SQL server, firewall rules should be defined with more granular IP addresses by referencing the range of addresses available from specific datacenters. + +If `Allow Azure services and resources to access this server` is 'Checked', this will allow resources outside of the subscription/tenant/organization boundary, within any region of Azure, to effectively bypass the defined SQL Server Network ACL on public endpoint. A malicious attacker can successfully launch a SQL server password bruteforce attack by creating a virtual machine in any Azure subscription/region, from outside of the subscription boundary where the SQL Server is residing. + +## Remediation + +### From Azure Portal + +1. Go to `SQL servers`. +2. For each SQL server. +3. Under `Security`, click `Networking`. +4. Uncheck `Allow Azure services and resources to access this server`. +5. Set firewall rules to limit access to only authorized connections. +6. Click `Save`. + +### From Azure CLI + +Disable default firewall rule `Allow access to Azure services`: + +```bash +az sql server firewall-rule delete --resource-group --server --name "AllowAllWindowsAzureIps" +``` + +Remove a custom firewall rule: + +```bash +az sql server firewall-rule delete --resource-group --server --name +``` + +Create a firewall rule: + +```bash +az sql server firewall-rule create --resource-group --server --name --start-ip-address "" --end-ip-address "" +``` + +Update a firewall rule: + +```bash +az sql server firewall-rule update --resource-group --server --name --start-ip-address "" --end-ip-address "" +``` + +### From PowerShell + +Disable Default Firewall Rule `Allow access to Azure services`: + +```bash +Remove-AzSqlServerFirewallRule -FirewallRuleName "AllowAllWindowsAzureIps" -ResourceGroupName -ServerName +``` + +Remove a custom Firewall rule: + +```bash +Remove-AzSqlServerFirewallRule -FirewallRuleName "" -ResourceGroupName -ServerName +``` + +Set the appropriate firewall rules: + +```bash +Set-AzSqlServerFirewallRule -ResourceGroupName -ServerName -FirewallRuleName "" -StartIpAddress "" -EndIpAddress "" +``` + +### Default Value + +By default, `Allow access to Azure Services` is set to `NO`. diff --git a/cis_v300/docs/cis_v300_5_1_3.md b/cis_v300/docs/cis_v300_5_1_3.md new file mode 100644 index 00000000..1f4cae88 --- /dev/null +++ b/cis_v300/docs/cis_v300_5_1_3.md @@ -0,0 +1,42 @@ +## Description + +Transparent Data Encryption (TDE) with Customer-managed key support provides increased transparency and control over the TDE Protector, increased security with an HSM-backed external service, and promotion of separation of duties. + +With TDE, data is encrypted at rest with a symmetric key (called the database encryption key) stored in the database or data warehouse distribution. To protect this data encryption key (DEK) in the past, only a certificate that the Azure SQL Service managed could be used. Now, with Customer-managed key support for TDE, the DEK can be protected with an asymmetric key that is stored in the Azure Key Vault. The Azure Key Vault is a highly available and scalable cloud-based key store which offers central key management, leverages FIPS 140-2 Level 2 validated hardware security modules (HSMs), and allows separation of management of keys and data for additional security. + +Based on business needs or criticality of data/databases hosted on a SQL server, it is recommended that the TDE protector is encrypted by a key that is managed by the data owner (Customer-managed key). + +Customer-managed key support for Transparent Data Encryption (TDE) allows user control of TDE encryption keys and restricts who can access them and when. Azure Key Vault, Azure’s cloud-based external key management system, is the first key management service where TDE has integrated support for Customer-managed keys. With Customer-managed key support, the database encryption key is protected by an asymmetric key stored in the Key Vault. The asymmetric key is set at the server level and inherited by all databases under that server. + +## Remediation + +### From Azure Portal + +1. Go to `SQL servers`. +2. For each SQL server, under `Security`, click `Transparent data encryption`. +3. Set `Transparent data encryption` to `Customer-managed key`. +4. Select a key or enter a key identifier. +5. Check `Make this key the default TDE protector`. +6. Click `Save`. + +### From Azure CLI + +Use the below command to encrypt SQL server's TDE protector with a Customer-managed key + +```bash +az sql server tde-key set --resource-group --server --server-key-type {AzureKeyVault} --kid +``` + +### From PowerShell + +Use the below command to encrypt SQL server's TDE protector with a Customer-managed Key Vault key + +```bash +Set-AzSqlServerTransparentDataEncryptionProtector -Type AzureKeyVault -KeyId -ServerName -ResourceGroupName +``` + +Select `Y` when prompted + +### Default Value + +By Default, Microsoft managed TDE protector is enabled for a SQL server. diff --git a/cis_v300/docs/cis_v300_5_1_4.md b/cis_v300/docs/cis_v300_5_1_4.md new file mode 100644 index 00000000..392d6e0a --- /dev/null +++ b/cis_v300/docs/cis_v300_5_1_4.md @@ -0,0 +1,50 @@ +## Description + +Use Microsoft Entra authentication for authentication with SQL Database to manage credentials in a single place. + +Microsoft Entra authentication is a mechanism to connect to Microsoft Azure SQL Database and SQL Data Warehouse by using identities in the Microsoft Entra ID directory. With Entra ID authentication, identities of database users and other Microsoft services can be managed in one central location. Central ID management provides a single place to manage database users and simplifies permission management. + +- It provides an alternative to SQL Server authentication. +- Helps stop the proliferation of user identities across database servers. +- Allows password rotation in a single place. +- Customers can manage database permissions using external (Entra ID) groups. +- It can eliminate storing passwords by enabling integrated Windows authentication and other forms of authentication supported by Microsoft Entra. +- Entra ID authentication uses contained database users to authenticate identities at the database level. +- Entra ID supports token-based authentication for applications connecting to SQL Database. +- Entra ID authentication supports ADFS (domain federation) or native user/password authentication for a local Active Directory without domain synchronization. +- Entra ID supports connections from SQL Server Management Studio that use Active Directory Universal Authentication, which includes Multi-Factor Authentication (MFA). MFA includes strong authentication with a range of easy verification options — phone call, text message, smart cards with pin, or mobile app notification. + +## Remediation + +### From Azure Portal + +1. Go to `SQL servers`. +2. For each SQL server, under `Settings`, click `Microsoft Entra ID`. +3. Click `Set admin`. +4. Select an admin. +5. Click `Select`. +6. Click `Save`. + +### From Azure CLI + +```bash +az ad user show --id +``` + +For each Server, set AD Admin + +```bash +az sql server ad-admin create --resource-group --server --display-name --object-id +``` + +### From PowerShell + +For each Server, set Entra ID Admin + +```bash +Set-AzSqlServerActiveDirectoryAdministrator -ResourceGroupName -ServerName -DisplayName "" +``` + +### Default Value + +Entra ID Authentication for SQL Database/Server is not enabled by default. diff --git a/cis_v300/docs/cis_v300_5_1_5.md b/cis_v300/docs/cis_v300_5_1_5.md new file mode 100644 index 00000000..7cf6ec35 --- /dev/null +++ b/cis_v300/docs/cis_v300_5_1_5.md @@ -0,0 +1,40 @@ +## Description + +Enable Transparent Data Encryption on every SQL server. + +Azure SQL Database transparent data encryption helps protect against the threat of malicious activity by performing real-time encryption and decryption of the database, associated backups, and transaction log files at rest without requiring changes to the application. + +## Remediation + +### From Azure Portal + +1. Go to `SQL databases`. +2. For each DB instance, under `Security`, click `Data Encryption`. +3. Under `Transparent data encryption`, set `Data encryption` to `On`. +4. Click `Save`. + +### From Azure CLI + +Use the below command to enable `Transparent data encryption` for SQL DB instance. + +```bash +az sql db tde set --resource-group --server --database --status Enabled +``` + +### From PowerShell + +Use the below command to enable `Transparent data encryption` for SQL DB instance. + +```bash +Set-AzSqlDatabaseTransparentDataEncryption -ResourceGroupName -ServerName -DatabaseName -State 'Enabled' +``` + +**Note:** + +- TDE cannot be used to encrypt the logical master database in SQL Database. The master database contains objects that are needed to perform the TDE operations on the user databases. + +- Azure Portal does not show master databases per SQL server. However, CLI/API responses will show master databases. + +### Default Value + +By default, `Data encryption` is set to `On`. diff --git a/cis_v300/docs/cis_v300_5_1_6.md b/cis_v300/docs/cis_v300_5_1_6.md new file mode 100644 index 00000000..65a0d987 --- /dev/null +++ b/cis_v300/docs/cis_v300_5_1_6.md @@ -0,0 +1,41 @@ +## Description + +SQL Server Audit Retention should be configured to be greater than 90 days. + +Audit Logs can be used to check for anomalies and give insight into suspected breaches or misuse of information and access. + +## Remediation + +### From Azure Portal + +1. Go to `SQL servers`. +2. For each SQL server, under `Security`, click `Auditing`. +3. If `Storage` is checked, expand `Advanced properties`. +4. Set `Retention (days)` to a value greater than `90`, or `0` for unlimited retention. +5. Click `Save`. + +### From PowerShell + +For each Server, set retention policy to more than 90 days + +### Log Analytics Example + +```bash +Set-AzSqlServerAudit -ResourceGroupName -ServerName -RetentionInDays -LogAnalyticsTargetState Enabled -WorkspaceResourceId "/subscriptions//resourceGroups/insights-integration/providers/Microsoft.OperationalInsights/workspaces/ +``` + +### Event Hub Example + +```bash +Set-AzSqlServerAudit -ResourceGroupName "" -ServerName "" -EventHubTargetState Enabled -EventHubName "" -EventHubAuthorizationRuleResourceId "" +``` + +### Blob Storage Example + +```bash +Set-AzSqlServerAudit -ResourceGroupName "" -ServerName "" -BlobStorageTargetState Enabled -StorageAccountResourceId "/subscriptions//resourceGroups//providers/Microsoft.Storage/storageAccounts/" +``` + +### Default Value + +By default, SQL Server audit storage is `disabled`. diff --git a/cis_v300/docs/cis_v300_5_1_7.md b/cis_v300/docs/cis_v300_5_1_7.md new file mode 100644 index 00000000..5bbf5cee --- /dev/null +++ b/cis_v300/docs/cis_v300_5_1_7.md @@ -0,0 +1,18 @@ +## Description + +Disabling public network access restricts the service from accessing public networks. + +A secure network architecture requires carefully constructed network segmentation. Public Network Access tends to be overly permissive and introduces unintended vectors for threat activity. + +## Remediation + +### From Azure Portal + +1. Go to `SQL servers`. +2. For each SQL server, under `Security`, click `Networking`. +3. Set `Public network access` to `Disable`. +4. Click `Save`. + +### Default Value + +By default, Azure SQL Server's Public network access is set to `Disable`. diff --git a/cis_v300/docs/cis_v300_5_2.md b/cis_v300/docs/cis_v300_5_2.md new file mode 100644 index 00000000..240db72d --- /dev/null +++ b/cis_v300/docs/cis_v300_5_2.md @@ -0,0 +1,9 @@ +## Overview + +This section covers security best practice recommendations for Azure PostgreSQL Database Servers. + +Azure Product Page: https://azure.microsoft.com/en-us/products/postgresql/ + +**RETIREMENT of Azure PostgreSQL Single Server:** Azure PostgreSQL Single Server is slated for retirement by March 25, 2025. Azure PostgreSQL Flexible Server is the newer deployment standard and is unaffected. Please use these resources to consider and prepare for migration: +- https://learn.microsoft.com/en-us/azure/postgresql/single-server/whats-happening-to-postgresql-single-server +- https://learn.microsoft.com/en-us/azure/postgresql/migrate/concepts-single-to-flexible diff --git a/cis_v300/docs/cis_v300_5_2_1.md b/cis_v300/docs/cis_v300_5_2_1.md new file mode 100644 index 00000000..536d68ef --- /dev/null +++ b/cis_v300/docs/cis_v300_5_2_1.md @@ -0,0 +1,34 @@ +## Description + +Enable `require_secure_transport` on `PostgreSQL flexible servers`. + +`SSL connectivity` helps to provide a new layer of security by connecting database server to client applications using Secure Sockets Layer (SSL). Enforcing SSL connections between database server and client applications helps protect against "man in the middle" attacks by encrypting the data stream between the server and application. + +## Remediation + +### From Azure Portal + +1. Login to Azure Portal using [https://portal.azure.com](https://portal.azure.com). +2. Go to `Azure Database for PostgreSQL flexible servers`. +3. For each database, under `Settings`, click `Server parameters`. +4. In the filter bar, type `require_secure_transport`. +5. Set the `VALUE` for `require_secure_transport` to `ON`. +6. Click `Save`. + +### From Azure CLI + +Use the below command to enable `require_secure_transport`: + +```bash +az postgres flexible-server parameter set --resource-group --server-name --name require_secure_transport --value on +``` + +### From PowerShell + +```bash +Update-AzPostgreSqlFlexibleServerConfiguration -ResourceGroupName -ServerName -Name require_secure_transport -Value on +``` + +### Default Value + +By default, secure connectivity is enforced, but some application frameworks may not enable it during deployment. diff --git a/cis_v300/docs/cis_v300_5_2_2.md b/cis_v300/docs/cis_v300_5_2_2.md new file mode 100644 index 00000000..11d12b36 --- /dev/null +++ b/cis_v300/docs/cis_v300_5_2_2.md @@ -0,0 +1,34 @@ +## Description + +Enable `log_checkpoints` on `PostgreSQL flexible servers`. + +Enabling `log_checkpoints` helps the PostgreSQL Database to `Log each checkpoint`, which in turn generates query and error logs. However, access to transaction logs is not supported. Query and error logs can be used to identify, troubleshoot, and repair configuration errors and sub-optimal performance. + +## Remediation + +### From Azure Portal + +1. From Azure Home select the Portal Menu. +2. Go to `Azure Database for PostgreSQL flexible servers`. +3. For each database, under `Settings`, click `Server parameters`. +4. In the filter bar, type `log_checkpoints`. +5. Set the `VALUE` for `log_checkpoints` to `ON`. +6. Click `Save`. + +### From Azure CLI + +Use the below command to enable `log_checkpoints`: + +```bash +az postgres flexible-server parameter set --resource-group --server-name --name log_checkpoints --value on +``` + +### From PowerShell + +```bash +Update-AzPostgreSqlFlexibleServerConfiguration -ResourceGroupName -ServerName -Name log_checkpoints -Value on +``` + +### Default Value + +By default `log_checkpoints` is enabled (set to `on`). diff --git a/cis_v300/docs/cis_v300_5_2_3.md b/cis_v300/docs/cis_v300_5_2_3.md new file mode 100644 index 00000000..8ace17a2 --- /dev/null +++ b/cis_v300/docs/cis_v300_5_2_3.md @@ -0,0 +1,36 @@ +## Description + +Enable connection throttling on `PostgreSQL flexible servers`. + +Enabling `connection throttling` helps the PostgreSQL Database to `Set the verbosity of logged messages`. This in turn generates query and error logs with respect to concurrent connections that could lead to a successful Denial of Service (DoS) attack by exhausting connection resources. A system can also fail or be degraded by an overload of legitimate users. Query and error logs can be used to identify, troubleshoot, and repair configuration errors and sub-optimal performance. + +## Remediation + +### From Azure Portal + +1. Login to Azure Portal using [https://portal.azure.com](https://portal.azure.com). +2. Go to `Azure Database for PostgreSQL flexible servers`. +3. For each database, under `Settings`, click `Server parameters`. +4. In the filter bar, type `connection_throttle.enable`. +5. Set `connection_throttle.enable` to `ON`. +6. Click `Save`. + +### From Azure CLI + +Use the below command to enable `connection_throttle.enable`: + +```bash +az postgres flexible-server parameter set --resource-group --server-name --name connection_throttle.enable --value on +``` + +### From PowerShell + +Use the below command to update `connection_throttling` configuration. + +```bash +Update-AzPostgreSqlFlexibleServerConfiguration -ResourceGroupName -ServerName -Name connection_throttle.enable -Value on +``` + +### Default Value + +By default, `connection_throttle.enable` is disabled (set to `off`). diff --git a/cis_v300/docs/cis_v300_5_2_4.md b/cis_v300/docs/cis_v300_5_2_4.md new file mode 100644 index 00000000..7643ac39 --- /dev/null +++ b/cis_v300/docs/cis_v300_5_2_4.md @@ -0,0 +1,36 @@ +## Description + +Ensure `logfiles.retention_days` on `PostgreSQL flexible servers` is set to an appropriate value. + +Configuring `logfiles.retention_days` determines the duration in days that `Azure Database for PostgreSQL` retains log files. Query and error logs can be used to identify, troubleshoot, and repair configuration errors and sub-optimal performance. + +## Remediation + +### From Azure Portal + +1. From Azure Home select the Portal Menu. +2. Go to `Azure Database for PostgreSQL flexible servers`. +3. For each database, under `Settings`, click `Server parameters`. +4. In the filter bar, type `logfiles.retention_days`. +5. Input a value between 4 and 7 (inclusive). +6. Click `Save`. + +### From Azure CLI + +Use the below command to update `logfiles.retention_days` configuration: + +```bash +az postgres flexible-server parameter set --resource-group --server-name --name logfiles.retention_days --value <4-7> +``` + +### From Powershell + +Use the below command to update `logfiles.retention_days` configuration: + +```bash +Update-AzPostgreSqlFlexibleServerConfiguration -ResourceGroupName -ServerName -Name logfiles.retention_days -Value <4-7> +``` + +### Default Value + +By default `logfiles.retention_days` is set to `3`. diff --git a/cis_v300/docs/cis_v300_5_2_5.md b/cis_v300/docs/cis_v300_5_2_5.md new file mode 100644 index 00000000..83883513 --- /dev/null +++ b/cis_v300/docs/cis_v300_5_2_5.md @@ -0,0 +1,37 @@ +## Description + +Disable access from Azure services to `PostgreSQL flexible server`. + +If access from Azure services is enabled, the server's firewall will accept connections from all Azure resources, including resources not in your subscription. This is usually not a desired configuration. Instead, set up firewall rules to allow access from specific network ranges or VNET rules to allow access from specific virtual networks. + +## Remediation + +### From Azure Portal + +1. Login to Azure Portal using https://portal.azure.com. +2. Go to `Azure Database for PostgreSQL flexible servers`. +3. For each database, under `Settings`, click `Networking`. +4. Under `Firewall rules`, uncheck `Allow public access from any Azure service within Azure to this server`. +5. Click `Save`. + +### From Azure CLI + +Using the firewall rule name from the `Audit from Azure CLI` steps, use the below command to delete the `AllowAllAzureServicesAndResourcesWithinAzureIps` rule for PostgreSQL flexible server: + +```bash +az postgres flexible-server firewall-rule delete --resource-group --name --rule-name +``` + +Type `y` and press `enter` to confirm. + +### From PowerShell + +Using the firewall rule name from the `Audit from PowerShell` steps, use the below command to delete the `AllowAllAzureServicesAndResourcesWithinAzureIps` rule for PostgreSQL flexible server: + +```bash +Remove-AzPostgreSqlFlexibleServerFirewallRule -ResourceGroupName -ServerName -Name +``` + +### Default Value + +The Azure Postgres firewall is set to block all access by default. diff --git a/cis_v300/docs/cis_v300_5_2_6.md b/cis_v300/docs/cis_v300_5_2_6.md new file mode 100644 index 00000000..f94b62f7 --- /dev/null +++ b/cis_v300/docs/cis_v300_5_2_6.md @@ -0,0 +1,38 @@ +## Description + +Enable `log_connections` on `PostgreSQL single servers`. + +**NOTE:** This recommendation currently only applies to Single Server, not Flexible Server. See additional information below for details about the planned retirement of Azure PostgreSQL Single Server. + +Enabling `log_connections` helps PostgreSQL Database to log attempted connection to the server, as well as successful completion of client authentication. Log data can be used to identify, troubleshoot, and repair configuration errors and suboptimal performance. + +## Remediation + +### From Azure Portal + +1. Login to Azure Portal using https://portal.azure.com. +2. Go to `Azure Database for PostgreSQL servers`. +3. For each database, under `Settings`, click `Server parameters`. +4. In the filter bar, type `log_connections`. +5. Set `log_connections` to `ON`. +6. Click `Save`. + +### From Azure CLI + +Use the below command to update `log_connections` configuration. + +```bash +az postgres server configuration set --resource-group --server-name --name log_connections --value on +``` + +### From PowerShell + +Use the below command to update `log_connections` configuration. + +```bash +Update-AzPostgreSqlConfiguration -ResourceGroupName -ServerName -Name log_connections -Value on +``` + +### Default Value + +By default `log_connections` is enabled (set to `on`). diff --git a/cis_v300/docs/cis_v300_5_2_7.md b/cis_v300/docs/cis_v300_5_2_7.md new file mode 100644 index 00000000..787a9370 --- /dev/null +++ b/cis_v300/docs/cis_v300_5_2_7.md @@ -0,0 +1,38 @@ +## Description + +Enable `log_disconnections` on `PostgreSQL Servers`. + +**NOTE:** This recommendation currently only applies to Single Server, not Flexible Server. See additional information below for details about the planned retirement of Azure PostgreSQL Single Server. + +Enabling `log_disconnections` helps PostgreSQL Database to `Logs end of a session`, including duration, which in turn generates query and error logs. Query and error logs can be used to identify, troubleshoot, and repair configuration errors and sub-optimal performance. + +## Remediation + +### From Azure Portal + +1. From Azure Home select the Portal Menu. +2. Go to `Azure Database` for `PostgreSQL servers`. +3. For each database, under `Settings`, click `Server parameters`. +4. Search for `log_disconnections`. +5. Set `log_disconnections` to `ON`. +6. Click `Save`. + +### From Azure CLI + +Use the below command to update `log_disconnections` configuration. + +```bash +az postgres server configuration set --resource-group --server-name --name log_disconnections --value on +``` + +### From PowerShell + +Use the below command to update `log_disconnections` configuration. + +```bash +Update-AzPostgreSqlConfiguration -ResourceGroupName -ServerName -Name log_disconnections -Value on +``` + +### Default Value + +By default `log_disconnections` is disabled (set to `off`). diff --git a/cis_v300/docs/cis_v300_5_2_8.md b/cis_v300/docs/cis_v300_5_2_8.md new file mode 100644 index 00000000..bcb8d618 --- /dev/null +++ b/cis_v300/docs/cis_v300_5_2_8.md @@ -0,0 +1,29 @@ +## Description + +Azure Database for PostgreSQL servers should be created with 'infrastructure double encryption' enabled. + +**NOTE:** This recommendation currently only applies to Single Server, not Flexible Server. See additional information below for details about the planned retirement of Azure PostgreSQL Single Server. + +If Double Encryption is enabled, another layer of encryption is implemented at the hardware level before the storage or network level. Information will be encrypted before it is even accessed, preventing both interception of data in motion if the network layer encryption is broken and data at rest in system resources such as memory or processor cache. Encryption will also be in place for any backups taken of the database, so the key will secure access the data in all forms. For the most secure implementation of key based encryption, it is recommended to use a Customer Managed asymmetric RSA 2048 Key in Azure Key Vault. + +## Remediation + +It is not possible to enable 'infrastructure double encryption' on an existing Azure Database for PostgreSQL server. +The remediation steps detail the creation of a new Azure Database for PostgreSQL server with 'infrastructure double encryption' enabled. + +### From Azure Portal + +1. Go through the normal process of database creation. +2. On step 2 titled `Additional settings` ensure that `Infrastructure double encryption enabled` is checked. +3. Acknowledge that you understand this will impact database performance. +4. Finish database creation as normal. + +### From Azure CLI + +```bash +az postgres server create --resource-group --name --location --admin-user --admin-password --sku-name GP_Gen4_2 --version 11 --infrastructure-encryption Enabled +``` + +### Default Value + +By Default, Double Encryption is disabled. diff --git a/cis_v300/docs/cis_v300_5_3.md b/cis_v300/docs/cis_v300_5_3.md new file mode 100644 index 00000000..5afc332e --- /dev/null +++ b/cis_v300/docs/cis_v300_5_3.md @@ -0,0 +1,9 @@ +## Overview + +This section covers security best practice recommendations for Azure MySQL Database Servers. + +Azure Product Page: https://azure.microsoft.com/en-us/products/mysql/ + +**RETIREMENT of Azure MySQL Single Server:** Azure MySQL Single Server is slated for retirement by September 16, 2024. Azure MySQL Flexible Server is the newer deployment standard and is unaffected. Please use these resources to consider and prepare for migration: +- https://learn.microsoft.com/en-us/azure/mysql/migrate/whats-happening-to-mysql-single-server. +- https://learn.microsoft.com/en-us/azure/mysql/migrate/how-to-decide-on-right-migration-tools. diff --git a/cis_v300/docs/cis_v300_5_3_1.md b/cis_v300/docs/cis_v300_5_3_1.md new file mode 100644 index 00000000..08063696 --- /dev/null +++ b/cis_v300/docs/cis_v300_5_3_1.md @@ -0,0 +1,36 @@ +## Description + +Enable `require_secure_transport` on `MySQL flexible servers`. + +SSL connectivity helps to provide a new layer of security by connecting database server to client applications using Secure Sockets Layer (SSL). Enforcing SSL connections between database server and client applications helps protect against "man in the middle" attacks by encrypting the data stream between the server and application. + +## Remediation + +### From Azure Portal + +1. Login to Azure Portal using https://portal.azure.com. +2. Go to `Azure Database for MySQL flexible servers`. +3. For each database, under `Settings`, click `Server parameters`. +4. In the filter bar, type `require_secure_transport`. +5. Set the `VALUE` for `require_secure_transport` to `ON`. +6. Click `Save`. + +### From Azure CLI + +Use the below command to enable `require_secure_transport`: + +```bash +az mysql flexible-server parameter set --resource-group --server-name --name require_secure_transport --value on +``` + +### From PowerShell + +Use the below command to enable `require_secure_transport`: + +```bash +Update-AzMySqlFlexibleServerConfiguration -ResourceGroupName -ServerName -Name require_secure_transport -Value on +``` + +### Default Value + +Azure Database for MySQL when provisioned through the Azure portal or CLI will require SSL connections by default. diff --git a/cis_v300/docs/cis_v300_5_3_2.md b/cis_v300/docs/cis_v300_5_3_2.md new file mode 100644 index 00000000..9ab16e2c --- /dev/null +++ b/cis_v300/docs/cis_v300_5_3_2.md @@ -0,0 +1,37 @@ +## Description + +Ensure `tls_version` on `MySQL flexible servers` is set to use TLS version 1.2 or higher. + +TLS connectivity helps to provide a new layer of security by connecting database server to client applications using Transport Layer Security (TLS). Enforcing TLS connections between database server and client applications helps protect against "man in the middle" attacks by encrypting the data stream between the server and application. + +## Remediation + +### From Azure Portal + +1. Login to Azure Portal using [https://portal.azure.com](https://portal.azure.com). +2. Go to `Azure Database for MySQL flexible servers`. +3. For each database, under `Settings`, click `Server parameters`. +4. In the filter bar, type `tls_version`. +5. Click on the VALUE dropdown next to `tls_version`, and check `TLSv1.2` (or higher). +6. Uncheck anything lower than `TLSv1.2`. +7. Click `Save`. + +### From Azure CLI + +Use the below command to update MySQL flexible servers to use TLS version 1.2: + +```bash +az mysql flexible-server parameter set --resource-group --server-name --name tls_version --value TLSv1.2 +``` + +### From PowerShell + +Use the below command to update MySQL flexible servers to use TLS version 1.2: + +```bash +Update-AzMySqlFlexibleServerConfiguration -ResourceGroupName -ServerName -Name tls_version -Value TLSv1.2 +``` + +### Default Value + +By default, TLS is set to v1.2 for MySQL Flexible servers. diff --git a/cis_v300/docs/cis_v300_5_3_3.md b/cis_v300/docs/cis_v300_5_3_3.md new file mode 100644 index 00000000..5b7ab208 --- /dev/null +++ b/cis_v300/docs/cis_v300_5_3_3.md @@ -0,0 +1,48 @@ +## Description + +Enable `audit_log_enabled` on `MySQL flexible servers`. + +Enabling `audit_log_enabled` helps MySQL Database to log items such as connection attempts to the server, DDL/DML access, and more. Log data can be used to identify, troubleshoot, and repair configuration errors and suboptimal performance. + +## Remediation + +### From Azure Portal + +Part 1 - Turn on audit logs + +1. Login to Azure Portal using [https://portal.azure.com](https://portal.azure.com). +2. Go to `Azure Database for MySQL flexible servers`. +3. For each database, under `Settings`, click `Server parameters`. +4. Set `audit_log_enabled` to `ON`. +5. Click `Save`. + +Part 2 - Capture audit logs (diagnostic settings is for example only, send these logs to the appropriate data sink for your logging needs) + +1. Under Monitoring, select `Diagnostic settings`. +2. Select `+ Add diagnostic setting`. +3. Provide a diagnostic setting name. +4. Under Categories, select `MySQL Audit Logs`. +5. Specify destination details. +6. Click `Save`. + +It may take up to 10 minutes for the logs to appear in the configured destination. + +### From Azure CLI + +Use the below command to enable `audit_log_enabled `: + +```bash +az mysql flexible-server parameter set --resource-group --server-name --name audit_log_enabled --value on +``` + +### From PowerShell + +Use the below command to enable `audit_log_enabled `: + +```bash +Update-AzMySqlFlexibleServerConfiguration -ResourceGroupName -ServerName -Name audit_log_enabled -Value on +``` + +### Default Value + +audit_log_enabled is set to OFF by default. diff --git a/cis_v300/docs/cis_v300_5_3_4.md b/cis_v300/docs/cis_v300_5_3_4.md new file mode 100644 index 00000000..1d288171 --- /dev/null +++ b/cis_v300/docs/cis_v300_5_3_4.md @@ -0,0 +1,45 @@ +## Description + +Set `audit_log_events` to include `CONNECTION` on `MySQL flexible servers`. + +Enabling `CONNECTION` helps MySQL Database to log items such as successful and failed connection attempts to the server. Log data can be used to identify, troubleshoot, and repair configuration errors and suboptimal performance. + +## Remediation + +### From Azure Portal + +1. Login to Azure Portal using https://portal.azure.com. +2. Go to `Azure Database for MySQL flexible servers`. +3. For each database, under `Settings`, click `Server parameters`. +4. In the filter bar, type `audit_log`. +5. Set `audit_log_enabled` to `ON`. +6. In the drop-down next to `audit_log_events`, check `CONNECTION`. +7. Click `Save`. +8. Under `Monitoring`, select `Diagnostic settings`. +9. Select `+ Add diagnostic setting`. +10. Provide a diagnostic setting name. +11. Under `Categories`, select `MySQL Audit Logs`. +12. Specify destination details. +13. Click `Save`. + +It may take up to 10 minutes for the logs to appear in the configured destination. + +### From Azure CLI + +Use the below command to set `audit_log_events` to `CONNECTION`: + +```bash +az mysql flexible-server parameter set --resource-group --server-name --name audit_log_events --value CONNECTION +``` + +### From PowerShell + +Use the below command to set `audit_log_events` to `CONNECTION`: + +```bash +Update-AzMySqlFlexibleServerConfiguration -ResourceGroupName -ServerName -Name audit_log_events -Value CONNECTION +``` + +### Default Value + +By default `audit_log_events` is set to `CONNECTION`. diff --git a/cis_v300/docs/cis_v300_5_4.md b/cis_v300/docs/cis_v300_5_4.md new file mode 100644 index 00000000..f621122b --- /dev/null +++ b/cis_v300/docs/cis_v300_5_4.md @@ -0,0 +1,5 @@ +## Overview + +This section covers security best practice recommendations for Azure Cosmos DB Database Servers. + +Azure Product Page: https://azure.microsoft.com/en-us/products/cosmos-db/ diff --git a/cis_v300/docs/cis_v300_5_4_1.md b/cis_v300/docs/cis_v300_5_4_1.md new file mode 100644 index 00000000..7f4e6497 --- /dev/null +++ b/cis_v300/docs/cis_v300_5_4_1.md @@ -0,0 +1,22 @@ +## Description + +Limiting your Cosmos DB to only communicate on whitelisted networks lowers its attack footprint. + +Selecting certain networks for your Cosmos DB to communicate restricts the number of networks including the internet that can interact with what is stored within the database. + +## Remediation + +### From Azure Portal + +1. Open the portal menu. +2. Select the Azure Cosmos DB blade. +3. Select a Cosmos DB account to audit. +4. Select `Networking`. +5. Under `Public network access`, select `Selected networks`. +6. Under `Virtual networks`, select `+ Add existing virtual network` or `+ Add a new virtual network`. +7. For existing networks, select subscription, virtual network, subnet and click `Add`. For new networks, provide a name, update the default values if required, and click `Create`. +8. Click `Save`. + +### Default Value + +By default, Cosmos DBs are set to have access all networks. diff --git a/cis_v300/docs/cis_v300_5_4_2.md b/cis_v300/docs/cis_v300_5_4_2.md new file mode 100644 index 00000000..808acdea --- /dev/null +++ b/cis_v300/docs/cis_v300_5_4_2.md @@ -0,0 +1,32 @@ +## Description + +Private endpoints limit network traffic to approved sources. + +For sensitive data, private endpoints allow granular control of which services can communicate with Cosmos DB and ensure that this network traffic is private. You set this up on a case by case basis for each service you wish to be connected. + +## Remediation + +### From Azure Portal + +1. Open the portal menu. +2. Select the Azure Cosmos DB blade. +3. Select the Azure Cosmos DB account. +4. Select `Networking`. +5. Select `Private access`. +6. Click `+ Private Endpoint`. +7. Provide a Name. +8. Click `Next`. +9. From the Resource type drop down, select `Microsoft.AzureCosmosDB/databaseAccounts`. +10. From the Resource drop down, select the Cosmos DB account. +11. Click `Next`. +12. Provide appropriate Virtual Network details. +13. Click `Next`. +14. Provide appropriate DNS details. +15. Click `Next`. +16. Optionally provide Tags. +17. Click `Next : Review + create`. +18. Click `Create`. + +### Default Value + +By default Cosmos DB does not have private endpoints enabled and its traffic is public to the network. diff --git a/cis_v300/docs/cis_v300_5_4_3.md b/cis_v300/docs/cis_v300_5_4_3.md new file mode 100644 index 00000000..59805c54 --- /dev/null +++ b/cis_v300/docs/cis_v300_5_4_3.md @@ -0,0 +1,26 @@ +## Description + +Cosmos DB can use tokens or Entra ID for client authentication which in turn will use Azure RBAC for authorization. Using Entra ID is significantly more secure because Entra ID handles the credentials and allows for MFA and centralized management, and the Azure RBAC is better integrated with the rest of Azure. + +Entra ID client authentication is considerably more secure than token-based authentication because the tokens must be persistent at the client. Entra ID does not require this. + +## Remediation + +Map all the resources that currently have access to the Azure Cosmos DB account with keys or access tokens. +Create an Entra ID identity for each of these resources: +- For Azure resources, you can create a managed identity. You may choose between system-assigned and user-assigned managed identities. + +- For non-Azure resources, create an Entra ID identity. Grant each Entra ID identity the minimum permission it requires. When possible, we recommend you use one of the 2 built-in role definitions: Cosmos DB Built-in Data Reader or Cosmos DB Built-in Data Contributor. Validate that the new resource is functioning correctly. After new permissions are granted to identities, it may take a few hours until they propagate. When all resources are working correctly with the new identities, continue to the next step. + +### From PowerShell + +```bash +$cosmosdbname = "" +$resourcegroup = "" +az cosmosdb show --name $cosmosdbname --resource-group $resourcegroup | ConvertFrom-Json +az resource update --ids $cosmosdb.id --set properties.disableLocalAuth=true --latest-include-preview +``` + +### Default Value + +The default is to use tokens/keys for client authentication. diff --git a/cis_v300/docs/cis_v300_6.md b/cis_v300/docs/cis_v300_6.md new file mode 100644 index 00000000..6d3508b9 --- /dev/null +++ b/cis_v300/docs/cis_v300_6.md @@ -0,0 +1,23 @@ +## Overview + +This section covers security recommendations to follow for logging and monitoring policies on an Azure Subscription. + +**Scoping: A necessary exercise for effective and efficient use of Logging and Monitoring** + +For recommendations contained in this section, it is crucial that your organization consider and settle on the scope of application for each recommendation individually. The scope of application cannot be realistically written in a generic prescriptive way within these recommendations, so a scoping exercise is strongly recommended. A scoping exercise will help you determine which resources are "in scope" and will receive partial or complete logging and monitoring treatment, and which resources are "out of scope" and will not receive any logging and monitoring treatment. + +Your objectives with the scoping exercise should be to: +- Produce a clear classification of resources. +- Understand the control requirements of any relevant security or compliance frameworks. +- Ensure the appropriate personnel can detect and react to threats. +- Ensure relevant resources have a historical register for accountability and investigation. +- Minimize alert fatigue and cost. + +Release Environments provide a helpful context for understanding scope from a DevOps perspective. For example: + +1. Production Environment +2. Staging Environment +3. Testing Environment +4. Development Environment + +While resources considered in the scope of a Production Environment might have a full set of recommendations applied for logging and monitoring, other release environments might have a limited set of recommendations applied for the sake of accountability. The names of these environments and which resources are in the scope of each environment will vary from one organization to another. diff --git a/cis_v300/docs/cis_v300_6_1.md b/cis_v300/docs/cis_v300_6_1.md new file mode 100644 index 00000000..f8d4c37c --- /dev/null +++ b/cis_v300/docs/cis_v300_6_1.md @@ -0,0 +1,15 @@ +## Overview + +The Azure Diagnostic Settings capture control/management activities performed on a subscription or Azure AD Tenant. By default, the Azure Portal retains activity logs only for 90 days. The Diagnostic Settings define the type of events that are stored or streamed and the outputs—storage account, log analytics workspace, event hub, and others. The Diagnostic Settings, if configured properly, can ensure that all logs are retained for longer duration. This section has recommendations for correctly configuring the Diagnostic Settings so that all logs captured are retained for longer periods. + +### Azure Subscriptions + +When configuring Diagnostic Settings, you may choose to export in one of four ways in which you need to ensure appropriate data retention. The options are Log Analytics workspace, Event Hub, Storage Account, and Partner Solutions. It is important to ensure you are aware and have set retention as your organization sees fit. + +### Azure AD Logs + +In order to retain sign in logs, user account changes, application provisioning logs, or other logs that are visible to only on the Tenant in Azure AD, separate Diagnostic settings must be specified. + +### Deployment by Policy + +Deploying Azure diagnostics should ideally be done by policy to ensure a consistent configuration, Microsoft provide a full set of policies for all diagnostic capable resource types in their github repository. If you chose to deploy by policy, it is best to route the diagnostics to a Log Analytics Workspace so that they can be used in Azure Monitor or Azure Sentinel. Be aware that this has a cost attached to it. Future versions of the CIS Azure Foundations Benchmark will aim to cover the use of policy in greater detail. diff --git a/cis_v300/docs/cis_v300_6_1_1.md b/cis_v300/docs/cis_v300_6_1_1.md new file mode 100644 index 00000000..0dc5e3fa --- /dev/null +++ b/cis_v300/docs/cis_v300_6_1_1.md @@ -0,0 +1,83 @@ +## Description + +Enable Diagnostic settings for exporting activity logs. +Diagnostic settings are available for each individual resource within a subscription. Settings should be configured for all appropriate resources for your environment. + +A diagnostic setting controls how a diagnostic log is exported. By default, logs are retained only for 90 days. Diagnostic settings should be defined so that logs can be exported and stored for a longer duration in order to analyze security activities within an Azure subscription. + +## Remediation + +### From Azure Portal + +To enable Diagnostic Settings on a Subscription: + +1. Go to `Monitor`. +2. Click on `Activity log`. +3. Click on `Export Activity Logs`. +4. Click `+ Add diagnostic setting`. +5. Enter a `Diagnostic setting name`. +6. Select `Categories` for the diagnostic setting. +7. Select the appropriate `Destination details` (this may be Log Analytics, Storage Account, Event Hub, or Partner solution). +8. Click `Save`. + +To enable Diagnostic Settings on a specific resource: + +1. Go to `Monitoring`. +2. Click `Diagnostic settings`. +3. Select `Add diagnostic setting`. +4. Enter a `Diagnostic setting name`. +5. Select the appropriate log, metric, and destination (this may be Log Analytics, Storage Account, Event Hub, or Partner solution). +6. Click `Save`. + +Repeat these step for all resources as needed. + +### From Azure CLI + +To configure Diagnostic Settings on a Subscription: + +```bash +az monitor diagnostic-settings subscription create --subscription --name --location <[--event-hub --event-hub-auth-rule ] [--storage-account ] [--workspace ] --logs "" (e.g. [{category:Security,enabled:true},{category:Administrative,enabled:true},{category:Alert,enabled:true},{category:Policy,enabled:true}]) +``` + +To configure Diagnostic Settings on a specific resource: + +```bash +az monitor diagnostic-settings create --subscription --resource --name <[--event-hub --event-hub-rule ] [--storage-account ] [--workspace ] --logs --metrics +``` + +### From PowerShell + +To configure Diagnostic Settings on a subscription: + +```bash +$logCategories = @(); +$logCategories += New-AzDiagnosticSettingSubscriptionLogSettingsObject -Category Administrative -Enabled $true +$logCategories += New-AzDiagnosticSettingSubscriptionLogSettingsObject -Category Security -Enabled $true +$logCategories += New-AzDiagnosticSettingSubscriptionLogSettingsObject -Category ServiceHealth -Enabled $true +$logCategories += New-AzDiagnosticSettingSubscriptionLogSettingsObject -Category Alert -Enabled $true +$logCategories += New-AzDiagnosticSettingSubscriptionLogSettingsObject -Category Recommendation -Enabled $true +$logCategories += New-AzDiagnosticSettingSubscriptionLogSettingsObject -Category Policy -Enabled $true +$logCategories += New-AzDiagnosticSettingSubscriptionLogSettingsObject -Category Autoscale -Enabled $true +$logCategories += New-AzDiagnosticSettingSubscriptionLogSettingsObject -Category ResourceHealth -Enabled $true + +New-AzSubscriptionDiagnosticSetting -SubscriptionId -Name <[-EventHubAuthorizationRule -EventHubName ] [-StorageAccountId ] [-WorkSpaceId ] [-MarketplacePartner ID ]> -Log $logCategories +``` + +To configure Diagnostic Settings on a specific resource: + +```bash +$logCategories = @() +$logCategories += New-AzDiagnosticSettingLogSettingsObject -Category -Enabled $true + +Repeat command and variable assignment for each Log category specific to the resource where this Diagnostic Setting will get configured. + +$metricCategories = @() +$metricCategories += New-AzDiagnosticSettingMetricSettingsObject -Enabled $true [-Category ] [-RetentionPolicyDay ] [-RetentionPolicyEnabled $true] + +Repeat command and variable assignment for each Metric category or use the 'AllMetrics' category. + +New-AzDiagnosticSetting -ResourceId -Name -Log $logCategories -Metric $metricCategories [-EventHubAuthorizationRuleId -EventHubName ] [-StorageAccountId ] [-WorkspaceId ] [-MarketplacePartnerId ]> + +### Default Value + +By default, diagnostic setting is not set. diff --git a/cis_v300/docs/cis_v300_6_1_2.md b/cis_v300/docs/cis_v300_6_1_2.md new file mode 100644 index 00000000..7caafa7e --- /dev/null +++ b/cis_v300/docs/cis_v300_6_1_2.md @@ -0,0 +1,42 @@ +## Description + +**Prerequisite**: A Diagnostic Setting must exist. If a Diagnostic Setting does not exist, the navigation and options within this recommendation will not be available. Please review the recommendation at the beginning of this subsection titled: "Ensure that a 'Diagnostic Setting' exists." + +The diagnostic setting should be configured to log the appropriate activities from the control/management plane. + +A diagnostic setting controls how the diagnostic log is exported. Capturing the diagnostic setting categories for appropriate control/management plane activities allows proper alerting. + +## Remediation + +### From Azure Portal + +1. Go to `Monitor`. +2. Click `Activity log`. +3. Click on `Export Activity Logs`. +4. Select the `Subscription` from the drop down menu. +5. Click `Edit setting` next to a diagnostic setting. +6. Check the following categories: `Administrative, Alert, Policy, and Security`. +7. Choose the destination details according to your organization's needs. +8. Click `Save`. + +### From Azure CLI + +```bash +az monitor diagnostic-settings subscription create --subscription --name --location <[--event-hub --event-hub-auth-rule ] [--storage-account ] [--workspace ] --logs "[{category:Security,enabled:true},{category:Administrative,enabled:true},{category:Alert,enabled:true},{category:Policy,enabled:true}]" +``` + +### From Powershell + +```bash +$logCategories = @(); +$logCategories += New-AzDiagnosticSettingSubscriptionLogSettingsObject -Category Administrative -Enabled $true +$logCategories += New-AzDiagnosticSettingSubscriptionLogSettingsObject -Category Security -Enabled $true +$logCategories += New-AzDiagnosticSettingSubscriptionLogSettingsObject -Category Alert -Enabled $true +$logCategories += New-AzDiagnosticSettingSubscriptionLogSettingsObject -Category Policy -Enabled $true + +New-AzSubscriptionDiagnosticSetting -SubscriptionId -Name <[-EventHubAuthorizationRule -EventHubName ] [-StorageAccountId ] [-WorkSpaceId ] [-MarketplacePartner ID ]> -Log $logCategories +``` + +### Default Value + +When the diagnostic setting is created using Azure Portal, by default no categories are selected. diff --git a/cis_v300/docs/cis_v300_6_1_3.md b/cis_v300/docs/cis_v300_6_1_3.md new file mode 100644 index 00000000..da5a7998 --- /dev/null +++ b/cis_v300/docs/cis_v300_6_1_3.md @@ -0,0 +1,36 @@ +## Description + +Storage accounts with the activity log exports can be configured to use Customer Managed Keys (CMK). + +Configuring the storage account with the activity log export container to use CMKs provides additional confidentiality controls on log data, as a given user must have read permission on the corresponding storage account and must be granted decrypt permission by the CMK. + +## Remediation + +### From Azure Portal + +1. Go to `Monitor`. +2. Select `Activity log`. +3. Select `Export Activity Logs`. +4. Select a `Subscription`. +5. Note the name of the `Storage Account` for the diagnostic setting. +6. Navigate to `Storage accounts`. +7. Click on the storage account. +8. Under `Security + networking`, click `Encryption`. +9. Next to `Encryption type`, select `Customer-managed keys`. +10. Complete the steps to configure a customer-managed key for encryption of the storage account. + +### From Azure CLI + +```bash +az storage account update --name --resource-group --encryption-key-source=Microsoft.Keyvault --encryption-key-vault --encryption-key-name --encryption-key-version +``` + +### From PowerShell + +```bash +Set-AzStorageAccount -ResourceGroupName -Name -KeyvaultEncryption -KeyVaultUri -KeyName +``` + +### Default Value + +By default, for a storage account `keySource` is set to `Microsoft.Storage` allowing encryption with vendor Managed key and not a Customer Managed Key. diff --git a/cis_v300/docs/cis_v300_6_1_4.md b/cis_v300/docs/cis_v300_6_1_4.md new file mode 100644 index 00000000..a03f8cce --- /dev/null +++ b/cis_v300/docs/cis_v300_6_1_4.md @@ -0,0 +1,59 @@ +## Description + +Enable AuditEvent logging for key vault instances to ensure interactions with key vaults are logged and available. + +Monitoring how and when key vaults are accessed, and by whom, enables an audit trail of interactions with confidential information, keys, and certificates managed by Azure Key Vault. Enabling logging for Key Vault saves information in a user provided destination of either an Azure storage account or Log Analytics workspace. The same destination can be used for collecting logs for multiple Key Vaults. + +## Remediation + +### From Azure Portal + +1. Go to `Key vaults`. +2. Select a Key vault. +3. Under `Monitoring`, select `Diagnostic settings`. +4. Click `Edit setting` to update an existing diagnostic setting, or `Add diagnostic setting` to create a new one. +5. If creating a new diagnostic setting, provide a name. +6. Configure an appropriate destination. +7. Under `Category groups`, check `audit` and `allLogs`. +8. Click `Save`. + +### From Azure CLI + +To update an existing `Diagnostic Settings` + +```bash +az monitor diagnostic-settings update --name "" --resource +``` + +To create a new `Diagnostic Settings` + +```bash +az monitor diagnostic-settings create --name "" --resource --logs "[{category:audit,enabled:true},{category:allLogs,enabled:true}]" --metrics "[{category:AllMetrics,enabled:true}]" <[--event-hub --event-hub-rule | --storage-account |--workspace | --marketplace-partner-id ]> +``` + +### From PowerShell + +Create the `Log` settings object + +```bash +$logSettings = @() +$logSettings += New-AzDiagnosticSettingLogSettingsObject -Enabled $true -Category audit +$logSettings += New-AzDiagnosticSettingLogSettingsObject -Enabled $true -Category allLogs +``` + +Create the `Metric` settings object + +```bash +$metricSettings = @() +$metricSettings += New-AzDiagnosticSettingMetricSettingsObject -Enabled $true -Category AllMetrics +``` + +Create the `Diagnostic Settings` for each `Key Vault` + +```bash +New-AzDiagnosticSetting -Name "" -ResourceId -Log $logSettings -Metric $metricSettings [-StorageAccountId | -EventHubName -EventHubAuthorizationRuleId | -WorkSpaceId | -MarketPlacePartnerId ] +``` + +### Default Value + +By default, Diagnostic AuditEvent logging is not enabled for Key Vault instances. diff --git a/cis_v300/docs/cis_v300_6_1_5.md b/cis_v300/docs/cis_v300_6_1_5.md new file mode 100644 index 00000000..5291afc7 --- /dev/null +++ b/cis_v300/docs/cis_v300_6_1_5.md @@ -0,0 +1,37 @@ +## Description + +Ensure that network flow logs are captured and fed into a central log analytics workspace. + +Network Flow Logs provide valuable insight into the flow of traffic around your network and feed into both Azure Monitor and Azure Sentinel (if in use), permitting the generation of visual flow diagrams to aid with analyzing for lateral movement, etc. + +## Remediation + +### From Azure Portal + +1. Navigate to `Network Watcher`. +2. Under `Logs`, select `Flow logs`. +3. Select `+ Create`. +4. Select the desired Subscription. +5. For `Flow log type`, select `Network security group`. +6. Select `+ Select target resource`. +7. Select `Network security group`. +8. Select a network security group. +9. Click `Confirm selection`. +10. Select or create a new Storage Account. +11. If using a v2 storage account, input the retention in days to retain the log. +12. Click `Next`. +13. Under `Analytics`, for `Flow log version`, select `Version 2`. +14. Check the box next to `Enable traffic analytics`. +15. Select a processing interval. +16. Select a `Log Analytics Workspace`. +17. Select `Next`. +18. Optionally add Tags. +19. Select `Review + create`. +20. Select `Create`. + +**Warning** +The remediation policy creates remediation deployment and names them by concatenating the subscription name and the resource group name. The MAXIMUM permitted length of a deployment name is 64 characters. Exceeding this will cause the remediation task to fail. + +### Default Value + +By default Network Security Group logs are not sent to Log Analytics. diff --git a/cis_v300/docs/cis_v300_6_1_6.md b/cis_v300/docs/cis_v300_6_1_6.md new file mode 100644 index 00000000..3f4790f8 --- /dev/null +++ b/cis_v300/docs/cis_v300_6_1_6.md @@ -0,0 +1,23 @@ +## Description + +Enable AppServiceHTTPLogs diagnostic log category for Azure App Service instances to ensure all http requests are captured and centrally logged. + +Capturing web requests can be important supporting information for security analysts performing monitoring and incident response activities. Once logging, these logs can be ingested into SIEM or other central aggregation point for the organization. + +## Remediation + +### From Azure Portal + +1. Go to `App Services`. + +For each `App Service`: + +2. Under `Monitoring`, go to `Diagnostic settings`. +3. To update an existing diagnostic setting, click `Edit setting` against the setting. To create a new diagnostic setting, click `Add diagnostic setting` and provide a name for the new setting. +4. Check the checkbox next to `HTTP logs`. +5. Configure a destination based on your specific logging consumption capability (for example Stream to an event hub and then consuming with SIEM integration for Event Hub logging). +6. Click `Save`. + +### Default Value + +Not configured. diff --git a/cis_v300/docs/cis_v300_6_2.md b/cis_v300/docs/cis_v300_6_2.md new file mode 100644 index 00000000..188011cc --- /dev/null +++ b/cis_v300/docs/cis_v300_6_2.md @@ -0,0 +1,19 @@ +## Overview + +The recommendations provided in this section are intended to provide entry-level alerting for crucial activities on a tenant account. These recommended activities **should** be tuned to your needs. By default, each of these Activity Log Alerts tends to guide the reader to alerting at the "Subscription-wide" level which will capture and alert on rules triggered by all resources and resource groups contained within a subscription. This is not an ideal rule set for Alerting within larger and more complex organizations. + +While this section provides recommendations for the creation of **Activity Log Alerts** specifically, Microsoft Azure supports four different types of alerts: +- Metric Alerts +- Log Alerts +- Activity Log Alerts +- Smart Detection Alerts + +All Azure services (Microsoft provided or otherwise) that can generate alerts are assigned a "Resource provider namespace" when they are registered in an Azure tenant. The recommendations in this section are in no way exhaustive of the plethora of available "Providers" or "Resource Types." The Resource Providers that are registered in your Azure Tenant can be located in your Subscription. Each registered Provider in your environment **may** have available "Conditions" to raise alerts via Activity Log Alerts. These providers should be considered for inclusion in Activity Log Alert rules of your own making. + +To view the registered resource providers in your Subscription(s), use this guide: + +- [https://docs.microsoft.com/en-us/azure/azure-resource-manager/management/resource-providers-and-types](https://docs.microsoft.com/en-us/azure/azure-resource-manager/management/resource-providers-and-types) + +If you wish to create custom alerting rules for Activity Log Alerts or other alert types, please refer to Microsoft documentation: + +- [https://docs.microsoft.com/en-us/azure/azure-monitor/alerts/alerts-create-new-alert-rule](https://docs.microsoft.com/en-us/azure/azure-monitor/alerts/alerts-create-new-alert-rule) diff --git a/cis_v300/docs/cis_v300_6_2_1.md b/cis_v300/docs/cis_v300_6_2_1.md new file mode 100644 index 00000000..15229b29 --- /dev/null +++ b/cis_v300/docs/cis_v300_6_2_1.md @@ -0,0 +1,67 @@ +## Description + +Create an activity log alert for the Create Policy Assignment event. + +Monitoring for create policy assignment events gives insight into changes done in "Azure policy - assignments" and can reduce the time it takes to detect unsolicited changes. + +## Remediation + +### From Azure Portal + +1. Navigate to the `Monitor` blade. +2. Select `Alerts`. +3. Select `Create`. +4. Select `Alert rule`. +5. Choose a subscription. +6. Select `Apply`. +7. Select the `Condition` tab. +8. Click `See all signals`. +9. Select `Create policy assignment (Policy assignment)`. +10. Click `Apply`. +11. Select the `Actions` tab. +12. Click `Select action groups` to select an existing action group, or `Create action group` to create a new action group. +13. Follow the prompts to choose or create an action group. +14. Select the `Details` tab. +15. Select a `Resource group`, provide an `Alert rule name` and an optional `Alert rule description`. +16. Click `Review + create`. +17. Click `Create`. + +### From Azure CLI + +```bash +az monitor activity-log alert create --resource-group "" --condition category=Administrative and operationName=Microsoft.Authorization/policyAssignments/write and level= --scope "/subscriptions/" --name "" --subscription --action-group +``` + +### From PowerShell + +Create the `conditions` object. + +```bash +$conditions = @() +$conditions += New-AzActivityLogAlertAlertRuleAnyOfOrLeafConditionObject -Equal Administrative -Field category +$conditions += New-AzActivityLogAlertAlertRuleAnyOfOrLeafConditionObject -Equal Microsoft.Authorization/policyAssignments/write -Field operationName +$conditions += New-AzActivityLogAlertAlertRuleAnyOfOrLeafConditionObject -Equal Verbose -Field level +``` + +Get the `Action Group` information and store it in a variable, then create a new `Action` object. + +```bash +$actionGroup = Get-AzActionGroup -ResourceGroupName -Name +$actionObject = New-AzActivityLogAlertActionGroupObject -Id $actionGroup.Id +``` + +Create the `Scope` variable. + +```bash +$scope = "/subscriptions/" +``` + +Create the `Activity Log Alert Rule` for `Microsoft.Authorization/policyAssignments/write` + +```bash +New-AzActivityLogAlert -Name "" -ResourceGroupName "" -Condition $conditions -Scope $scope -Location global -Action $actionObject -Subscription -Enabled $true +``` + +### Default Value + +By default, no monitoring alerts are created. diff --git a/cis_v300/docs/cis_v300_6_2_10.md b/cis_v300/docs/cis_v300_6_2_10.md new file mode 100644 index 00000000..4033c753 --- /dev/null +++ b/cis_v300/docs/cis_v300_6_2_10.md @@ -0,0 +1,67 @@ +## Description + +Create an activity log alert for the Delete Public IP Address rule. + +Monitoring for Delete Public IP Address events gives insight into network access changes and may reduce the time it takes to detect suspicious activity. + +## Remediation + +### From Azure Portal + +1. Navigate to the `Monitor` blade. +2. Select `Alerts`. +3. Select `Create`. +4. Select `Alert rule`. +5. Choose a subscription. +6. Select `Apply`. +7. Select the `Condition` tab. +8. Click `See all signals`. +9. Select `Delete Public Ip Address (Public Ip Address)`. +10. Click `Apply`. +11. Select the `Actions` tab. +12. Click `Select action groups` to select an existing action group, or `Create action group` to create a new action group. +13. Follow the prompts to choose or create an action group. +14. Select the `Details` tab. +15. Select a `Resource group`, provide an `Alert rule name` and an optional `Alert rule description`. +16. Click `Review + create`. +17. Click `Create`. + +### From Azure CLI + +```bash +az monitor activity-log alert create --resource-group "" --condition category=Administrative and operationName=Microsoft.Network/publicIPAddresses/delete and level= --scope "/subscriptions/" --name "" --subscription --action-group +``` + +### From PowerShell + +Create the `Conditions` object. + +```bash +$conditions = @() +$conditions += New-AzActivityLogAlertAlertRuleAnyOfOrLeafConditionObject -Equal Administrative -Field category +$conditions += New-AzActivityLogAlertAlertRuleAnyOfOrLeafConditionObject -Equal Microsoft.Network/publicIPAddresses/delete -Field operationName +$conditions += New-AzActivityLogAlertAlertRuleAnyOfOrLeafConditionObject -Equal Verbose -Field level +``` + +Retrieve the `Action Group` information and store in a variable, then create the `Actions` object. + +```bash +$actionGroup = Get-AzActionGroup -ResourceGroupName -Name +$actionObject = New-AzActivityLogAlertActionGroupObject -Id $actionGroup.Id +``` + +Create the `Scope` object + +```bash +$scope = "/subscriptions/" +``` + +Create the `Activity Log Alert Rule` for `Microsoft.Network/publicIPAddresses/delete` + +```bash +New-AzActivityLogAlert -Name "" -ResourceGroupName "" -Condition $conditions -Scope $scope -Location global -Action $actionObject -Subscription -Enabled $true +``` + +### Default Value + +By default, no monitoring alerts are created. diff --git a/cis_v300/docs/cis_v300_6_2_2.md b/cis_v300/docs/cis_v300_6_2_2.md new file mode 100644 index 00000000..b4b60d66 --- /dev/null +++ b/cis_v300/docs/cis_v300_6_2_2.md @@ -0,0 +1,67 @@ +## Description + +Create an activity log alert for the Delete Policy Assignment event. + +Monitoring for delete policy assignment events gives insight into changes done in "azure policy - assignments" and can reduce the time it takes to detect unsolicited changes. + +## Remediation + +### From Azure Portal + +1. Navigate to the `Monitor` blade. +2. Select `Alerts`. +3. Select `Create`. +4. Select `Alert rule`. +5. Choose a subscription. +6. Select `Apply`. +7. Select the `Condition` tab. +8. Click `See all signals`. +9. Select `Delete policy assignment (Policy assignment)`. +10. Click `Apply`. +11. Select the `Actions` tab. +12. Click `Select action groups` to select an existing action group, or `Create action group` to create a new action group. +13. Follow the prompts to choose or create an action group. +14. Select the `Details` tab. +15. Select a `Resource group`, provide an `Alert rule name` and an optional `Alert rule description`. +16. Click `Review + create`. +17. Click `Create`. + +### From Azure CLI + +```bash +az monitor activity-log alert create --resource-group "" --condition category=Administrative and operationName=Microsoft.Authorization/policyAssignments/delete and level= --scope "/subscriptions/" --name "" --subscription --action-group +``` + +### From PowerShell + +Create the conditions object + +```bash +$conditions = @() +$conditions += New-AzActivityLogAlertAlertRuleAnyOfOrLeafConditionObject -Equal Administrative -Field category +$conditions += New-AzActivityLogAlertAlertRuleAnyOfOrLeafConditionObject -Equal Microsoft.Authorization/policyAssignments/delete -Field operationName +$conditions += New-AzActivityLogAlertAlertRuleAnyOfOrLeafConditionObject -Equal Verbose -Field level +``` + +Retrieve the `Action Group` information and store in a variable, then create the `Action` object. + +```bash +$actionGroup = Get-AzActionGroup -ResourceGroupName -Name +$actionObject = New-AzActivityLogAlertActionGroupObject -Id $actionGroup.Id +``` + +Create the `Scope` variable. + +```bash +$scope = "/subscriptions/" +``` + +Create the `Activity Log Alert Rule` for `Microsoft.Authorization/policyAssignments/delete`. + +```bash +New-AzActivityLogAlert -Name "" -ResourceGroupName "" -Condition $conditions -Scope $scope -Location global -Action $actionObject -Subscription -Enabled $true +``` + +### Default Value + +By default, no monitoring alerts are created. diff --git a/cis_v300/docs/cis_v300_6_2_3.md b/cis_v300/docs/cis_v300_6_2_3.md new file mode 100644 index 00000000..06b8e167 --- /dev/null +++ b/cis_v300/docs/cis_v300_6_2_3.md @@ -0,0 +1,67 @@ +## Description + +Create an Activity Log Alert for the Create or Update Network Security Group event. + +Monitoring for Create or Update Network Security Group events gives insight into network access changes and may reduce the time it takes to detect suspicious activity. + +## Remediation + +### From Azure Portal + +1. Navigate to the `Monitor` blade. +2. Select `Alerts`. +3. Select `Create`. +4. Select `Alert rule`. +5. Choose a subscription. +6. Select `Apply`. +7. Select the `Condition` tab. +8. Click `See all signals`. +9. Select `Create or Update Network Security Group (Network Security Group)`. +10. Click `Apply`. +11. Select the `Actions` tab. +12. Click `Select action groups` to select an existing action group, or `Create action group` to create a new action group. +13. Follow the prompts to choose or create an action group. +14. Select the `Details` tab. +15. Select a `Resource group`, provide an `Alert rule name` and an optional `Alert rule description`. +16. Click `Review + create`. +17. Click `Create`. + +### From Azure CLI + +```bash +az monitor activity-log alert create --resource-group "" --condition category=Administrative and operationName=Microsoft.Network/networkSecurityGroups/write and level=verbose --scope "/subscriptions/" --name "" --subscription --action-group +``` + +### From PowerShell + +Create the `Conditions` object. + +```bash +$conditions = @() +$conditions += New-AzActivityLogAlertAlertRuleAnyOfOrLeafConditionObject -Equal Administrative -Field category +$conditions += New-AzActivityLogAlertAlertRuleAnyOfOrLeafConditionObject -Equal Microsoft.Network/networkSecurityGroups/write -Field operationName +$conditions += New-AzActivityLogAlertAlertRuleAnyOfOrLeafConditionObject -Equal Verbose -Field level +``` + +Retrieve the `Action Group` information and store in a variable, then create the `Actions` object. + +```bash +$actionGroup = Get-AzActionGroup -ResourceGroupName -Name +$actionObject = New-AzActivityLogAlertActionGroupObject -Id $actionGroup.Id +``` + +Create the `Scope` object + +```bash +$scope = "/subscriptions/" +``` + +Create the `Activity Log Alert Rule` for `Microsoft.Network/networkSecurityGroups/write` + +```bash +New-AzActivityLogAlert -Name "" -ResourceGroupName "" -Condition $conditions -Scope $scope -Location global -Action $actionObject -Subscription -Enabled $true +``` + +### Default Value + +By default, no monitoring alerts are created. diff --git a/cis_v300/docs/cis_v300_6_2_4.md b/cis_v300/docs/cis_v300_6_2_4.md new file mode 100644 index 00000000..deea93f7 --- /dev/null +++ b/cis_v300/docs/cis_v300_6_2_4.md @@ -0,0 +1,67 @@ +## Description + +Create an activity log alert for the Delete Network Security Group event. + +Monitoring for "Delete Network Security Group" events gives insight into network access changes and may reduce the time it takes to detect suspicious activity. + +## Remediation + +### From Azure Portal + +1. Navigate to the `Monitor` blade. +2. Select `Alerts`. +3. Select `Create`. +4. Select `Alert rule`. +5. Choose a subscription. +6. Select `Apply`. +7. Select the `Condition` tab. +8. Click `See all signals`. +9. Select `Delete Network Security Group (Network Security Group)`. +10. Click `Apply`. +11. Select the `Actions` tab. +12. Click `Select action groups` to select an existing action group, or `Create action group` to create a new action group. +13. Follow the prompts to choose or create an action group. +14. Select the `Details` tab. +15. Select a `Resource group`, provide an `Alert rule name` and an optional `Alert rule description`. +16. Click `Review + create`. +17. Click `Create`. + +### From Azure CLI + +```bash +az monitor activity-log alert create --resource-group "" --condition category=Administrative and operationName=Microsoft.Network/networkSecurityGroups/delete and level= --scope "/subscriptions/" --name "" --subscription --action-group +``` + +### From PowerShell + +Create the `Conditions` object. + +```bash +$conditions = @() +$conditions += New-AzActivityLogAlertAlertRuleAnyOfOrLeafConditionObject -Equal Administrative -Field category +$conditions += New-AzActivityLogAlertAlertRuleAnyOfOrLeafConditionObject -Equal Microsoft.Network/networkSecurityGroups/delete -Field operationName +$conditions += New-AzActivityLogAlertAlertRuleAnyOfOrLeafConditionObject -Equal Verbose -Field level +``` + +Retrieve the `Action Group` information and store in a variable, then create the `Actions` object. + +```bash +$actionGroup = Get-AzActionGroup -ResourceGroupName -Name +$actionObject = New-AzActivityLogAlertActionGroupObject -Id $actionGroup.Id +``` + +Create the `Scope` object + +```bash +$scope = "/subscriptions/" +``` + +Create the `Activity Log Alert Rule` for `Microsoft.Network/networkSecurityGroups/delete` + +```bash +New-AzActivityLogAlert -Name "" -ResourceGroupName "" -Condition $conditions -Scope $scope -Location global -Action $actionObject -Subscription -Enabled $true +``` + +### Default Value + +By default, no monitoring alerts are created. diff --git a/cis_v300/docs/cis_v300_6_2_5.md b/cis_v300/docs/cis_v300_6_2_5.md new file mode 100644 index 00000000..c7a33c15 --- /dev/null +++ b/cis_v300/docs/cis_v300_6_2_5.md @@ -0,0 +1,67 @@ +## Description + +Create an activity log alert for the Create or Update Security Solution event. + +Monitoring for Create or Update Security Solution events gives insight into changes to the active security solutions and may reduce the time it takes to detect suspicious activity. + +## Remediation + +### From Azure Portal + +1. Navigate to the `Monitor` blade. +2. Select `Alerts`. +3. Select `Create`. +4. Select `Alert rule`. +5. Choose a subscription. +6. Select `Apply`. +7. Select the `Condition` tab. +8. Click `See all signals`. +9. Select `Create or Update Security Solutions (Security Solutions)`. +10. Click `Apply`. +11. Select the `Actions` tab. +12. Click `Select action groups` to select an existing action group, or `Create action group` to create a new action group. +13. Follow the prompts to choose or create an action group. +14. Select the `Details` tab. +15. Select a `Resource group`, provide an `Alert rule name` and an optional `Alert rule description`. +16. Click `Review + create`. +17. Click `Create`. + +### From Azure CLI + +```bash +az monitor activity-log alert create --resource-group "" --condition category=Administrative and operationName=Microsoft.Security/securitySolutions/write and level= --scope "/subscriptions/" --name "" --subscription --action-group +``` + +### From PowerShell + +Create the `Conditions` object. + +```bash +$conditions = @() +$conditions += New-AzActivityLogAlertAlertRuleAnyOfOrLeafConditionObject -Equal Administrative -Field category +$conditions += New-AzActivityLogAlertAlertRuleAnyOfOrLeafConditionObject -Equal Microsoft.Security/securitySolutions/write -Field operationName +$conditions += New-AzActivityLogAlertAlertRuleAnyOfOrLeafConditionObject -Equal Verbose -Field level +``` + +Retrieve the `Action Group` information and store in a variable, then create the `Actions` object. + +```bash +$actionGroup = Get-AzActionGroup -ResourceGroupName -Name +$actionObject = New-AzActivityLogAlertActionGroupObject -Id $actionGroup.Id +``` + +Create the `Scope` object + +```bash +$scope = "/subscriptions/" +``` + +Create the `Activity Log Alert Rule` for `Microsoft.Security/securitySolutions/write` + +```bash +New-AzActivityLogAlert -Name "" -ResourceGroupName "" -Condition $conditions -Scope $scope -Location global -Action $actionObject -Subscription -Enabled $true +``` + +### Default Value + +By default, no monitoring alerts are created. diff --git a/cis_v300/docs/cis_v300_6_2_6.md b/cis_v300/docs/cis_v300_6_2_6.md new file mode 100644 index 00000000..341ab7fb --- /dev/null +++ b/cis_v300/docs/cis_v300_6_2_6.md @@ -0,0 +1,67 @@ +## Description + +Create an activity log alert for the Delete Security Solution event. + +Monitoring for Delete Security Solution events gives insight into changes to the active security solutions and may reduce the time it takes to detect suspicious activity. + +## Remediation + +### From Azure Portal + +1. Navigate to the `Monitor` blade. +2. Select `Alerts`. +3. Select `Create`. +4. Select `Alert rule`. +5. Choose a subscription. +6. Select `Apply`. +7. Select the `Condition` tab. +8. Click `See all signals`. +9. Select `Delete Security Solutions (Security Solutions)`. +10. Click `Apply`. +11. Select the `Actions` tab. +12. Click `Select action groups` to select an existing action group, or `Create action group` to create a new action group. +13. Follow the prompts to choose or create an action group. +14. Select the `Details` tab. +15. Select a `Resource group`, provide an `Alert rule name` and an optional `Alert rule description`. +16. Click `Review + create`. +17. Click `Create`. + +### From Azure CLI + +```bash +az monitor activity-log alert create --resource-group "" --condition category=Administrative and operationName=Microsoft.Security/securitySolutions/delete and level= --scope "/subscriptions/" --name "" --subscription --action-group +``` + +### From PowerShell + +Create the `Conditions` object. + +```bash +$conditions = @() +$conditions += New-AzActivityLogAlertAlertRuleAnyOfOrLeafConditionObject -Equal Administrative -Field category +$conditions += New-AzActivityLogAlertAlertRuleAnyOfOrLeafConditionObject -Equal Microsoft.Security/securitySolutions/delete -Field operationName +$conditions += New-AzActivityLogAlertAlertRuleAnyOfOrLeafConditionObject -Equal Verbose -Field level +``` + +Retrieve the `Action Group` information and store in a variable, then create the `Actions` object. + +```bash +$actionGroup = Get-AzActionGroup -ResourceGroupName -Name +$actionObject = New-AzActivityLogAlertActionGroupObject -Id $actionGroup.Id +``` + +Create the `Scope` object + +```bash +$scope = "/subscriptions/" +``` + +Create the `Activity Log Alert Rule` for `Microsoft.Security/securitySolutions/delete` + +```bash +New-AzActivityLogAlert -Name "" -ResourceGroupName "" -Condition $conditions -Scope $scope -Location global -Action $actionObject -Subscription -Enabled $true +``` + +### Default Value + +By default, no monitoring alerts are created. diff --git a/cis_v300/docs/cis_v300_6_2_7.md b/cis_v300/docs/cis_v300_6_2_7.md new file mode 100644 index 00000000..905b679b --- /dev/null +++ b/cis_v300/docs/cis_v300_6_2_7.md @@ -0,0 +1,67 @@ +## Description + +Create an activity log alert for the Create or Update SQL Server Firewall Rule event. + +Monitoring for Create or Update SQL Server Firewall Rule events gives insight into network access changes and may reduce the time it takes to detect suspicious activity. + +## Remediation + +### From Azure Portal + +1. Navigate to the `Monitor` blade. +2. Select `Alerts`. +3. Select `Create`. +4. Select `Alert rule`. +5. Choose a subscription. +6. Select `Apply`. +7. Select the `Condition` tab. +8. Click `See all signals`. +9. Select `Create/Update server firewall rule (Server Firewall Rule)`. +10. Click `Apply`. +11. Select the `Actions` tab. +12. Click `Select action groups` to select an existing action group, or `Create action group` to create a new action group. +13. Follow the prompts to choose or create an action group. +14. Select the `Details` tab. +15. Select a `Resource group`, provide an `Alert rule name` and an optional `Alert rule description`. +16. Click `Review + create`. +17. Click `Create`. + +### From Azure CLI + +```bash +az monitor activity-log alert create --resource-group "" --condition category=Administrative and operationName=Microsoft.Sql/servers/firewallRules/write and level= --scope "/subscriptions/" --name "" --subscription --action-group +``` + +### From PowerShell + +Create the `Conditions` object. + +```bash +$conditions = @() +$conditions += New-AzActivityLogAlertAlertRuleAnyOfOrLeafConditionObject -Equal Administrative -Field category +$conditions += New-AzActivityLogAlertAlertRuleAnyOfOrLeafConditionObject -Equal Microsoft.Sql/servers/firewallRules/write -Field operationName +$conditions += New-AzActivityLogAlertAlertRuleAnyOfOrLeafConditionObject -Equal Verbose -Field level +``` + +Retrieve the `Action Group` information and store in a variable, then create the `Actions` object. + +```bash +$actionGroup = Get-AzActionGroup -ResourceGroupName -Name +$actionObject = New-AzActivityLogAlertActionGroupObject -Id $actionGroup.Id +``` + +Create the `Scope` object + +```bash +$scope = "/subscriptions/" +``` + +Create the `Activity Log Alert Rule` for `Microsoft.Sql/servers/firewallRules/write` + +```bash +New-AzActivityLogAlert -Name "" -ResourceGroupName "" -Condition $conditions -Scope $scope -Location global -Action $actionObject -Subscription -Enabled $true +``` + +### Default Value + +By default, no monitoring alerts are created. diff --git a/cis_v300/docs/cis_v300_6_2_8.md b/cis_v300/docs/cis_v300_6_2_8.md new file mode 100644 index 00000000..df5af5de --- /dev/null +++ b/cis_v300/docs/cis_v300_6_2_8.md @@ -0,0 +1,67 @@ +## Description + +Create an activity log alert for the "Delete SQL Server Firewall Rule." + +Monitoring for Delete SQL Server Firewall Rule events gives insight into SQL network access changes and may reduce the time it takes to detect suspicious activity. + +## Remediation + +### From Azure Portal + +1. Navigate to the `Monitor` blade. +2. Select `Alerts`. +3. Select `Create`. +4. Select `Alert rule`. +5. Choose a subscription. +6. Select `Apply`. +7. Select the `Condition` tab. +8. Click `See all signals`. +9. Select `Delete server firewall rule (Server Firewall Rule)`. +10. Click `Apply`. +11. Select the `Actions` tab. +12. Click `Select action groups` to select an existing action group, or `Create action group` to create a new action group. +13. Follow the prompts to choose or create an action group. +14. Select the `Details` tab. +15. Select a `Resource group`, provide an `Alert rule name` and an optional `Alert rule description`. +16. Click `Review + create`. +17. Click `Create`. + +### From Azure CLI + +```bash +az monitor activity-log alert create --resource-group "" --condition category=Administrative and operationName=Microsoft.Sql/servers/firewallRules/delete and level= --scope "/subscriptions/" --name "" --subscription --action-group +``` + +### From PowerShell + +Create the `Conditions` object. + +```bash +$conditions = @() +$conditions += New-AzActivityLogAlertAlertRuleAnyOfOrLeafConditionObject -Equal Administrative -Field category +$conditions += New-AzActivityLogAlertAlertRuleAnyOfOrLeafConditionObject -Equal Microsoft.Sql/servers/firewallRules/delete -Field operationName +$conditions += New-AzActivityLogAlertAlertRuleAnyOfOrLeafConditionObject -Equal Verbose -Field level +``` + +Retrieve the `Action Group` information and store in a variable, then create the `Actions` object. + +```bash +$actionGroup = Get-AzActionGroup -ResourceGroupName -Name +$actionObject = New-AzActivityLogAlertActionGroupObject -Id $actionGroup.Id +``` + +Create the `Scope` object + +```bash +$scope = "/subscriptions/" +``` + +Create the `Activity Log Alert Rule` for `Microsoft.Sql/servers/firewallRules/delete` + +```bash +New-AzActivityLogAlert -Name "" -ResourceGroupName "" -Condition $conditions -Scope $scope -Location global -Action $actionObject -Subscription -Enabled $true +``` + +### Default Value + +By default, no monitoring alerts are created. diff --git a/cis_v300/docs/cis_v300_6_2_9.md b/cis_v300/docs/cis_v300_6_2_9.md new file mode 100644 index 00000000..ae56984c --- /dev/null +++ b/cis_v300/docs/cis_v300_6_2_9.md @@ -0,0 +1,67 @@ +## Description + +Create an activity log alert for the Create or Update Public IP Addresses rule. + +Monitoring for Create or Update Public IP Address events gives insight into network access changes and may reduce the time it takes to detect suspicious activity. + +## Remediation + +### From Azure Portal + +1. Navigate to the `Monitor` blade. +2. Select `Alerts`. +3. Select `Create`. +4. Select `Alert rule`. +5. Choose a subscription. +6. Select `Apply`. +7. Select the `Condition` tab. +8. Click `See all signals`. +9. Select `Create or Update Public Ip Address (Public Ip Address)`. +10. Click `Apply`. +11. Select the `Actions` tab. +12. Click `Select action groups` to select an existing action group, or `Create action group` to create a new action group. +13. Follow the prompts to choose or create an action group. +14. Select the `Details` tab. +15. Select a `Resource group`, provide an `Alert rule name` and an optional `Alert rule description`. +16. Click `Review + create`. +17. Click `Create`. + +### From Azure CLI + +```bash +az monitor activity-log alert create --resource-group "" --condition category=Administrative and operationName=Microsoft.Network/publicIPAddresses/write and level= --scope "/subscriptions/" --name "" --subscription --action-group +``` + +### From PowerShell + +Create the `Conditions` object. + +```bash +$conditions = @() +$conditions += New-AzActivityLogAlertAlertRuleAnyOfOrLeafConditionObject -Equal Administrative -Field category +$conditions += New-AzActivityLogAlertAlertRuleAnyOfOrLeafConditionObject -Equal Microsoft.Network/publicIPAddresses/write -Field operationName +$conditions += New-AzActivityLogAlertAlertRuleAnyOfOrLeafConditionObject -Equal Verbose -Field level +``` + +Retrieve the `Action Group` information and store in a variable, then create the `Actions` object. + +```bash +$actionGroup = Get-AzActionGroup -ResourceGroupName -Name +$actionObject = New-AzActivityLogAlertActionGroupObject -Id $actionGroup.Id +``` + +Create the `Scope` object + +```bash +$scope = "/subscriptions/" +``` + +Create the `Activity Log Alert Rule` for `Microsoft.Network/publicIPAddresses/write` + +```bash +New-AzActivityLogAlert -Name "" -ResourceGroupName "" -Condition $conditions -Scope $scope -Location global -Action $actionObject -Subscription -Enabled $true +``` + +### Default Value + +By default, no monitoring alerts are created. diff --git a/cis_v300/docs/cis_v300_6_3.md b/cis_v300/docs/cis_v300_6_3.md new file mode 100644 index 00000000..9bb24a40 --- /dev/null +++ b/cis_v300/docs/cis_v300_6_3.md @@ -0,0 +1,3 @@ +## Overview + +This section covers security recommendations for Configuring Application Insights. diff --git a/cis_v300/docs/cis_v300_6_3_1.md b/cis_v300/docs/cis_v300_6_3_1.md new file mode 100644 index 00000000..7fdcc910 --- /dev/null +++ b/cis_v300/docs/cis_v300_6_3_1.md @@ -0,0 +1,38 @@ +## Description + +Application Insights within Azure act as an Application Performance Monitoring solution providing valuable data into how well an application performs and additional information when performing incident response. The types of log data collected include application metrics, telemetry data, and application trace logging data providing organizations with detailed information about application activity and application transactions. Both data sets help organizations adopt a proactive and retroactive means to handle security and performance related metrics within their modern applications. + +Configuring Application Insights provides additional data not found elsewhere within Azure as part of a much larger logging and monitoring program within an organization's Information Security practice. The types and contents of these logs will act as both a potential cost saving measure (application performance) and a means to potentially confirm the source of a potential incident (trace logging). Metrics and Telemetry data provide organizations with a proactive approach to cost savings by monitoring an application's performance, while the trace logging data provides necessary details in a reactive incident response scenario by helping organizations identify the potential source of an incident within their application. + +## Remediation + +### From Azure Portal + +1. Navigate to `Application Insights`. +2. Under the `Basics` tab within the `PROJECT DETAILS` section, select the `Subscription`. +3. Select the `Resource group`. +4. Within the `INSTANCE DETAILS`, enter a `Name`. +5. Select a `Region`. +6. Next to `Resource Mode`, select `Workspace-based`. +7. Within the `WORKSPACE DETAILS`, select the `Subscription` for the log analytics workspace. +8. Select the appropriate `Log Analytics Workspace`. +9. Click `Next : Tags >`. +10. Enter the appropriate `Tags` as `Name`, `Value` pairs. +11. Click `Next : Review + Create`. +12. Click `Create`. + +### From Azure CLI + +```bash +az monitor app-insights component create --app --resource-group --location --kind "web" --retention-time --workspace --subscription +``` + +### From PowerShell + +```bash +New-AzApplicationInsights -Kind "web" -ResourceGroupName -Name -location -RetentionInDays -SubscriptionID -WorkspaceResourceId +``` + +### Default Value + +Application Insights are not enabled by default. diff --git a/cis_v300/docs/cis_v300_6_4.md b/cis_v300/docs/cis_v300_6_4.md new file mode 100644 index 00000000..41e4d451 --- /dev/null +++ b/cis_v300/docs/cis_v300_6_4.md @@ -0,0 +1,57 @@ +## Description + +Resource Logs capture activity to the data access plane while the Activity log is a subscription-level log for the control plane. Resource-level diagnostic logs provide insight into operations that were performed within that resource itself; for example, reading or updating a secret from a Key Vault. Currently, 95 Azure resources support Azure Monitoring (See the more information section for a complete list), including Network Security Groups, Load Balancers, Key Vault, AD, Logic Apps, and CosmosDB. The content of these logs varies by resource type. + +A number of back-end services were not configured to log and store Resource Logs for certain activities or for a sufficient length. It is crucial that monitoring is correctly configured to log all relevant activities and retain those logs for a sufficient length of time. Given that the mean time to detection in an enterprise is 240 days, a minimum retention period of two years is recommended. + +A lack of monitoring reduces the visibility into the data plane, and therefore an organization's ability to detect reconnaissance, authorization attempts or other malicious activity. Unlike Activity Logs, Resource Logs are not enabled by default. Specifically, without monitoring it would be impossible to tell which entities had accessed a data store that was breached. In addition, alerts for failed attempts to access APIs for Web Services or Databases are only possible when logging is enabled. + +## Remediation + +Azure Subscriptions should log every access and operation for all resources. +Logs should be sent to Storage and a Log Analytics Workspace or equivalent third-party system. Logs should be kept in readily-accessible storage for a minimum of one year, and then moved to inexpensive cold storage for a duration of time as necessary. If retention policies are set but storing logs in a Storage Account is disabled (for example, if only Event Hubs or Log Analytics options are selected), the retention policies have no effect. Enable all monitoring at first, and then be more aggressive moving data to cold storage if the volume of data becomes a cost concern. + +### From Azure Portal + +The specific steps for configuring resources within the Azure console vary depending on resource, but typically the steps are: + +1. Go to the resource. +2. Click on Diagnostic settings. +3. In the blade that appears, click "Add diagnostic setting". +4. Configure the diagnostic settings. +5. Click on Save. + +### From Azure CLI + +For each `resource`, run the following making sure to use a `resource` appropriate JSON encoded `category` for the `--logs` option. + +```bash +az monitor diagnostic-settings create --name --resource --logs "[{category:,enabled:true,rentention-policy:{enabled:true,days:180}}]" --metrics "[{category:AllMetrics,enabled:true,retention-policy:{enabled:true,days:180}}]" <[--event-hub --event-hub-rule | --storage-account |--workspace | --marketplace-partner-id ]> +``` + +### From PowerShell + +Create the `log` settings object + +```bash +$logSettings = @() +$logSettings += New-AzDiagnosticSettingLogSettingsObject -Enabled $true -RetentionPolicyDay 180 -RetentionPolicyEnabled $true -Category +$logSettings += New-AzDiagnosticSettingLogSettingsObject -Enabled $true -RetentionPolicyDay 180 -RetentionPolicyEnabled $true -Category +``` + +Create the `metric` settings object + +```bash +$metricSettings = @() +$metricSettings += New-AzDiagnosticSettingMetricSettingsObject -Enabled $true -RetentionPolicyDay 180 -RetentionPolicyEnabled $true -Category AllMetrics +``` + +Create the diagnostic setting for a specific resource + +```bash +New-AzDiagnosticSetting -Name "" -ResourceId -Log $logSettings -Metric $metricSettings +``` + +### Default Value + +By default, Azure Monitor Resource Logs are 'Disabled' for all resources. diff --git a/cis_v300/docs/cis_v300_6_5.md b/cis_v300/docs/cis_v300_6_5.md new file mode 100644 index 00000000..6ce772cd --- /dev/null +++ b/cis_v300/docs/cis_v300_6_5.md @@ -0,0 +1,25 @@ +## Description + +The use of Basic or Free SKUs in Azure whilst cost effective have significant limitations in terms of what can be monitored and what support can be realized from Microsoft. Typically, these SKU’s do not have a service SLA and Microsoft may refuse to provide support for them. Consequently Basic/Free SKUs should never be used for production workloads. + +Typically, production workloads need to be monitored and should have an SLA with Microsoft, using Basic SKUs for any deployed product will mean that that these capabilities do not exist. + +The following resource types should use standard SKUs as a minimum. +- Public IP Addresses +- Network Load Balancers +- REDIS Cache +- SQL PaaS Databases +- VPN Gateways + +## Remediation + +Each artifact has its own process for upgrading from basic to standard SKU's and this should be followed if required. + +### Default Value + +Policy should enforce standard SKUs for the following artifacts: +- Public IP Addresses +- Network Load Balancers +- REDIS Cache +- SQL PaaS Databases +- VPN Gateways diff --git a/cis_v300/docs/cis_v300_7.md b/cis_v300/docs/cis_v300_7.md new file mode 100644 index 00000000..4853376f --- /dev/null +++ b/cis_v300/docs/cis_v300_7.md @@ -0,0 +1,3 @@ +## Overview + +This section covers security recommendations to follow in order to set networking policies on an Azure subscription. diff --git a/cis_v300/docs/cis_v300_7_1.md b/cis_v300/docs/cis_v300_7_1.md new file mode 100644 index 00000000..c989e6e1 --- /dev/null +++ b/cis_v300/docs/cis_v300_7_1.md @@ -0,0 +1,21 @@ +## Description + +Network security groups should be periodically evaluated for port misconfigurations. Where certain ports and protocols may be exposed to the Internet, they should be evaluated for necessity and restricted wherever they are not explicitly required. + +The potential security problem with using RDP over the Internet is that attackers can use various brute force techniques to gain access to Azure Virtual Machines. Once the attackers gain access, they can use a virtual machine as a launch point for compromising other machines on an Azure Virtual Network or even attack networked devices outside of Azure. + +## Remediation + +Where RDP is not explicitly required and narrowly configured for resources attached to the Network Security Group, Internet-level access to your Azure resources should be restricted or eliminated. + +For internal access to relevant resources, configure an encrypted network tunnel such as: + +1. [ExpressRoute](https://docs.microsoft.com/en-us/azure/expressroute/) + +2. [Site-to-site VPN](https://docs.microsoft.com/en-us/azure/vpn-gateway/vpn-gateway-howto-site-to-site-resource-manager-portal) + +3. [Point-to-site VPN](https://docs.microsoft.com/en-us/azure/vpn-gateway/vpn-gateway-howto-point-to-site-resource-manager-portal) + +### Default Value + +By default, RDP access from internet is not `enabled`. diff --git a/cis_v300/docs/cis_v300_7_2.md b/cis_v300/docs/cis_v300_7_2.md new file mode 100644 index 00000000..eaf1b665 --- /dev/null +++ b/cis_v300/docs/cis_v300_7_2.md @@ -0,0 +1,21 @@ +## Description + +Network security groups should be periodically evaluated for port misconfigurations. Where certain ports and protocols may be exposed to the Internet, they should be evaluated for necessity and restricted wherever they are not explicitly required. + +The potential security problem with using SSH over the Internet is that attackers can use various brute force techniques to gain access to Azure Virtual Machines. Once the attackers gain access, they can use a virtual machine as a launch point for compromising other machines on the Azure Virtual Network or even attack networked devices outside of Azure. + +## Remediation + +Where SSH is not explicitly required and narrowly configured for resources attached to the Network Security Group, Internet-level access to your Azure resources should be restricted or eliminated. + +For internal access to relevant resources, configure an encrypted network tunnel such as: + +1. [ExpressRoute](https://docs.microsoft.com/en-us/azure/expressroute/) + +2. [Site-to-site VPN](https://docs.microsoft.com/en-us/azure/vpn-gateway/vpn-gateway-howto-site-to-site-resource-manager-portal) + +3. [Point-to-site VPN](https://docs.microsoft.com/en-us/azure/vpn-gateway/vpn-gateway-howto-point-to-site-resource-manager-portal) + +### Default Value + +By default, SSH access from internet is not `enabled`. diff --git a/cis_v300/docs/cis_v300_7_3.md b/cis_v300/docs/cis_v300_7_3.md new file mode 100644 index 00000000..d02bd8f3 --- /dev/null +++ b/cis_v300/docs/cis_v300_7_3.md @@ -0,0 +1,21 @@ +## Description + +Network security groups should be periodically evaluated for port misconfigurations. Where certain ports and protocols may be exposed to the Internet, they should be evaluated for necessity and restricted wherever they are not explicitly required. + +The potential security problem with broadly exposing UDP services over the Internet is that attackers can use DDoS amplification techniques to reflect spoofed UDP traffic from Azure Virtual Machines. The most common types of these attacks use exposed DNS, NTP, SSDP, SNMP, CLDAP and other UDP-based services as amplification sources for disrupting services of other machines on the Azure Virtual Network or even attack networked devices outside of Azure. + +## Remediation + +Where UDP is not explicitly required and narrowly configured for resources attached to the Network Security Group, Internet-level access to your Azure resources should be restricted or eliminated. + +For internal access to relevant resources, configure an encrypted network tunnel such as: + +1. [ExpressRoute](https://docs.microsoft.com/en-us/azure/expressroute/) + +2. [Site-to-site VPN](https://docs.microsoft.com/en-us/azure/vpn-gateway/vpn-gateway-howto-site-to-site-resource-manager-portal) + +3. [Point-to-site VPN](https://docs.microsoft.com/en-us/azure/vpn-gateway/vpn-gateway-howto-point-to-site-resource-manager-portal) + +### Default Value + +By default, UDP access from internet is not `enabled`. diff --git a/cis_v300/docs/cis_v300_7_4.md b/cis_v300/docs/cis_v300_7_4.md new file mode 100644 index 00000000..f69817cd --- /dev/null +++ b/cis_v300/docs/cis_v300_7_4.md @@ -0,0 +1,43 @@ +## Description + +Network security groups should be periodically evaluated for port misconfigurations. Where certain ports and protocols may be exposed to the Internet, they should be evaluated for necessity and restricted wherever they are not explicitly required and narrowly configured. + +The potential security problem with using HTTP(S) over the Internet is that attackers can use various brute force techniques to gain access to Azure resources. Once the attackers gain access, they can use the resource as a launch point for compromising other resources within the Azure tenant. + +## Remediation + +### From Azure Portal + +1. Go to `Virtual machines`. +2. For each VM, open the `Networking` blade. +3. Click on `Inbound port rules`. +4. Delete the rule with: + * Port = 80/443 OR \[port range containing 80/443\] + * Protocol = TCP OR Any + * Source = Any (\*) OR IP Addresses(0.0.0.0/0) OR Service Tag(Internet) + * Action = Allow + +### From Azure CLI + +1. Run below command to list network security groups: + +```bash +az network nsg list --subscription --output table +``` + +2. For each network security group, run below command to list the rules associated with the specified port: + +```bash +az network nsg rule list --resource-group --nsg-name --query "[?destinationPortRange=='80 or 443']" +``` + +3. Run the below command to delete the rule with: + + * Port = 80/443 OR \[port range containing 80/443\] + * Protocol = TCP OR "*" + * Source = Any (\*) OR IP Addresses(0.0.0.0/0) OR Service Tag(Internet) + * Action = Allow + +```bash +az network nsg rule delete --resource-group --nsg-name --name +``` diff --git a/cis_v300/docs/cis_v300_7_5.md b/cis_v300/docs/cis_v300_7_5.md new file mode 100644 index 00000000..211ae322 --- /dev/null +++ b/cis_v300/docs/cis_v300_7_5.md @@ -0,0 +1,29 @@ +## Description + +Network Security Group Flow Logs should be enabled and the retention period set to greater than or equal to 90 days. + +Flow logs enable capturing information about IP traffic flowing in and out of network security groups. Logs can be used to check for anomalies and give insight into suspected breaches. + +## Remediation + +### From Azure Portal + +1. Go to `Network Watcher`. +2. Select `NSG flow logs` blade in the Logs section. +3. Select each Network Security Group from the list. +4. Ensure `Status` is set to `On`. +5. Ensure `Retention (days)` setting `greater than 90 days`. +6. Select your storage account in the `Storage account` field. +7. Select `Save`. + +### From Azure CLI + +Enable the `NSG flow logs` and set the Retention (days) to greater than or equal to 90 days. + +```bash +az network watcher flow-log configure --nsg --enabled true --resource-group --retention 91 --storage-account +``` + +### Default Value + +By default, Network Security Group Flow Logs are `disabled`. diff --git a/cis_v300/docs/cis_v300_7_6.md b/cis_v300/docs/cis_v300_7_6.md new file mode 100644 index 00000000..0bd64e09 --- /dev/null +++ b/cis_v300/docs/cis_v300_7_6.md @@ -0,0 +1,29 @@ +## Description + +Enable Network Watcher for physical regions in Azure subscriptions. + +Network diagnostic and visualization tools available with Network Watcher help users understand, diagnose, and gain insights to the network in Azure. + +## Remediation + +Opting out of Network Watcher automatic enablement is a permanent change. Once you opt-out you cannot opt-in without contacting support. + +To manually enable Network Watcher in each region where you want to use Network Watcher capabilities, follow the steps below. + +### From Azure Portal + +1. Use the Search bar to search for and click on the `Network Watcher` service. +2. Click `Create`. +3. Select a `Region` from the drop-down menu. +4. Click `Add`. + +### From Azure CLI + +```bash +az network watcher configure --locations --enabled true --resource-group +``` + +### Default Value + +Network Watcher is automatically enabled. +When you create or update a virtual network in your subscription, Network Watcher will be enabled automatically in your Virtual Network's region. There is no impact to your resources or associated charge for automatically enabling Network Watcher. diff --git a/cis_v300/docs/cis_v300_7_7.md b/cis_v300/docs/cis_v300_7_7.md new file mode 100644 index 00000000..38b9566d --- /dev/null +++ b/cis_v300/docs/cis_v300_7_7.md @@ -0,0 +1,13 @@ +## Description + +Public IP Addresses provide tenant accounts with Internet connectivity for resources contained within the tenant. During the creation of certain resources in Azure, a Public IP Address may be created. All Public IP Addresses within the tenant should be periodically reviewed for accuracy and necessity. + +Public IP Addresses allocated to the tenant should be periodically reviewed for necessity. Public IP Addresses that are not intentionally assigned and controlled present a publicly facing vector for threat actors and significant risk to the tenant. + +## Remediation + +Remediation will vary significantly depending on your organization's security requirements for the resources attached to each individual Public IP address. + +### Default Value + +During Virtual Machine and Application creation, a setting may create and attach a public IP. diff --git a/cis_v300/docs/cis_v300_8.md b/cis_v300/docs/cis_v300_8.md new file mode 100644 index 00000000..7a15fa00 --- /dev/null +++ b/cis_v300/docs/cis_v300_8.md @@ -0,0 +1,3 @@ +## Overview + +This section covers security recommendations to follow for the configuration of Virtual Machines on an Azure subscription. diff --git a/cis_v300/docs/cis_v300_8_1.md b/cis_v300/docs/cis_v300_8_1.md new file mode 100644 index 00000000..a8899e2a --- /dev/null +++ b/cis_v300/docs/cis_v300_8_1.md @@ -0,0 +1,55 @@ +## Description + +The Azure Bastion service allows secure remote access to Azure Virtual Machines over the Internet without exposing remote access protocol ports and services directly to the Internet. The Azure Bastion service provides this access using TLS over 443/TCP, and subscribes to hardened configurations within an organization's Azure Active Directory service. + +The Azure Bastion service allows organizations a more secure means of accessing Azure Virtual Machines over the Internet without assigning public IP addresses to those Virtual Machines. The Azure Bastion service provides Remote Desktop Protocol (RDP) and Secure Shell (SSH) access to Virtual Machines using TLS within a web browser, thus preventing organizations from opening up 3389/TCP and 22/TCP to the Internet on Azure Virtual Machines. Additional benefits of the Bastion service includes Multi-Factor Authentication, Conditional Access Policies, and any other hardening measures configured within Azure Active Directory using a central point of access. + +## Remediation + +### From Azure Portal + +1. Click on `Bastions`. +2. Select the `Subscription`. +3. Select the `Resource group`. +4. Type a `Name` for the new Bastion host. +5. Select a `Region`. +6. Choose `Standard` next to `Tier`. +7. Use the slider to set the `Instance count`. +8. Select the `Virtual network` or `Create new`. +9. Select the `Subnet` named `AzureBastionSubnet`. Create a `Subnet` named `AzureBastionSubnet` using a `/26` CIDR range if it doesn't already exist. +10. Selct the appropriate `Public IP address` option. +11. If `Create new` is selected for the `Public IP address` option, provide a `Public IP address name`. +12. If `Use existing` is selected for `Public IP address` option, select an IP address from `Choose public IP address`. +13. Click `Next: Tags >`. +14. Configure the appropriate `Tags`. +15. Click `Next: Advanced >`. +16. Select the appropriate `Advanced` options. +17. Click `Next: Review + create >`. +18. Click `Create`. + +### From Azure CLI + +```bash +az network bastion create --location --name --public-ip-address --resource-group --vnet-name --scale-units --sku Standard [--disable-copy-paste true|false] [--enable-ip-connect true|false] [--enable-tunneling true|false] +``` + +### From PowerShell + +Create the appropriate `Virtual network` settings and `Public IP Address` settings. + +```bash +$subnetName = "AzureBastionSubnet" +$subnet = New-AzVirtualNetworkSubnetConfig -Name $subnetName -AddressPrefix +$virtualNet = New-AzVirtualNetwork -Name -ResourceGroupName -Location -AddressPrefix -Subnet $subnet +$publicip = New-AzPublicIpAddress -ResourceGroupName -Name -Location -AllocationMethod Dynamic -Sku Standard +``` + +Create the `Azure Bastion` service using the information within the created variables from above. + +```bash +New-AzBastion -ResourceGroupName -Name -PublicIpAddress $publicip -VirtualNetwork $virtualNet -Sku "Standard" -ScaleUnit +``` + +### Default Value + +By default, the Azure Bastion service is not configured. diff --git a/cis_v300/docs/cis_v300_8_10.md b/cis_v300/docs/cis_v300_8_10.md new file mode 100644 index 00000000..7f8a52c6 --- /dev/null +++ b/cis_v300/docs/cis_v300_8_10.md @@ -0,0 +1,30 @@ +## Description + +Verify identities without MFA that can log in to a privileged virtual machine using separate login credentials. An adversary can leverage the access to move laterally and perform actions with the virtual machine's managed identity. Make sure the virtual machine only has necessary permissions, and revoke the admin-level permissions according to the least privileges principal. + +Integrating multi-factor authentication (MFA) as part of the organizational policy can greatly reduce the risk of an identity gaining control of valid credentials that may be used for additional tactics such as initial access, lateral movement, and collecting information. MFA can also be used to restrict access to cloud resources and APIs. + +An Adversary may log into accessible cloud services within a compromised environment using Valid Accounts that are synchronized to move laterally and perform actions with the virtual machine's managed identity. The adversary may then perform management actions or access cloud-hosted resources as the logged-on managed identity. + +## Remediation + +### From Azure Portal + +1. Log in to the Azure portal. +2. This can be remediated by enabling MFA for user, Removing user access or Reducing access of managed identities attached to virtual machines. + +- Case I : Enable MFA for users having access on virtual machines. + 1. Navigate to `Entra ID` from the left pane and select `Users` from the `Manage` section. + 2. Click on `Per-User MFA` from the top menu options and select each user with `MULTI-FACTOR AUTH STATUS` as `Disabled` and can login to virtual machines: + * From `quick steps` on the right side select `enable`. + * Click on `enable multi-factor auth` and share the link with the user to setup MFA as required. + +- Case II : Removing user access on a virtual machine. + 1. Select the `Subscription`, then click on `Access control (IAM)`. + 2. Select `Role assignments` and search for `Virtual Machine Administrator Login` or `Virtual Machine User Login` or any role that provides access to log into virtual machines. + 3. Click on `Role Name`, Select `Assignments`, and remove identities with no MFA configured. + +- Case III : Reducing access of managed identities attached to virtual machines. + 1. Select the `Subscription`, then click on `Access control (IAM)`. + 2. Select `Role Assignments` from the top menu and apply filters on `Assignment type` as `Privileged administrator roles` and `Type` as `Virtual Machines`. + 3. Click on `Role Name`, Select `Assignments`, and remove identities access make sure this follows the least privileges principal. diff --git a/cis_v300/docs/cis_v300_8_11.md b/cis_v300/docs/cis_v300_8_11.md new file mode 100644 index 00000000..406c2977 --- /dev/null +++ b/cis_v300/docs/cis_v300_8_11.md @@ -0,0 +1,21 @@ +## Description + +When **Secure Boot** and **vTPM** are enabled together, they provide a strong foundation for protecting your VM from boot attacks. For example, if an attacker attempts to replace the bootloader with a malicious version, Secure Boot will prevent the VM from booting. If the attacker is able to bypass Secure Boot and install a malicious bootloader, vTPM can be used to detect the intrusion and alert you. + +Secure Boot and vTPM work together to protect your VM from a variety of boot attacks, including bootkits, rootkits, and firmware rootkits. Not enabling Trusted Launch in Azure VM can lead to increased vulnerability to rootkits and boot-level malware, reduced ability to detect and prevent unauthorized changes to the boot process, and a potential compromise of system integrity and data security. + +## Remediation + +### From Azure Portal + +1. Go to Virtual Machines. +2. For each VM, under Settings, click on Configuration on the left blade. +3. Under Security Type, select 'Trusted Launch Virtual Machines'. +4. Make sure Enable Secure Boot & Enable vTPM are checked. +5. Click on Apply. + +Note: Trusted launch on existing virtual machines (VMs) is currently not supported for Azure Generation 1 VMs + +### Default Value + +On Azure Generation 2 VMs, vTPM is enabled by default. Secure Boot is not enabled by default. diff --git a/cis_v300/docs/cis_v300_8_2.md b/cis_v300/docs/cis_v300_8_2.md new file mode 100644 index 00000000..3ffdd3a9 --- /dev/null +++ b/cis_v300/docs/cis_v300_8_2.md @@ -0,0 +1,36 @@ +## Description + +Migrate blob-based VHDs to Managed Disks on Virtual Machines to exploit the default features of this configuration. +The features include: +1) Default Disk Encryption. +2) Resilience, as Microsoft will managed the disk storage and move around if underlying hardware goes faulty. +3) Reduction of costs over storage accounts. + +Managed disks are by default encrypted on the underlying hardware, so no additional encryption is required for basic protection. It is available if additional encryption is required. +Managed disks are by design more resilient that storage accounts. + +For ARM-deployed Virtual Machines, Azure Adviser will at some point recommend moving VHDs to managed disks both from a security and cost management perspective. + +## Remediation + +### From Azure Portal + +1. Using the search feature, go to `Virtual Machines`. +2. Select the virtual machine you would like to convert. +3. Select `Disks` in the menu for the VM. +4. At the top select `Migrate to managed disks`. +5. You may follow the prompts to convert the disk and finish by selecting `Migrate` to start the process. + +**NOTE** VMs will be stopped and restarted after migration is complete. + +### From PowerShell + +```bash +Stop-AzVM -ResourceGroupName $rgName -Name $vmName -Force +ConvertTo-AzVMManagedDisk -ResourceGroupName $rgName -VMName $vmName +Start-AzVM -ResourceGroupName $rgName -Name $vmName +``` + +### Default Value + +Managed disks or are an option upon the creation of VMs. diff --git a/cis_v300/docs/cis_v300_8_3.md b/cis_v300/docs/cis_v300_8_3.md new file mode 100644 index 00000000..6813565e --- /dev/null +++ b/cis_v300/docs/cis_v300_8_3.md @@ -0,0 +1,43 @@ +## Description + +Ensure that OS disks (boot volumes) and data disks (non-boot volumes) are encrypted with CMK (Customer Managed Keys). +Customer Managed keys can be either ADE or Server Side Encryption (SSE). + +Encrypting the IaaS VM's OS disk (boot volume) and Data disks (non-boot volume) ensures that the entire content is fully unrecoverable without a key, thus protecting the volume from unwanted reads. PMK (Platform Managed Keys) are enabled by default in Azure-managed disks and allow encryption at rest. CMK is recommended because it gives the customer the option to control which specific keys are used for the encryption and decryption of the disk. The customer can then change keys and increase security by disabling them instead of relying on the PMK key that remains unchanging. There is also the option to increase security further by using automatically rotating keys so that access to disk is ensured to be limited. Organizations should evaluate what their security requirements are, however, for the data stored on the disk. For high-risk data using CMK is a must, as it provides extra steps of security. If the data is low risk, PMK is enabled by default and provides sufficient data security. + +## Remediation + +### From Azure Portal + +**Note:** Disks must be detached from VMs to have encryption changed. + +1. Go to `Virtual machines`. +2. For each virtual machine, go to `Settings`. +3. Click on `Disks`. +4. Click the ellipsis (`...`), then click `Detach` to detach the disk from the VM. +5. Now search for `Disks` and locate the unattached disk. +6. Click the disk then select `Encryption`. +7. Change your encryption type, then select your encryption set. +8. Click `Save`. +9. Go back to the VM and re-attach the disk. + +### From PowerShell + +```bash +$KVRGname = 'MyKeyVaultResourceGroup'; +$VMRGName = 'MyVirtualMachineResourceGroup'; +$vmName = 'MySecureVM'; +$KeyVaultName = 'MySecureVault'; +$KeyVault = Get-AzKeyVault -VaultName $KeyVaultName -ResourceGroupName $KVRGname; +$diskEncryptionKeyVaultUrl = $KeyVault.VaultUri; +$KeyVaultResourceId = $KeyVault.ResourceId; + +Set-AzVMDiskEncryptionExtension -ResourceGroupName $VMRGname -VMName $vmName -DiskEncryptionKeyVaultUrl $diskEncryptionKeyVaultUrl -DiskEncryptionKeyVaultId $KeyVaultResourceId; +``` + +**NOTE:** During encryption it is likely that a reboot will be required. It may take up to 15 minutes to complete the process. +For Linux machines you may need to set the `-skipVmBackup` parameter. + +### Default Value + +By default, Azure disks are encrypted using SSE with PMK. diff --git a/cis_v300/docs/cis_v300_8_4.md b/cis_v300/docs/cis_v300_8_4.md new file mode 100644 index 00000000..c4bff8ed --- /dev/null +++ b/cis_v300/docs/cis_v300_8_4.md @@ -0,0 +1,26 @@ +## Description + +Ensure that unattached disks in a subscription are encrypted with a Customer Managed Key (CMK). + +Managed disks are encrypted by default with Platform-managed keys. Using Customer-managed keys may provide an additional level of security or meet an organization's regulatory requirements. Encrypting managed disks ensures that its entire content is fully unrecoverable without a key and thus protects the volume from unwarranted reads. +Even if the disk is not attached to any of the VMs, there is always a risk where a compromised user account with administrative access to VM service can mount/attach these data disks, which may lead to sensitive information disclosure and tampering. + +## Remediation + +If data stored in the disk is no longer useful, refer to Azure documentation to delete unattached data disks at: + +```bash +- https://docs.microsoft.com/en-us/rest/api/compute/disks/delete +- https://docs.microsoft.com/en-us/cli/azure/disk?view=azure-cli-latest#az-disk-delete +``` + +If data stored in the disk is important, to encrypt the disk refer to azure documentation at: + +```bash +- https://docs.microsoft.com/en-us/azure/virtual-machines/disks-enable-customer-managed-keys-portal +- https://docs.microsoft.com/en-us/rest/api/compute/disks/update#encryptionsettings +``` + +### Default Value + +By default, managed disks are encrypted with a Platform-managed key. diff --git a/cis_v300/docs/cis_v300_8_5.md b/cis_v300/docs/cis_v300_8_5.md new file mode 100644 index 00000000..6d7e9371 --- /dev/null +++ b/cis_v300/docs/cis_v300_8_5.md @@ -0,0 +1,67 @@ +## Description + +Virtual Machine Disks and snapshots can be configured to allow access from different network resources. + +The setting 'Enable public access from all networks' is, in many cases, an overly permissive setting on Virtual Machine Disks that presents atypical attack, data infiltration, and data exfiltration vectors. If a disk to network connection is required, the preferred setting is to 'Disable public access and enable private access.' + +## Remediation + +### From Azure Portal + +Part A. Select the Virtual Machine to Remediate + +1. Using the search bar, search for and open the `Virtual Machines` service. +2. Click on the name of the Virtual Machine to be remediated. + +Part B. Remediate each Virtual Machine Disk individually + +1. From the selected Virtual Machine resource window, expand the `Settings` menu item and click `Disks.` +2. For each disk, click the name of the disk to open the disk resource window. +3. From the selected Disk resource window, expand the `Settings` menu item, and click `Networking`. + +Under Network access, select the radio button for either: +- Disable public access and enable private access +- Disable public and private access + +Repeat Part B for each Disk attached to a VM. + +Repeat Parts A and B to remediate all Disks in all VMs. + +### From Powershell + +To disable `PublicNetworkAccess` and to set a `DenyAll` setting for the disk's `NetworkAccessPolicy` for each managed disk, run the following command: + +```bash +$disk = Get-AzDisk -ResourceGroupName ‘’ -DiskName ‘’ +$disk.NetworkAccessPolicy = 'DenyAll' +$disk.PublicNetworkAccess = 'Disabled' +Update-AzDisk -ResourceGroup ' -DiskName $disk.Name -Disk $disk +``` + +To disable `PublicNetworkAccess` and to set an `AllowPrivate` setting for the disk's `NetworkAccessPolicy` for each managed disk, run the following command: + +```bash +$disk = Get-AzDisk -ResourceGroupName ‘’ -DiskName ‘’ +$disk.NetworkAccessPolicy = 'AllowPrivate' +$disk.PublicNetworkAccess = 'Disabled' +$disk.DiskAccessId = '/subscriptions//resourceGroups//providers/Microsoft.Compute/diskAccesses/ +Update-AzDisk -ResourceGroup ' -DiskName $disk.Name -Disk $disk +``` + +### From Azure CLI + +To configure a disk to allow private access only, run the following command making sure you have the `Disk Access ID` from a private disk access end point. + +```bash +az disk update --name --resource-group --network-access-policy AllowPrivate --disk-access +``` + +To completely disable public and private access for a disk, run the following command (still in preview) for each disk: + +```bash +az disk update --name --resource-group --public-network-access Disabled --network-access-policy DenyAll +``` + +### Default Value + +By default, Disk Network access is set to `Enable public access from all networks`. diff --git a/cis_v300/docs/cis_v300_8_6.md b/cis_v300/docs/cis_v300_8_6.md new file mode 100644 index 00000000..93b5cd99 --- /dev/null +++ b/cis_v300/docs/cis_v300_8_6.md @@ -0,0 +1,48 @@ +## Description + +Data Access Authentication Mode provides a method of uploading or exporting Virtual Machine Disks. + +Enabling `data access authentication mode` adds a layer of protection using an Entra ID role to further restrict users from creating and using Secure Access Signature (SAS) tokens for exporting a detached managed disk or virtual machine state. Users will need the `Data operator for managed disk` role within Entra ID in order to download a VHD or VM Guest state using a secure URL. + +## Remediation + +### From Azure Portal + +Part A. Select the Virtual Machine to Remediate + +1. Using the search bar, search for and open the `Virtual Machines` service. +2. Click on the name of the Virtual Machine to be remediated. + +Part B. Remediate each Virtual Machine Disk individually + +1. From the selected Virtual Machine resource window, expand the `Settings` menu item and click `Disks.` +2. For each disk, click the name of the disk to open the disk resource window. +3. From the selected Disk resource window, expand the `Settings` menu item, and click `Disk Export.` + +`check` the checkbox next to `Enable Data Access Authentication Mode`. + +Repeat Part B for each Disk attached to a VM. + +Repeat Parts A and B to remediate all Disks in all VMs. + +### From Powershell + +Ensure that each disk is detached from its associated `Virtual Machine` before proceeding. Once detached, run the following for each disk: + +```bash +$disk = Get-AzDisk -ResourceGroupName '' -DiskName '' +$disk.DataAccessAuthMode = 'AzureActiveDirectory' +Update-AzDisk -ResourceGroup '' -DiskName $disk.Name -Disk $disk +``` + +### From Azure CLI + +Ensure that each disk is detached from its associated `Virtual Machine` before proceeding. Once detached, run the following for each disk: + +```bash +az disk update --name --resource-group --data-access-auth-mode AzureActiveDirectory +``` + +### Default Value + +By default, Data Access Authentication Mode is `Disabled.` diff --git a/cis_v300/docs/cis_v300_8_7.md b/cis_v300/docs/cis_v300_8_7.md new file mode 100644 index 00000000..5c0adfcd --- /dev/null +++ b/cis_v300/docs/cis_v300_8_7.md @@ -0,0 +1,34 @@ +## Description + +For added security, only install organization-approved extensions on VMs. + +Azure virtual machine extensions are small applications that provide post-deployment configuration and automation tasks on Azure virtual machines. These extensions run with administrative privileges and could potentially access anything on a virtual machine. The Azure Portal and community provide several such extensions. Each organization should carefully evaluate these extensions and ensure that only those that are approved for use are actually implemented. + +## Remediation + +### From Azure Portal + +1. Go to `Virtual machines`. +2. For each virtual machine, go to `Settings`. +3. Click on `Extensions + applications`. +4. If there are unapproved extensions, uninstall them. + +### From Azure CLI + +From the audit command identify the unapproved extensions, and use the below CLI command to remove an unapproved extension attached to VM. + +```bash +az vm extension delete --resource-group --vm-name --name +``` + +### From PowerShell + +For each VM and each insecure extension from the Audit Procedure run the following command. + +```bash +Remove-AzVMExtension -ResourceGroupName -Name -VMName +``` + +### Default Value + +By default, no extensions are added to the virtual machines. diff --git a/cis_v300/docs/cis_v300_8_8.md b/cis_v300/docs/cis_v300_8_8.md new file mode 100644 index 00000000..d84a1e5e --- /dev/null +++ b/cis_v300/docs/cis_v300_8_8.md @@ -0,0 +1,13 @@ +## Description + +Install endpoint protection for all virtual machines. + +Installing endpoint protection systems (like anti-malware for Azure) provides for real-time protection capability that helps identify and remove viruses, spyware, and other malicious software. These also offer configurable alerts when known-malicious or unwanted software attempts to install itself or run on Azure systems. + +## Remediation + +Follow Microsoft Azure documentation to install endpoint protection from the security center. Alternatively, you can employ your own endpoint protection tool for your OS. + +### Default Value + +By default Endpoint Protection is disabled. diff --git a/cis_v300/docs/cis_v300_8_9.md b/cis_v300/docs/cis_v300_8_9.md new file mode 100644 index 00000000..62ea6867 --- /dev/null +++ b/cis_v300/docs/cis_v300_8_9.md @@ -0,0 +1,56 @@ +## Description + +**NOTE: This is a legacy recommendation. Managed Disks are encrypted by default and recommended for all new VM implementations.** + +VHD (Virtual Hard Disks) are stored in blob storage and are the old-style disks that were attached to Virtual Machines. The blob VHD was then leased to the VM. By default, storage accounts are not encrypted, and Microsoft Defender will then recommend that the OS disks should be encrypted. Storage accounts can be encrypted as a whole using PMK or CMK. This should be turned on for storage accounts containing VHDs. + +While it is recommended to use Managed Disks which are encrypted by default, "legacy" VHDs may exist for a variety of reasons and may need to remain in VHD format. VHDs are not encrypted by default, so this recommendation intends to address the security of these disks. In these niche cases, VHDs should be encrypted using the procedures in this recommendation to encrypt and protect the data content. + +If a virtual machine is using a VHD and can be converted to a managed disk, instructions for this procedure can be found in the resources section of this recommendation under the title "Convert VHD to Managed Disk." + +## Remediation + +### From Azure Portal + +1. Navigate to the `storage account` that you wish to encrypt. +2. Select `encryption`. +3. Select the `encryption type` that you wish to use. + +If you wish to use a Microsoft-managed key (the default), you can save at this point and encryption will be applied to the account. + +If you select `Customer-managed keys`, it will ask for the location of the key (The default is an Azure Key Vault) and the key name. +Once these are captured, save the configuration and the account will be encrypted using the provided key. + +### From Azure CLI + +Create the Key Vault + +```bash +az keyvault create --name --resource-group --location --enabled-for-disk-encryption +``` + +Encrypt the disk and store the key in Key Vault + +```bash +az vm encryption enable -g --name --disk-encryption-keyvault myKV +``` + +### From PowerShell + +This process uses a Key Vault to store the keys +Create the Key Vault + +```bash +New-AzKeyvault -name -ResourceGroupName -Location -EnabledForDiskEncryption +``` + +Encrypt the disk and store the key in Key Vault + +```bash +$KeyVault = Get-AzKeyVault -VaultName -ResourceGroupName +Set-AzVMDiskEncryptionExtension -ResourceGroupName -VMName -DiskEncryptionKeyVaultUrl $KeyVault.VaultUri -DiskEncryptionKeyVaultId $KeyVault.ResourceId +``` + +### Default Value + +The default value for encryption is "NO Encryption". diff --git a/cis_v300/docs/cis_v300_9.md b/cis_v300/docs/cis_v300_9.md new file mode 100644 index 00000000..2eb7d886 --- /dev/null +++ b/cis_v300/docs/cis_v300_9.md @@ -0,0 +1,3 @@ +## Overview + +This section covers security recommendations for Azure AppService. diff --git a/cis_v300/docs/cis_v300_9_1.md b/cis_v300/docs/cis_v300_9_1.md new file mode 100644 index 00000000..7a8150ac --- /dev/null +++ b/cis_v300/docs/cis_v300_9_1.md @@ -0,0 +1,33 @@ +## Description + +Azure App Service allows apps to run under both HTTP and HTTPS by default. Apps can be accessed by anyone using non-secure HTTP links by default. Non-secure HTTP requests can be restricted and all HTTP requests redirected to the secure HTTPS port. It is recommended to enforce HTTPS-only traffic. + +Enabling HTTPS-only traffic will redirect all non-secure HTTP requests to HTTPS ports. HTTPS uses the TLS/SSL protocol to provide a secure connection which is both encrypted and authenticated. It is therefore important to support HTTPS for the security benefits. + +## Remediation + +### From Azure Portal + +1. Login to Azure Portal using [https://portal.azure.com](https://portal.azure.com). +2. Go to `App Services`. +3. For each App Service. +4. Under `Setting` section, click on `Configuration`. +5. Under the `General Settings` tab, set `HTTPS Only` to `On` under `Platform Settings`. + +### From Azure CLI + +To set HTTPS-only traffic value for an existing app, run the following command: + +```bash +az webapp update --resource-group --name --set httpsOnly=true +``` + +### From Powershell + +```bash +Set-AzWebApp -ResourceGroupName -Name -HttpsOnly $true +``` + +### Default Value + +By default, HTTPS-only feature will be disabled when a new app is created using the command-line tool or Azure Portal console. diff --git a/cis_v300/docs/cis_v300_9_10.md b/cis_v300/docs/cis_v300_9_10.md new file mode 100644 index 00000000..2ba594e2 --- /dev/null +++ b/cis_v300/docs/cis_v300_9_10.md @@ -0,0 +1,35 @@ +## Description + +Periodically, newer versions are released for HTTP either due to security flaws or to include additional functionality. Using the latest HTTP version for apps to take advantage of security fixes, if any, and/or new functionalities of the newer version. + +Newer versions may contain security enhancements and additional functionality. Using the latest version is recommended in order to take advantage of enhancements and new capabilities. With each software installation, organizations need to determine if a given update meets their requirements. They must also verify the compatibility and support provided for any additional software against the update revision that is selected. + +HTTP 2.0 has additional performance improvements on the head-of-line blocking problem of old HTTP version, header compression, and prioritization of requests. HTTP 2.0 no longer supports HTTP 1.1's chunked transfer encoding mechanism, as it provides its own, more efficient, mechanisms for data streaming. + +## Remediation + +### From Azure Portal + +1. Login to Azure Portal using [https://portal.azure.com](https://portal.azure.com). +2. Go to `App Services`. +3. Click on each App. +4. Under `Setting` section, Click on `Configuration`. +5. Set `HTTP version` to `2.0` under `General settings`. + +NOTE: Most modern browsers support HTTP 2.0 protocol over TLS only, while non-encrypted traffic continues to use HTTP 1.1. To ensure that client browsers connect to your app with HTTP/2, either buy an App Service Certificate for your app's custom domain or bind a third-party certificate. + +### From Azure CLI + +To set HTTP 2.0 version for an existing app, run the following command: + +```bash +az webapp config set --resource-group --name --http20-enabled true +``` + +### From PowerShell + +To enable HTTP 2.0 version support, run the following command: + +```bash +Set-AzWebApp -ResourceGroupName -Name -Http20Enabled $true +``` diff --git a/cis_v300/docs/cis_v300_9_11.md b/cis_v300/docs/cis_v300_9_11.md new file mode 100644 index 00000000..003b8c57 --- /dev/null +++ b/cis_v300/docs/cis_v300_9_11.md @@ -0,0 +1,126 @@ +## Description + +Azure Key Vault will store multiple types of sensitive information such as encryption keys, certificate thumbprints, and Managed Identity Credentials. Access to these 'Secrets' can be controlled through granular permissions. + +The credentials given to an application have permissions to create, delete, or modify data stored within the systems they access. If these credentials are stored within the application itself, anyone with access to the application or a copy of the code has access to them. Storing within Azure Key Vault as secrets increases security by controlling access. This also allows for updates of the credentials without redeploying the entire application. + +## Remediation + +Remediation has 2 steps + +1. Setup the Key Vault. +2. Setup the App Service to use the Key Vault. + +### Step 1: Set up the Key Vault + +### From Azure CLI + +```bash +az keyvault create --name "" --resource-group "" --location myLocation +``` + +### From Powershell + +```bash +New-AzKeyvault -name -ResourceGroupName -Location +``` + +### Step 2: Set up the App Service to use the Key Vault + +Sample JSON Template for App Service Configuration: + +```json +{ + "resources": [ + { + "type": "Microsoft.Storage/storageAccounts", + "name": "[variables('storageAccountName')]" + }, + { + "type": "Microsoft.Insights/components", + "name": "[variables('appInsightsName')]" + }, + { + "type": "Microsoft.Web/sites", + "name": "[variables('functionAppName')]", + "identity": { + "type": "SystemAssigned" + }, + "resources": [ + { + "type": "config", + "name": "appsettings", + "dependsOn": [ + "[resourceId('Microsoft.Web/sites', variables('functionAppName'))]", + "[resourceId('Microsoft.KeyVault/vaults/', variables('keyVaultName'))]", + "[resourceId('Microsoft.KeyVault/vaults/secrets', variables('keyVaultName'), variables('storageConnectionStringName'))]", + "[resourceId('Microsoft.KeyVault/vaults/secrets', variables('keyVaultName'), variables('appInsightsKeyName'))]" + ], + "properties": { + "AzureWebJobsStorage": "[concat('@Microsoft.KeyVault(SecretUri=', reference(variables('storageConnectionStringResourceId')).secretUriWithVersion, ')')]", + "WEBSITE_CONTENTAZUREFILECONNECTIONSTRING": "[concat('@Microsoft.KeyVault(SecretUri=', reference(variables('storageConnectionStringResourceId')).secretUriWithVersion, ')')]", + "APPINSIGHTS_INSTRUMENTATIONKEY": "[concat('@Microsoft.KeyVault(SecretUri=', reference(variables('appInsightsKeyResourceId')).secretUriWithVersion, ')')]", + "WEBSITE_ENABLE_SYNC_UPDATE_SITE": "true" + } + }, + { + "type": "sourcecontrols", + "name": "web", + "dependsOn": [ + "[resourceId('Microsoft.Web/sites', variables('functionAppName'))]", + "[resourceId('Microsoft.Web/sites/config', variables('functionAppName'), 'appsettings')]" + ] + } + ] + }, + { + "type": "Microsoft.KeyVault/vaults", + "name": "[variables('keyVaultName')]", + "dependsOn": [ + "[resourceId('Microsoft.Web/sites', variables('functionAppName'))]" + ], + "properties": { + "accessPolicies": [ + { + "tenantId": "[reference(concat('Microsoft.Web/sites/', variables('functionAppName'), '/providers/Microsoft.ManagedIdentity/Identities/default'), '2015-08-31-PREVIEW').tenantId]", + "objectId": "[reference(concat('Microsoft.Web/sites/', variables('functionAppName'), '/providers/Microsoft.ManagedIdentity/Identities/default'), '2015-08-31-PREVIEW').principalId]", + "permissions": { + "secrets": [ + "get" + ] + } + } + ] + }, + "resources": [ + { + "type": "secrets", + "name": "[variables('storageConnectionStringName')]", + "dependsOn": [ + "[resourceId('Microsoft.KeyVault/vaults/', variables('keyVaultName'))]", + "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]" + ], + "properties": { + "value": "[concat('DefaultEndpointsProtocol=https;AccountName=', variables('storageAccountName'), ';AccountKey=', listKeys(variables('storageAccountResourceId'),'2015-05-01-preview').key1)]" + } + }, + { + "type": "secrets", + "name": "[variables('appInsightsKeyName')]", + "dependsOn": [ + "[resourceId('Microsoft.KeyVault/vaults/', variables('keyVaultName'))]", + "[resourceId('Microsoft.Insights/components', variables('appInsightsName'))]" + ], + "properties": { + "value": "[reference(resourceId('microsoft.insights/components/', variables('appInsightsName')), '2015-05-01').InstrumentationKey]" + } + } + ] + } + ] +} +``` + +### Default Value + +By default, no Azure Key Vaults are created. diff --git a/cis_v300/docs/cis_v300_9_12.md b/cis_v300/docs/cis_v300_9_12.md new file mode 100644 index 00000000..af5fb2c6 --- /dev/null +++ b/cis_v300/docs/cis_v300_9_12.md @@ -0,0 +1,41 @@ +## Description + +Remote Debugging allows Azure App Service to be debugged in real-time directly on the Azure environment. When remote debugging is enabled, it opens a communication channel that could potentially be exploited by unauthorized users if not properly secured. + +Disabling remote debugging on Azure App Service is primarily about enhancing security. + +Remote debugging opens a communication channel that can be exploited by attackers. By disabling it, you reduce the number of potential entry points for unauthorized access. + +If remote debugging is enabled without proper access controls, it can allow unauthorized users to connect to your application, potentially leading to data breaches or malicious code execution. + +During a remote debugging session, sensitive information might be exposed. Disabling remote debugging helps ensure that such data remains secure. This minimizes the use of remote access tools to reduce risk. + +## Remediation + +### From Azure Portal + +1. Login to Azure Portal using https://portal.azure.com. +2. Go to `App Services`. +3. Click on each App. +4. Under `Setting` section, Click on `Configuration`. +5. Under the `General settings` tab, set the `Remote debugging` option to `Off`. + +### From Azure CLI + +To set remote debugging status to off, run the following command + +```bash +az webapp config set --resource-group --name --remote-debugging-enabled false +``` + +### From PowerShell + +To set remote debugging status to off, run the following command + +```bash +Set-AzWebApp -ResourceGroupName -Name -RemoteDebuggingEnabled $false +``` + +### Default Value + +By default, remote debugging is set to `off`. diff --git a/cis_v300/docs/cis_v300_9_2.md b/cis_v300/docs/cis_v300_9_2.md new file mode 100644 index 00000000..312c520e --- /dev/null +++ b/cis_v300/docs/cis_v300_9_2.md @@ -0,0 +1,39 @@ +## Description + +Azure App Service Authentication is a feature that can prevent anonymous HTTP requests from reaching a Web Application or authenticate those with tokens before they reach the app. If an anonymous request is received from a browser, App Service will redirect to a logon page. To handle the logon process, a choice from a set of identity providers can be made, or a custom authentication mechanism can be implemented. + +By Enabling App Service Authentication, every incoming HTTP request passes through it before being handled by the application code. It also handles authentication of users with the specified provider (Entra ID, Facebook, Google, Microsoft Account, and Twitter), validation, storing and refreshing of tokens, managing the authenticated sessions and injecting identity information into request headers. Disabling HTTP Basic Authentication functionality further ensures legacy authentication methods are disabled within the application. + +## Remediation + +### From Azure Portal + +1. Login to Azure Portal using [https://portal.azure.com](https://portal.azure.com). +2. Go to `App Services`. +3. Click on each App. +4. Under `Setting` section, click on `Authentication`. +5. If no identity providers are set up, then click `Add identity provider`. +6. Choose other parameters as per your requirements and click on `Add`. + +To disable the `Basic Auth Publishing Credentials` setting, perform the following steps: + +1. Login to Azure Portal using [https://portal.azure.com](https://portal.azure.com). +2. Go to `App Services`. +3. Click on each App. +4. Under `Settings`, click on `Configuration`. +5. Click on the 'General Settings' tab. +6. Under `Platform settings`, ensure `Basic Auth Publishing Credentials` is set to `Off`. + +### From Azure CLI + +To set App Service Authentication for an existing app, run the following command: + +```bash +az webapp auth update --resource-group --name --enabled true +``` + +**Note:** In order to access `App Service authentication` settings for Web app using Microsoft API requires `Website contributor` permission at subscription level. A custom role can be created in place of `Website contributor` to provide more specific permission and maintain the principle of least privileged access. + +### Default Value + +By default, App Service Authentication is disabled when a new app is created using the command-line tool or Azure Portal console. diff --git a/cis_v300/docs/cis_v300_9_3.md b/cis_v300/docs/cis_v300_9_3.md new file mode 100644 index 00000000..88ba715a --- /dev/null +++ b/cis_v300/docs/cis_v300_9_3.md @@ -0,0 +1,37 @@ +## Description + +By default, App Services can be deployed over FTP. If FTP is required for an essential deployment workflow, FTPS should be required for FTP login for all App Services. + +If FTPS is not expressly required for the App, the recommended setting is `Disabled.` + +FTP is an unencrypted network protocol that will transmit data - including passwords - in clear-text. The use of this protocol can lead to both data and credential compromise, and can present opportunities for exfiltration, persistence, and lateral movement. + +## Remediation + +### From Azure Portal + +1. Go to the Azure Portal. +2. Select `App Services`. +3. Click on an app. +4. Select `Settings` and then `Configuration`. +5. Under `General Settings`, for the `Platform Settings`, the `FTP state` should be set to `Disabled` or `FTPS Only`. + +### From Azure CLI + +For each out of compliance application, run the following choosing either 'disabled' or 'FtpsOnly' as appropriate: + +```bash +az webapp config set --resource-group --name --ftps-state [disabled|FtpsOnly] +``` + +### From Powershell + +For each out of compliance application, run the following: + +```bash +Set-AzWebApp -ResourceGroupName -Name -FtpsState +``` + +### Default Value + +By default, FTP based deployment is `All allowed`. diff --git a/cis_v300/docs/cis_v300_9_4.md b/cis_v300/docs/cis_v300_9_4.md new file mode 100644 index 00000000..a3cdf852 --- /dev/null +++ b/cis_v300/docs/cis_v300_9_4.md @@ -0,0 +1,33 @@ +## Description + +The TLS (Transport Layer Security) protocol secures transmission of data over the internet using standard encryption technology. Encryption should be set with the latest version of TLS. App service allows TLS 1.2 by default, which is the recommended TLS level by industry standards such as PCI DSS. + +App service currently allows the web app to set TLS versions 1.0, 1.1 and 1.2. It is highly recommended to use the latest TLS 1.2 version for web app secure connections. + +## Remediation + +### From Azure Portal + +1. Login to Azure Portal using [https://portal.azure.com](https://portal.azure.com). +2. Go to `App Services`. +3. Click on each App. +4. Under `Setting` section, Click on `SSL settings`. +5. Under the `Bindings` pane, set `Minimum TLS Version` to `1.2` under `Protocol Settings` section. + +### From Azure CLI + +To set TLS Version for an existing app, run the following command: + +```bash +az webapp config set --resource-group --name --min-tls-version 1.2 +``` + +### From Powershell + +```bash +Set-AzWebApp -ResourceGroupName -Name -MinTlsVersion 1.2 +``` + +### Default Value + +By default, TLS Version feature will be set to 1.2 when a new app is created using the command-line tool or Azure Portal console. diff --git a/cis_v300/docs/cis_v300_9_5.md b/cis_v300/docs/cis_v300_9_5.md new file mode 100644 index 00000000..59fb040f --- /dev/null +++ b/cis_v300/docs/cis_v300_9_5.md @@ -0,0 +1,35 @@ +## Description + +Managed service identity in App Service provides more security by eliminating secrets from the app, such as credentials in the connection strings. When registering an App Service with Entra ID, the app will connect to other Azure services securely without the need for usernames and passwords. + +App Service provides a highly scalable, self-patching web hosting service in Azure. It also provides a managed identity for apps, which is a turn-key solution for securing access to Azure SQL Database and other Azure services. + +## Remediation + +### From Azure Portal + +1. Login to Azure Portal using [https://portal.azure.com](https://portal.azure.com). +2. Go to `App Services`. +3. Click on each App. +4. Under `Setting` section, Click on `Identity`. +5. Under the `System assigned` pane, set `Status` to `On`. + +### From Azure CLI + +To register with Entra ID for an existing app, run the following command: + +```bash +az webapp identity assign --resource-group --name +``` + +### From PowerShell + +To register with Entra ID for an existing app, run the following command: + +```bash +Set-AzWebApp -AssignIdentity $True -ResourceGroupName -Name +``` + +### Default Value + +By default, Managed service identity via Entra ID is disabled. diff --git a/cis_v300/docs/cis_v300_9_6.md b/cis_v300/docs/cis_v300_9_6.md new file mode 100644 index 00000000..998dbef8 --- /dev/null +++ b/cis_v300/docs/cis_v300_9_6.md @@ -0,0 +1,25 @@ +## Description + +Basic Authentication provides the ability to create identities and authentication for an App Service without a centralized Identity Provider. For a more effective, capable, and secure solution for Identity, Authentication, Authorization, and Accountability, a centralized Identity Provider such as Entra ID is strongly advised. + +Basic Authentication introduces an identity silo which can produce privileged access to a resource. This can be exploited in numerous ways and represents a significant vulnerability and attack vector. + +## Remediation + +### From Azure Portal + +1. Search for, and open `App Services` from the search bar. +2. For each App Service listed: +3. Click on the App Service name. +4. Under the `Settings` menu item, click on `Configuration`. +5. Under the `General settings` tab, scroll down to locate the two Basic Auth settings: +- Set the `SCM Basic Auth Publishing Credentials` radio button to `Off`. +- Set the `FTP Basic Auth Publishing Credentials` radio button to `Off`. + +**CAUTION:** The new settings are not yet applied. Applying them may cause your App Service resource to restart - proceed with caution. Click the `Save` button, then click `Continue` to apply the updated configuration. + +Repeat this procedure for each App Service. + +### Default Value + +Both parameters for Basic Authentication (SCM and FTP) are set to `On` by default. diff --git a/cis_v300/docs/cis_v300_9_7.md b/cis_v300/docs/cis_v300_9_7.md new file mode 100644 index 00000000..34678b8a --- /dev/null +++ b/cis_v300/docs/cis_v300_9_7.md @@ -0,0 +1,45 @@ +## Description + +Periodically, older versions of PHP may be deprecated and no longer supported. Using a supported version of PHP for app services is recommended to avoid potential unpatched vulnerabilities. + +Deprecated and unsupported versions of programming and scripting languages can present vulnerabilities which may not be addressed or may not be addressable. + +## Remediation + +### From Azure Portal + +1. From Azure Home open the Portal Menu in the top left. +2. Go to `App Services`. +3. Click on each App. +4. Under `Settings` section, click on `Configuration`. +5. Click on the `General settings` pane, ensure that for a `Stack` of `PHP` the `Major Version` and `Minor Version` reflect a currently supported release. + +_NOTE:_ No action is required If `PHP version` is set to `Off` or is set with an empty value as PHP is not used by your app. + +### From Azure CLI + +List the available PHP runtimes: + +```bash +az webapp list-runtimes +``` + +To set a currently supported PHP version for an existing app, run the following command: + +```bash +az webapp config set --resource-group --name [--linux-fx-version ][--php-version ] +``` + +### From Powershell + +To set a currently supported PHP version for an existing app, run the following command: + +```bash +Set-AzWebApp -ResourceGroupName -Name -phpVersion +``` + +_NOTE:_ Currently there is no way to update an existing web app `Linux FX Version` setting using PowerShell, nor is there a way to create a new web app using PowerShell that configures the PHP runtime in the `Linux FX Version` setting. + +### Default Value + +The version of PHP is whatever was selected upon App creation. diff --git a/cis_v300/docs/cis_v300_9_8.md b/cis_v300/docs/cis_v300_9_8.md new file mode 100644 index 00000000..e2039e9b --- /dev/null +++ b/cis_v300/docs/cis_v300_9_8.md @@ -0,0 +1,39 @@ +## Description + +Periodically, older versions of Python may be deprecated and no longer supported. Using a supported version of Python for app services is recommended to avoid potential unpatched vulnerabilities. + +Deprecated and unsupported versions of programming and scripting languages can present vulnerabilities which may not be addressed or may not be addressable. + +## Remediation + +### From Azure Portal + +1. From Azure Home open the Portal Menu in the top left. +2. Go to `App Services`. +3. Click on each App. +4. Under `Settings` section, click on `Configuration`. +5. Click on the General settings pane and ensure that the Major Version and the Minor Version is set to a currently supported release. + +_NOTE:_ No action is required if `Python version` is set to `Off`, as Python is not used by your app. + +### From Azure CLI + +To see the list of supported runtimes: + +```bash +az webapp list-runtimes +``` + +To set latest Python version for an existing app, run the following command: + +```bash +az webapp config set --resource-group --name [--windows-fx-version "PYTHON|"] [--linux-fx-version "PYTHON|"] +``` + +### From PowerShell + +As of this writing, there is no way to update an existing application's `SiteConfig` or set a new application's `SiteConfig` settings during creation via PowerShell. + +### Default Value + +The version of Python is whatever was selected upon App creation. diff --git a/cis_v300/docs/cis_v300_9_9.md b/cis_v300/docs/cis_v300_9_9.md new file mode 100644 index 00000000..151ab19e --- /dev/null +++ b/cis_v300/docs/cis_v300_9_9.md @@ -0,0 +1,59 @@ +## Description + +Periodically, older versions of Java may be deprecated and no longer supported. Using a supported version of Java for app services is recommended to avoid potential unpatched vulnerabilities. + +Deprecated and unsupported versions of programming and scripting languages can present vulnerabilities which may not be addressed or may not be addressable. + +## Remediation + +### From Azure Portal + +1. Login to Azure Portal using [https://portal.azure.com](https://portal.azure.com). +2. Go to `App Services`. +3. Click on each App. +4. Under `Settings` section, click on `Configuration`. +5. Click on the `General settings` pane and ensure that for a `Stack` of `Java` the `Major Version` and `Minor Version` reflect a currently supported release, and that the `Java web server version` is set to the `auto-update` option. + +_NOTE:_ No action is required if `Java version` is set to `Off`, as Java is not used by your app. + +### From Azure CLI + +To see the list of supported runtimes: + +```bash +az webapp list-runtimes +``` + +To set a currently supported Java version for an existing app, run the following command: + +```bash +az webapp config set --resource-group --name [--java-version --java-container --java-container-version [--windows-fx-version ] [--linux-fx-version ] +``` + +If creating a new application to use a currently supported version of Java, run the following commands. + +To create an app service plan: + +```bash +az appservice plan create --resource-group --name --location [--is-linux --number-of-workers --sku ] [--hyper-v --sku ] +``` + +Get the app service plan ID: + +```bash +az appservice plan list --query "[].{Name:name, ID:id, SKU:sku, Location:location}" +``` + +To create a new Java web application using the retrieved app service ID: + +```bash +az webapp create --resource-group --plan --name [--linux-fx-version ] [--windows-fx-version ] +``` + +### From PowerShell + +As of this writing, there is no way to update an existing application's `SiteConfig` or set a new application's `SiteConfig` settings during creation via PowerShell. + +### Default Value + +The default setting is whichever setting was chosen in the creation of the webapp. diff --git a/cis_v300/section_10.pp b/cis_v300/section_10.pp new file mode 100644 index 00000000..cba99840 --- /dev/null +++ b/cis_v300/section_10.pp @@ -0,0 +1,30 @@ +locals { + cis_v300_10_common_tags = merge(local.cis_v300_common_tags, { + cis_section_id = "10" + }) +} + +benchmark "cis_v300_10" { + title = "10 Miscellaneous" + documentation = file("./cis_v300/docs/cis_v300_10.md") + children = [ + control.cis_v300_10_1 + ] + + tags = merge(local.cis_v300_10_common_tags, { + type = "Benchmark" + }) +} + +control "cis_v300_10_1" { + title = "10.1 Ensure that Resource Locks are set for Mission-Critical Azure Resources" + description = "Resource Manager Locks provide a way for administrators to lock down Azure resources to prevent deletion of, or modifications to, a resource. These locks sit outside of the Role Based Access Controls (RBAC) hierarchy and, when applied, will place restrictions on the resource for all users." + query = query.manual_control + documentation = file("./cis_v300/docs/cis_v300_10_1.md") + + tags = merge(local.cis_v300_8_common_tags, { + cis_item_id = "10.1" + cis_level = "2" + cis_type = "manual" + }) +} diff --git a/cis_v300/section_2.pp b/cis_v300/section_2.pp new file mode 100644 index 00000000..fd07275d --- /dev/null +++ b/cis_v300/section_2.pp @@ -0,0 +1,592 @@ +locals { + cis_v300_2_common_tags = merge(local.cis_v300_common_tags, { + cis_section_id = "2" + }) +} + +locals { + cis_v300_2_1_common_tags = merge(local.cis_v300_2_common_tags, { + cis_section_id = "2.1" + }) + cis_v300_2_2_common_tags = merge(local.cis_v300_2_common_tags, { + cis_section_id = "2.2" + }) +} + +benchmark "cis_v300_2" { + title = "2 Identity" + documentation = file("./cis_v300/docs/cis_v300_2.md") + children = [ + benchmark.cis_v300_2_1, + benchmark.cis_v300_2_2, + control.cis_v300_2_3, + control.cis_v300_2_4, + control.cis_v300_2_5, + control.cis_v300_2_6, + control.cis_v300_2_7, + control.cis_v300_2_8, + control.cis_v300_2_9, + control.cis_v300_2_10, + control.cis_v300_2_11, + control.cis_v300_2_12, + control.cis_v300_2_13, + control.cis_v300_2_14, + control.cis_v300_2_15, + control.cis_v300_2_16, + control.cis_v300_2_17, + control.cis_v300_2_18, + control.cis_v300_2_19, + control.cis_v300_2_20, + control.cis_v300_2_21, + control.cis_v300_2_22, + control.cis_v300_2_23, + control.cis_v300_2_24, + control.cis_v300_2_25, + control.cis_v300_2_26 + ] + + tags = merge(local.cis_v300_2_common_tags, { + type = "Benchmark" + service = "Azure/ActiveDirectory" + }) +} + +benchmark "cis_v300_2_1" { + title = "2.1 Security Defaults (Per-User MFA)" + documentation = file("./cis_v300/docs/cis_v300_2_1.md") + children = [ + control.cis_v300_2_1_1, + control.cis_v300_2_1_2, + control.cis_v300_2_1_3, + control.cis_v300_2_1_4 + ] + + tags = merge(local.cis_v300_2_1_common_tags, { + type = "Benchmark" + service = "Azure/ActiveDirectory" + }) +} + +control "cis_v300_2_1_1" { + title = "2.1.1 Ensure Security Defaults is enabled on Microsoft Entra ID" + description = "Security defaults in Microsoft Entra ID make it easier to be secure and help protect your organization. Security defaults contain preconfigured security settings for common attacks. Security defaults is available to everyone. The goal is to ensure that all organizations have a basic level of security enabled at no extra cost. You may turn on security defaults in the Azure portal." + query = query.ad_manual_control + documentation = file("./cis_v300/docs/cis_v300_2_1_1.md") + + tags = merge(local.cis_v300_2_1_common_tags, { + cis_item_id = "2.1.1" + cis_level = "1" + cis_type = "manual" + service = "Azure/ActiveDirectory" + }) +} + +control "cis_v300_2_1_2" { + title = "2.1.2 Ensure that 'Multi-Factor Auth Status' is 'Enabled' for all Privileged Users" + description = "Enable multi-factor authentication for all roles, groups, and users that have write access or permissions to Azure resources." + query = query.ad_manual_control + documentation = file("./cis_v300/docs/cis_v300_2_1_2.md") + + tags = merge(local.cis_v300_2_1_common_tags, { + cis_item_id = "2.1.2" + cis_level = "1" + cis_type = "manual" + service = "Azure/ActiveDirectory" + }) +} + +control "cis_v300_2_1_3" { + title = "2.1.3 Ensure that 'Multi-Factor Auth Status' is 'Enabled' for all Non-Privileged Users" + description = "Enable multi-factor authentication for all non-privileged users." + query = query.ad_manual_control + documentation = file("./cis_v300/docs/cis_v300_2_1_3.md") + + tags = merge(local.cis_v300_2_1_common_tags, { + cis_item_id = "2.1.3" + cis_level = "2" + cis_type = "manual" + service = "Azure/ActiveDirectory" + }) +} + +control "cis_v300_2_1_4" { + title = "2.1.4 Ensure that 'Allow users to remember multi-factor authentication on devices they trust' is Disabled" + description = "Do not allow users to remember multi-factor authentication on devices." + query = query.ad_manual_control + documentation = file("./cis_v300/docs/cis_v300_2_1_4.md") + + tags = merge(local.cis_v300_2_1_common_tags, { + cis_item_id = "2.1.4" + cis_level = "1" + cis_type = "manual" + service = "Azure/ActiveDirectory" + }) +} + +benchmark "cis_v300_2_2" { + title = "2.2 Conditional Access" + documentation = file("./cis_v300/docs/cis_v300_2_2.md") + children = [ + control.cis_v300_2_2_1, + control.cis_v300_2_2_2, + control.cis_v300_2_2_3, + control.cis_v300_2_2_4, + control.cis_v300_2_2_5, + control.cis_v300_2_2_6, + control.cis_v300_2_2_7, + control.cis_v300_2_2_8 + ] + + tags = merge(local.cis_v300_2_2_common_tags, { + type = "Benchmark" + service = "Azure/ActiveDirectory" + }) +} + +control "cis_v300_2_2_1" { + title = "2.2.1 Ensure Trusted Locations Are Defined" + description = "Microsoft Entra ID Conditional Access allows an organization to configure Named locations and configure whether those locations are trusted or untrusted. These settings provide organizations the means to specify Geographical locations for use in conditional access policies, or define actual IP addresses and IP ranges and whether or not those IP addresses and/or ranges are trusted by the organization." + query = query.ad_manual_control + documentation = file("./cis_v300/docs/cis_v300_2_2_1.md") + + tags = merge(local.cis_v300_2_2_common_tags, { + cis_item_id = "2.2.1" + cis_level = "2" + cis_type = "manual" + service = "Azure/ActiveDirectory" + }) +} + +control "cis_v300_2_2_2" { + title = "2.2.2 Ensure that an exclusionary Geographic Access Policy is considered" + description = "Conditional Access Policies can be used to block access from geographic locations that are deemed out-of-scope for your organization or application. The scope and variables for this policy should be carefully examined and defined." + query = query.ad_manual_control + documentation = file("./cis_v300/docs/cis_v300_2_2_2.md") + + tags = merge(local.cis_v300_2_2_common_tags, { + cis_item_id = "2.2.2" + cis_level = "2" + cis_type = "manual" + service = "Azure/ActiveDirectory" + }) +} + +control "cis_v300_2_2_3" { + title = "2.2.3 Ensure that an exclusionary Device code flow policy is considered" + description = "Conditional Access Policies can be used to prevent the Device code authentication flow. Device code flow should be permitted only for users that regularly perform duties that explicitly require the use of Device Code to authenticate, such as utilizing Azure with PowerShell." + query = query.ad_manual_control + documentation = file("./cis_v300/docs/cis_v300_2_2_3.md") + + tags = merge(local.cis_v300_2_2_common_tags, { + cis_item_id = "2.2.3" + cis_level = "2" + cis_type = "manual" + service = "Azure/ActiveDirectory" + }) +} + +control "cis_v300_2_2_4" { + title = "2.2.4 Ensure that A Multi-factor Authentication Policy Exists for Administrative Groups" + description = "For designated users, they will be prompted to use their multi-factor authentication (MFA) process on login." + query = query.ad_manual_control + documentation = file("./cis_v300/docs/cis_v300_2_2_4.md") + + tags = merge(local.cis_v300_2_2_common_tags, { + cis_item_id = "2.2.4" + cis_level = "2" + cis_type = "manual" + service = "Azure/ActiveDirectory" + }) +} + +control "cis_v300_2_2_5" { + title = "2.2.5 Ensure that A Multi-factor Authentication Policy Exists for All Users" + description = "For designated users, they will be prompted to use their multi-factor authentication (MFA) process on logins." + query = query.ad_manual_control + documentation = file("./cis_v300/docs/cis_v300_2_2_5.md") + + tags = merge(local.cis_v300_2_2_common_tags, { + cis_item_id = "2.2.5" + cis_level = "2" + cis_type = "manual" + service = "Azure/ActiveDirectory" + }) +} + +control "cis_v300_2_2_6" { + title = "2.2.6 Ensure Multi-factor Authentication is Required for Risky Sign-ins" + description = "Entra ID tracks the behavior of sign-in events. If the Entra ID domain is licensed with P2, the sign-in behavior can be used as a detection mechanism for additional scrutiny during the sign-in event. If this policy is set up, then Risky Sign-in events will prompt users to use multi-factor authentication (MFA) tokens on login for additional verification." + query = query.ad_manual_control + documentation = file("./cis_v300/docs/cis_v300_2_2_6.md") + + tags = merge(local.cis_v300_2_2_common_tags, { + cis_item_id = "2.2.6" + cis_level = "2" + cis_type = "manual" + service = "Azure/ActiveDirectory" + }) +} + +control "cis_v300_2_2_7" { + title = "2.2.7 Ensure Multifactor Authentication is Required for Windows Azure Service Management API" + description = "This recommendation ensures that users accessing the Windows Azure Service Management API (i.e. Azure Powershell, Azure CLI, Azure Resource Manager API, etc.) are required to use multifactor authentication (MFA) credentials when accessing resources through the Windows Azure Service Management API." + query = query.iam_conditional_access_mfa_enabled + documentation = file("./cis_v300/docs/cis_v300_2_2_7.md") + + tags = merge(local.cis_v300_2_2_common_tags, { + cis_item_id = "2.2.7" + cis_level = "2" + cis_type = "manual" + service = "Azure/ActiveDirectory" + }) +} + +control "cis_v300_2_2_8" { + title = "2.2.8 Ensure Multifactor Authentication is Required to access Microsoft Admin Portals" + description = "This recommendation ensures that users accessing Microsoft Admin Portals (i.e. Microsoft 365 Admin, Microsoft 365 Defender, Exchange Admin Center, Azure Portal, etc.) are required to use multifactor authentication (MFA) credentials when logging into an Admin Portal." + query = query.iam_conditional_access_mfa_enabled_for_administrators + documentation = file("./cis_v300/docs/cis_v300_2_2_8.md") + + tags = merge(local.cis_v300_2_2_common_tags, { + cis_item_id = "2.2.8" + cis_level = "1" + cis_type = "manual" + service = "Azure/ActiveDirectory" + }) +} + +control "cis_v300_2_3" { + title = "2.3 Ensure that 'Restrict non-admin users from creating tenants' is set to 'Yes'" + description = "Require administrators or appropriately delegated users to create new tenants." + query = query.ad_manual_control + documentation = file("./cis_v300/docs/cis_v300_2_3.md") + + tags = merge(local.cis_v300_2_common_tags, { + cis_item_id = "2.3" + cis_level = "1" + cis_type = "automated" + service = "Azure/ActiveDirectory" + }) +} + +control "cis_v300_2_4" { + title = "2.4 Ensure Guest Users Are Reviewed on a Regular Basis" + description = "Microsoft Entra ID has native and extended identity functionality allowing you to invite people from outside your organization to be guest users in your cloud account and sign in with their own work, school, or social identities." + query = query.ad_guest_user_reviewed_monthly + documentation = file("./cis_v300/docs/cis_v300_2_4.md") + + tags = merge(local.cis_v300_2_common_tags, { + cis_item_id = "2.4" + cis_level = "1" + cis_type = "manual" + service = "Azure/ActiveDirectory" + }) +} + +control "cis_v300_2_5" { + title = "2.5 Ensure That 'Number of methods required to reset' is set to '2'" + description = "Ensures that two alternate forms of identification are provided before allowing a password reset." + query = query.ad_manual_control + documentation = file("./cis_v300/docs/cis_v300_2_5.md") + + tags = merge(local.cis_v300_2_common_tags, { + cis_item_id = "2.5" + cis_level = "1" + cis_type = "manual" + service = "Azure/ActiveDirectory" + }) +} + +control "cis_v300_2_6" { + title = "2.6 Ensure that account 'Lockout Threshold' is less than or equal to '10'" + description = "The account lockout threshold determines how many failed login attempts are permitted prior to placing the account in a locked-out state and initiating a variable lockout duration." + query = query.ad_manual_control + documentation = file("./cis_v300/docs/cis_v300_2_6.md") + + tags = merge(local.cis_v300_2_common_tags, { + cis_item_id = "2.6" + cis_level = "1" + cis_type = "manual" + service = "Azure/ActiveDirectory" + }) +} + +control "cis_v300_2_7" { + title = "2.7 Ensure that account 'Lockout duration in seconds' is greater than or equal to '60'" + description = "The account lockout duration value determines how long an account retains the status of lockout, and therefore how long before a user can continue to attempt to login after passing the lockout threshold." + query = query.ad_manual_control + documentation = file("./cis_v300/docs/cis_v300_2_7.md") + + tags = merge(local.cis_v300_2_common_tags, { + cis_item_id = "2.7" + cis_level = "1" + cis_type = "manual" + service = "Azure/ActiveDirectory" + }) +} + +control "cis_v300_2_8" { + title = "2.8 Ensure that a Custom Bad Password List is set to 'Enforce' for your Organization" + description = "Microsoft Azure provides a Global Banned Password policy that applies to Azure administrative and normal user accounts. This is not applied to user accounts that are synced from an on-premise Active Directory unless Azure AD Connect is used and you enable EnforceCloudPasswordPolicyForPasswordSyncedUsers. Please see the list in default values on the specifics of this policy. To further password security, it is recommended to further define a custom banned password policy." + query = query.ad_manual_control + documentation = file("./cis_v300/docs/cis_v300_2_8.md") + + tags = merge(local.cis_v300_2_common_tags, { + cis_item_id = "2.8" + cis_level = "1" + cis_type = "manual" + service = "Azure/ActiveDirectory" + }) +} + +control "cis_v300_2_9" { + title = "2.9 Ensure that 'Number of days before users are asked to re-confirm their authentication information' is not set to '0'" + description = "Ensure that the number of days before users are asked to re-confirm their authentication information is not set to 0." + query = query.ad_manual_control + documentation = file("./cis_v300/docs/cis_v300_2_9.md") + + tags = merge(local.cis_v300_2_common_tags, { + cis_item_id = "2.9" + cis_level = "1" + cis_type = "manual" + service = "Azure/ActiveDirectory" + }) +} + +control "cis_v300_2_10" { + title = "2.10 Ensure that 'Notify users on password resets?' is set to 'Yes'" + description = "Ensure that users are notified on their primary and alternate emails on password resets." + query = query.ad_manual_control + documentation = file("./cis_v300/docs/cis_v300_2_10.md") + + tags = merge(local.cis_v300_2_common_tags, { + cis_item_id = "2.10" + cis_level = "1" + cis_type = "manual" + service = "Azure/ActiveDirectory" + }) +} + +control "cis_v300_2_11" { + title = "2.11 Ensure That 'Notify all admins when other admins reset their password?' is set to 'Yes'" + description = "Ensure that all Global Administrators are notified if any other administrator resets their password." + query = query.ad_manual_control + documentation = file("./cis_v300/docs/cis_v300_2_11.md") + + tags = merge(local.cis_v300_2_common_tags, { + cis_item_id = "2.11" + cis_level = "1" + cis_type = "manual" + service = "Azure/ActiveDirectory" + }) +} + +control "cis_v300_2_12" { + title = "2.12 Ensure 'User consent for applications' is set to 'Do not allow user consent'" + description = "Require administrators to provide consent for applications before use." + query = query.ad_manual_control + documentation = file("./cis_v300/docs/cis_v300_2_12.md") + + tags = merge(local.cis_v300_2_common_tags, { + cis_item_id = "2.12" + cis_level = "1" + cis_type = "manual" + service = "Azure/ActiveDirectory" + }) +} + +control "cis_v300_2_13" { + title = "2.13 Ensure 'User consent for applications' Is Set To 'Allow for Verified Publishers'" + description = "Allow users to provide consent for selected permissions when a request is coming from a verified publisher." + query = query.ad_manual_control + documentation = file("./cis_v300/docs/cis_v300_2_13.md") + + tags = merge(local.cis_v300_2_common_tags, { + cis_item_id = "2.13" + cis_level = "2" + cis_type = "manual" + service = "Azure/ActiveDirectory" + }) +} + +control "cis_v300_2_14" { + title = "2.14 Ensure That 'Users Can Register Applications' Is Set to 'No'" + description = "Require administrators or appropriately delegated users to register third-party applications." + query = query.iam_user_not_allowed_to_register_application + documentation = file("./cis_v300/docs/cis_v300_2_14.md") + + tags = merge(local.cis_v300_2_common_tags, { + cis_item_id = "2.14" + cis_level = "1" + cis_type = "automated" + service = "Azure/ActiveDirectory" + }) +} + +control "cis_v300_2_15" { + title = "2.15 Ensure That 'Guest users access restrictions' is set to 'Guest user access is restricted to properties and memberships of their own directory objects'" + description = "Limit guest user permissions." + query = query.ad_manual_control + documentation = file("./cis_v300/docs/cis_v300_2_15.md") + + tags = merge(local.cis_v300_2_common_tags, { + cis_item_id = "2.15" + cis_level = "1" + cis_type = "automated" + service = "Azure/ActiveDirectory" + }) +} + +control "cis_v300_2_16" { + title = "2.16 Ensure that 'Guest invite restrictions' is set to 'Only users assigned to specific admin roles can invite guest users'" + description = "Restrict invitations to users with specific administrative roles only." + query = query.ad_manual_control + documentation = file("./cis_v300/docs/cis_v300_2_16.md") + + tags = merge(local.cis_v300_2_common_tags, { + cis_item_id = "2.16" + cis_level = "2" + cis_type = "automated" + service = "Azure/ActiveDirectory" + }) +} + +control "cis_v300_2_17" { + title = "2.17 Ensure That 'Restrict access to Microsoft Entra admin center' is Set to 'Yes'" + description = "Restrict access to the Azure AD administration portal to administrators only." + query = query.ad_manual_control + documentation = file("./cis_v300/docs/cis_v300_2_17.md") + + tags = merge(local.cis_v300_2_common_tags, { + cis_item_id = "2.17" + cis_level = "1" + cis_type = "manual" + service = "Azure/ActiveDirectory" + }) +} + +control "cis_v300_2_18" { + title = "2.18 Ensure that 'Restrict user ability to access groups features in the Access Pane' is Set to 'Yes'" + description = "Restrict access to group web interface in the Access Panel portal." + query = query.ad_manual_control + documentation = file("./cis_v300/docs/cis_v300_2_18.md") + + tags = merge(local.cis_v300_2_common_tags, { + cis_item_id = "2.18" + cis_level = "2" + cis_type = "manual" + service = "Azure/ActiveDirectory" + }) +} + +control "cis_v300_2_19" { + title = "2.19 Ensure that 'Users can create security groups in Azure portals, API or PowerShell' is set to 'No'" + description = "Restrict security group creation to administrators only." + query = query.iam_user_not_allowed_to_create_security_group + documentation = file("./cis_v300/docs/cis_v300_2_19.md") + + tags = merge(local.cis_v300_2_common_tags, { + cis_item_id = "2.19" + cis_level = "2" + cis_type = "manual" + service = "Azure/ActiveDirectory" + }) +} + +control "cis_v300_2_20" { + title = "2.20 Ensure that 'Owners can manage group membership requests in the Access Panel' is set to 'No'" + description = "Restrict security group management to administrators only." + query = query.ad_manual_control + documentation = file("./cis_v300/docs/cis_v300_2_20.md") + + tags = merge(local.cis_v300_2_common_tags, { + cis_item_id = "2.20" + cis_level = "2" + cis_type = "manual" + service = "Azure/ActiveDirectory" + }) +} + +control "cis_v300_2_21" { + title = "2.21 Ensure that 'Users can create Microsoft 365 groups in Azure portals, API or PowerShell' is set to 'No'" + description = "Restrict Microsoft 365 group creation to administrators only." + query = query.ad_manual_control + documentation = file("./cis_v300/docs/cis_v300_2_21.md") + + tags = merge(local.cis_v300_2_common_tags, { + cis_item_id = "2.21" + cis_level = "2" + cis_type = "manual" + service = "Azure/ActiveDirectory" + }) +} + +control "cis_v300_2_22" { + title = "2.22 Ensure that 'Require Multi-Factor Authentication to register or join devices with Microsoft Entra ID' is set to 'Yes'" + description = "Joining or registering devices to the active directory should require Multi-factor authentication." + query = query.ad_manual_control + documentation = file("./cis_v300/docs/cis_v300_2_22.md") + + tags = merge(local.cis_v300_2_common_tags, { + cis_item_id = "2.22" + cis_level = "1" + cis_type = "manual" + service = "Azure/ActiveDirectory" + }) +} + +control "cis_v300_2_23" { + title = "2.23 Ensure That No Custom Subscription Administrator Roles Exist" + description = "The principle of least privilege should be followed and only necessary privileges should be assigned instead of allowing full administrative access." + query = query.iam_no_custom_subscription_owner_roles_created + documentation = file("./cis_v300/docs/cis_v300_2_23.md") + + tags = merge(local.cis_v300_2_common_tags, { + cis_item_id = "2.23" + cis_level = "1" + cis_type = "automated" + service = "Azure/ActiveDirectory" + }) +} + +control "cis_v300_2_24" { + title = "2.24 Ensure a Custom Role is Assigned Permissions for Administering Resource Locks" + description = "Resource locking is a powerful protection mechanism that can prevent inadvertent modification/deletion of resources within Azure subscriptions/Resource Groups and is a recommended NIST configuration." + query = query.ad_manual_control + documentation = file("./cis_v300/docs/cis_v300_2_24.md") + + tags = merge(local.cis_v300_2_common_tags, { + cis_item_id = "2.24" + cis_level = "2" + cis_type = "manual" + service = "Azure/ActiveDirectory" + }) +} + +control "cis_v300_2_25" { + title = "2.25 Ensure That `Subscription leaving Microsoft Entra ID directory` and `Subscription entering Microsoft Entra ID directory` Is Set To 'Permit No One'" + description = "Users who are set as subscription owners are able to make administrative changes to the subscriptions and move them into and out of Azure Active Directories." + query = query.ad_manual_control + documentation = file("./cis_v300/docs/cis_v300_2_25.md") + + tags = merge(local.cis_v300_2_common_tags, { + cis_item_id = "2.25" + cis_level = "2" + cis_type = "manual" + service = "Azure/ActiveDirectory" + }) +} + +control "cis_v300_2_26" { + title = "2.26 Ensure fewer than 5 users have global administrator assignment" + description = "This recommendation aims to maintain a balance between security and operational efficiency by ensuring that a minimum of 2 and a maximum of 4 users are assigned the Global Administrator role in Microsoft Entra ID. Having at least two Global Administrators ensures redundancy, while limiting the number to four reduces the risk of excessive privileged access." + query = query.iam_global_administrator_max_5 + documentation = file("./cis_v300/docs/cis_v300_2_26.md") + + tags = merge(local.cis_v300_2_common_tags, { + cis_item_id = "2.26" + cis_level = "1" + cis_type = "manual" + service = "Azure/ActiveDirectory" + }) +} \ No newline at end of file diff --git a/cis_v300/section_3.pp b/cis_v300/section_3.pp new file mode 100644 index 00000000..03987967 --- /dev/null +++ b/cis_v300/section_3.pp @@ -0,0 +1,681 @@ +locals { + cis_v300_3_common_tags = merge(local.cis_v300_common_tags, { + cis_section_id = "3" + }) +} + +locals { + cis_v300_3_1_common_tags = merge(local.cis_v300_3_common_tags, { + cis_section_id = "3.1" + }) + cis_v300_3_2_common_tags = merge(local.cis_v300_3_common_tags, { + cis_section_id = "3.2" + }) + cis_v300_3_3_common_tags = merge(local.cis_v300_3_common_tags, { + cis_section_id = "3.3" + }) +} + +benchmark "cis_v300_3" { + title = "3 Security" + documentation = file("./cis_v300/docs/cis_v300_3.md") + children = [ + benchmark.cis_v300_3_1, + benchmark.cis_v300_3_2, + benchmark.cis_v300_3_3 + ] + + tags = merge(local.cis_v300_3_common_tags, { + type = "Benchmark" + service = "Azure/SecurityCenter" + }) +} + +benchmark "cis_v300_3_1" { + title = "3.1 Microsoft Defender for Cloud" + documentation = file("./cis_v300/docs/cis_v300_3_1.md") + children = [ + benchmark.cis_v300_3_1_1, + benchmark.cis_v300_3_1_3, + benchmark.cis_v300_3_1_4, + benchmark.cis_v300_3_1_5, + benchmark.cis_v300_3_1_6, + benchmark.cis_v300_3_1_7, + benchmark.cis_v300_3_1_8, + benchmark.cis_v300_3_1_9, + control.cis_v300_3_1_10, + control.cis_v300_3_1_11, + control.cis_v300_3_1_12, + control.cis_v300_3_1_13, + control.cis_v300_3_1_14, + control.cis_v300_3_1_15, + control.cis_v300_3_1_16 + ] + + tags = merge(local.cis_v300_3_1_common_tags, { + type = "Benchmark" + service = "Azure/SecurityCenter" + }) +} + +benchmark "cis_v300_3_1_1" { + title = "3.1.1 Microsoft Cloud Security Posture Management (CSPM)" + documentation = file("./cis_v300/docs/cis_v300_3_1_1.md") + children = [ + control.cis_v300_3_1_1_1, + control.cis_v300_3_1_1_2 + ] + + tags = merge(local.cis_v300_3_1_common_tags, { + type = "Benchmark" + service = "Azure/SecurityCenter" + }) +} + +control "cis_v300_3_1_1_1" { + title = "3.1.1.1 Ensure that Auto provisioning of 'Log Analytics agent for Azure VMs' is Set to 'On'" + description = "Enable automatic provisioning of the monitoring agent to collect security data." + query = query.securitycenter_automatic_provisioning_monitoring_agent_on + documentation = file("./cis_v300/docs/cis_v300_3_1_1_1.md") + + tags = merge(local.cis_v300_3_1_common_tags, { + cis_item_id = "3.1.1.1" + cis_type = "automated" + cis_level = "1" + service = "Azure/SecurityCenter" + }) +} + +control "cis_v300_3_1_1_2" { + title = "3.1.1.2 Ensure that Microsoft Defender for Cloud Apps integration with Microsoft Defender for Cloud is Selected" + description = "This integration setting enables Microsoft Defender for Cloud Apps (formerly 'Microsoft Cloud App Security' or 'MCAS' - see additional info) to communicate with Microsoft Defender for Cloud." + query = query.securitycenter_mcas_integration + documentation = file("./cis_v300/docs/cis_v300_3_1_1_2.md") + + tags = merge(local.cis_v300_3_1_common_tags, { + cis_item_id = "3.1.1.2" + cis_type = "automated" + cis_level = "2" + service = "Azure/SecurityCenter" + }) +} + +benchmark "cis_v300_3_1_3" { + title = "3.1.3 Defender Plan: Servers" + documentation = file("./cis_v300/docs/cis_v300_3_1_3.md") + children = [ + control.cis_v300_3_1_3_1, + control.cis_v300_3_1_3_2, + control.cis_v300_3_1_3_3, + control.cis_v300_3_1_3_4, + control.cis_v300_3_1_3_5 + ] + + tags = merge(local.cis_v300_3_1_common_tags, { + type = "Benchmark" + service = "Azure/SecurityCenter" + }) +} + +control "cis_v300_3_1_3_1" { + title = "3.1.3.1 Ensure That Microsoft Defender for Servers Is Set to 'On'" + description = "Turning on Microsoft Defender for Servers enables threat detection for Servers, providing threat intelligence, anomaly detection, and behavior analytics in the Microsoft Defender for Cloud." + query = query.securitycenter_azure_defender_on_for_server + documentation = file("./cis_v300/docs/cis_v300_3_1_3_1.md") + + tags = merge(local.cis_v300_3_1_common_tags, { + cis_item_id = "3.1.3.1" + cis_type = "automated" + cis_level = "2" + service = "Azure/SecurityCenter" + }) +} + +control "cis_v300_3_1_3_2" { + title = "3.1.3.2 Ensure that 'Vulnerability assessment for machines' component status is set to 'On'" + description = "Enable vulnerability assessment for machines on both Azure and hybrid (Arc enabled) machines." + query = query.manual_control + documentation = file("./cis_v300/docs/cis_v300_3_1_3_2.md") + + tags = merge(local.cis_v300_3_1_common_tags, { + cis_item_id = "3.1.3.2" + cis_type = "manual" + cis_level = "2" + service = "Azure/SecurityCenter" + }) +} + +control "cis_v300_3_1_3_3" { + title = "3.1.3.3 Ensure that 'Endpoint protection' component status is set to 'On'" + description = "The Endpoint protection component enables Microsoft Defender for Endpoint (formerly 'Advanced Threat Protection' or 'ATP' or 'WDATP' - see additional info) to communicate with Microsoft Defender for Cloud." + query = query.securitycenter_wdatp_integration + documentation = file("./cis_v300/docs/cis_v300_3_1_3_3.md") + + tags = merge(local.cis_v300_3_1_common_tags, { + cis_item_id = "3.1.3.3" + cis_type = "manual" + cis_level = "2" + service = "Azure/SecurityCenter" + }) +} + +control "cis_v300_3_1_3_4" { + title = "3.1.3.4 Ensure that 'Agentless scanning for machines' component status is set to 'On'" + description = "Using disk snapshots, the agentless scanner scans for installed software, vulnerabilities, and plain text secrets." + query = query.manual_control + documentation = file("./cis_v300/docs/cis_v300_3_1_3_4.md") + + tags = merge(local.cis_v300_3_1_common_tags, { + cis_item_id = "3.1.3.4" + cis_type = "manual" + cis_level = "2" + service = "Azure/SecurityCenter" + }) +} + +control "cis_v300_3_1_3_5" { + title = "3.1.3.5 Ensure that 'File Integrity Monitoring' component status is set to 'On'" + description = "File Integrity Monitoring (FIM) is a feature that monitors critical system files in Windows or Linux for potential signs of attack or compromise." + query = query.manual_control + documentation = file("./cis_v300/docs/cis_v300_3_1_3_5.md") + + tags = merge(local.cis_v300_3_1_common_tags, { + cis_item_id = "3.1.3.5" + cis_type = "manual" + cis_level = "2" + service = "Azure/SecurityCenter" + }) +} + +benchmark "cis_v300_3_1_4" { + title = "3.1.4 Defender Plan: Containers" + documentation = file("./cis_v300/docs/cis_v300_3_1_4.md") + children = [ + control.cis_v300_3_1_4_1, + control.cis_v300_3_1_4_2, + control.cis_v300_3_1_4_3 + ] + + tags = merge(local.cis_v300_3_1_common_tags, { + type = "Benchmark" + service = "Azure/SecurityCenter" + }) +} + +control "cis_v300_3_1_4_1" { + title = "3.1.4.1 Ensure That Microsoft Defender for Containers Is Set To 'On'" + description = "Turning on Microsoft Defender for Containers enables threat detection for Container Registries including Kubernetes, providing threat intelligence, anomaly detection, and behavior analytics in the Microsoft Defender for Cloud." + query = query.securitycenter_azure_defender_on_for_containerregistry + documentation = file("./cis_v300/docs/cis_v300_3_1_4_1.md") + + tags = merge(local.cis_v300_3_1_common_tags, { + cis_item_id = "3.1.4.1" + cis_type = "automated" + cis_level = "2" + service = "Azure/SecurityCenter" + }) +} + +control "cis_v300_3_1_4_2" { + title = "3.1.4.2 Ensure that 'Agentless discovery for Kubernetes' component status 'On'" + description = "Enable automatic discovery and configuration scanning of the Microsoft Kubernetes clusters." + query = query.securitycenter_azure_defender_on_for_containers + documentation = file("./cis_v300/docs/cis_v300_3_1_4_2.md") + + tags = merge(local.cis_v300_3_1_common_tags, { + cis_item_id = "3.1.4.2" + cis_type = "automated" + cis_level = "2" + service = "Azure/SecurityCenter" + }) +} + +control "cis_v300_3_1_4_3" { + title = "3.1.4.3 Ensure that 'Agentless container vulnerability assessment' component status is 'On'" + description = "Enable automatic vulnerability management for images stored in ACR or running in AKS clusters." + query = query.manual_control + documentation = file("./cis_v300/docs/cis_v300_3_1_4_3.md") + + tags = merge(local.cis_v300_3_1_common_tags, { + cis_item_id = "3.1.4.3" + cis_type = "automated" + cis_level = "2" + service = "Azure/SecurityCenter" + }) +} + +benchmark "cis_v300_3_1_5" { + title = "3.1.5 Defender Plan: Storage" + documentation = file("./cis_v300/docs/cis_v300_3_1_5.md") + children = [ + control.cis_v300_3_1_5_1 + ] + + tags = merge(local.cis_v300_3_1_common_tags, { + type = "Benchmark" + service = "Azure/SecurityCenter" + }) +} + +control "cis_v300_3_1_5_1" { + title = "3.1.5.1 Ensure That Microsoft Defender for Storage Is Set To 'On'" + description = "Turning on Microsoft Defender for Storage enables threat detection for Storage, providing threat intelligence, anomaly detection, and behavior analytics in the Microsoft Defender for Cloud." + query = query.securitycenter_azure_defender_on_for_storage + documentation = file("./cis_v300/docs/cis_v300_3_1_5_1.md") + + tags = merge(local.cis_v300_3_1_common_tags, { + cis_item_id = "3.1.5.1" + cis_type = "automated" + cis_level = "2" + service = "Azure/SecurityCenter" + }) +} + +benchmark "cis_v300_3_1_6" { + title = "3.1.6 Defender Plan: App Service" + documentation = file("./cis_v300/docs/cis_v300_3_1_6.md") + children = [ + control.cis_v300_3_1_6_1 + ] + + tags = merge(local.cis_v300_3_1_common_tags, { + type = "Benchmark" + service = "Azure/SecurityCenter" + }) +} + +control "cis_v300_3_1_6_1" { + title = "3.1.6.1 Ensure That Microsoft Defender for App Services Is Set To 'On'" + description = "Turning on Microsoft Defender for App Service enables threat detection for App Service, providing threat intelligence, anomaly detection, and behavior analytics in the Microsoft Defender for Cloud." + query = query.securitycenter_azure_defender_on_for_appservice + documentation = file("./cis_v300/docs/cis_v300_3_1_6_1.md") + + tags = merge(local.cis_v300_3_1_common_tags, { + cis_item_id = "3.1.6." + cis_type = "automated" + cis_level = "2" + service = "Azure/SecurityCenter" + }) +} + +benchmark "cis_v300_3_1_7" { + title = "3.1.7 Defender Plan: Databases" + documentation = file("./cis_v300/docs/cis_v300_3_1_7.md") + children = [ + control.cis_v300_3_1_7_1, + control.cis_v300_3_1_7_2, + control.cis_v300_3_1_7_3, + control.cis_v300_3_1_7_4 + ] + + tags = merge(local.cis_v300_3_1_common_tags, { + type = "Benchmark" + service = "Azure/SecurityCenter" + }) +} + +control "cis_v300_3_1_7_1" { + title = "3.1.7.1 Ensure That Microsoft Defender for Azure Cosmos DB Is Set To 'On'" + description = "Microsoft Defender for Azure Cosmos DB scans all incoming network requests for threats to your Azure Cosmos DB resources." + query = query.securitycenter_azure_defender_on_for_cosmosdb + documentation = file("./cis_v300/docs/cis_v300_3_1_7_1.md") + + tags = merge(local.cis_v300_3_1_common_tags, { + cis_item_id = "3.1.7.1" + cis_type = "automated" + cis_level = "2" + service = "Azure/SecurityCenter" + }) +} + +control "cis_v300_3_1_7_2" { + title = "3.1.7.2 Ensure That Microsoft Defender for Open-Source Relational Databases Is Set To 'On'" + description = "Turning on Microsoft Defender for Open-source relational databases enables threat detection for Open-source relational databases, providing threat intelligence, anomaly detection, and behavior analytics in the Microsoft Defender for Cloud." + query = query.securitycenter_azure_defender_on_for_opensource_relational_db + documentation = file("./cis_v300/docs/cis_v300_3_1_7_2.md") + + tags = merge(local.cis_v300_3_1_common_tags, { + cis_item_id = "3.1.7.2" + cis_type = "automated" + cis_level = "2" + service = "Azure/SecurityCenter" + }) +} + +control "cis_v300_3_1_7_3" { + title = "3.1.7.3 Ensure That Microsoft Defender for (Managed Instance) Azure SQL Databases Is Set To 'On'" + description = "Turning on Microsoft Defender for Azure SQL Databases enables threat detection for Azure SQL database servers, providing threat intelligence, anomaly detection, and behavior analytics in the Microsoft Defender for Cloud." + query = query.securitycenter_azure_defender_on_for_sqldb + documentation = file("./cis_v300/docs/cis_v300_3_1_7_3.md") + + tags = merge(local.cis_v300_3_1_common_tags, { + cis_item_id = "3.1.7.3" + cis_type = "automated" + cis_level = "2" + service = "Azure/SecurityCenter" + }) +} + +control "cis_v300_3_1_7_4" { + title = "3.1.7.4 Ensure That Microsoft Defender for SQL Servers on Machines Is Set To 'On'" + description = "Turning on Microsoft Defender for SQL servers on machines enables threat detection for SQL servers on machines, providing threat intelligence, anomaly detection, and behavior analytics in the Microsoft Defender for Cloud." + query = query.securitycenter_azure_defender_on_for_sqlservervm + documentation = file("./cis_v300/docs/cis_v300_3_1_7_4.md") + + tags = merge(local.cis_v300_3_1_common_tags, { + cis_item_id = "3.1.7.4" + cis_type = "automated" + cis_level = "2" + service = "Azure/SecurityCenter" + }) +} + +benchmark "cis_v300_3_1_8" { + title = "3.1.8 Defender Plan: Key Vault" + documentation = file("./cis_v300/docs/cis_v300_3_1_8.md") + children = [ + control.cis_v300_3_1_8_1 + ] + + tags = merge(local.cis_v300_3_1_common_tags, { + type = "Benchmark" + service = "Azure/SecurityCenter" + }) +} + +control "cis_v300_3_1_8_1" { + title = "3.1.8.1 Ensure That Microsoft Defender for Key Vault Is Set To 'On'" + description = "Turning on Microsoft Defender for Key Vault enables threat detection for Key Vault, providing threat intelligence, anomaly detection, and behavior analytics in the Microsoft Defender for Cloud." + query = query.securitycenter_azure_defender_on_for_keyvault + documentation = file("./cis_v300/docs/cis_v300_3_1_8_1.md") + + tags = merge(local.cis_v300_3_1_common_tags, { + cis_item_id = "3.1.8.1" + cis_type = "automated" + cis_level = "2" + service = "Azure/SecurityCenter" + }) +} + +benchmark "cis_v300_3_1_9" { + title = "3.1.9 Defender Plan: Resource Manager" + documentation = file("./cis_v300/docs/cis_v300_3_1_9.md") + children = [ + control.cis_v300_3_1_9_1 + ] + + tags = merge(local.cis_v300_3_1_common_tags, { + type = "Benchmark" + service = "Azure/SecurityCenter" + }) +} + +control "cis_v300_3_1_9_1" { + title = "3.1.9.1 Ensure That Microsoft Defender for Resource Manager Is Set To 'On'" + description = "Microsoft Defender for Resource Manager scans incoming administrative requests to change your infrastructure from both CLI and the Azure portal." + query = query.securitycenter_azure_defender_on_for_resource_manager + documentation = file("./cis_v300/docs/cis_v300_3_1_9_1.md") + + tags = merge(local.cis_v300_3_1_common_tags, { + cis_item_id = "3.1.9.1" + cis_type = "automated" + cis_level = "2" + service = "Azure/SecurityCenter" + }) +} + +control "cis_v300_3_1_10" { + title = "3.1.10 Ensure that Microsoft Defender Recommendation for 'Apply system updates' status is 'Completed'" + description = "Ensure that the latest OS patches for all virtual machines are applied." + query = query.manual_control + documentation = file("./cis_v300/docs/cis_v300_3_1_10.md") + + tags = merge(local.cis_v300_3_1_common_tags, { + cis_item_id = "3.1.10" + cis_type = "automated" + cis_level = "1" + service = "Azure/SecurityCenter" + }) +} + +control "cis_v300_3_1_11" { + title = "3.1.11 Ensure that Microsoft Cloud Security Benchmark policies are not set to 'Disabled'" + description = "The Microsoft Cloud Security Benchmark (or 'MCSB') is an Azure Policy Initiative containing many security policies to evaluate resource configuration against best practice recommendations. If a policy in the MCSB is set with effect type Disabled, it is not evaluated and may prevent administrators from being informed of valuable security recommendations." + query = query.manual_control + documentation = file("./cis_v300/docs/cis_v300_3_1_11.md") + + tags = merge(local.cis_v300_3_1_common_tags, { + cis_item_id = "3.1.11" + cis_type = "manual" + cis_level = "1" + service = "Azure/SecurityCenter" + }) +} + +control "cis_v300_3_1_12" { + title = "3.1.12 Ensure That 'All users with the following roles' is set to 'Owner'" + description = "Enable security alert emails to subscription owners." + query = query.securitycenter_security_alerts_to_owner_enabled + documentation = file("./cis_v300/docs/cis_v300_3_1_12.md") + + tags = merge(local.cis_v300_3_1_common_tags, { + cis_item_id = "3.1.12" + cis_type = "automated" + cis_level = "1" + service = "Azure/SecurityCenter" + }) +} + +control "cis_v300_3_1_13" { + title = "3.1.13 Ensure 'Additional email addresses' is Configured with a Security Contact Email" + description = "Microsoft Defender for Cloud emails the subscription owners whenever a high-severity alert is triggered for their subscription. You should provide a security contact email address as an additional email address." + query = query.securitycenter_additional_email_configured + documentation = file("./cis_v300/docs/cis_v300_3_1_13.md") + + tags = merge(local.cis_v300_3_1_common_tags, { + cis_item_id = "3.1.13" + cis_type = "automated" + cis_level = "1" + service = "Azure/SecurityCenter" + }) +} + +control "cis_v300_3_1_14" { + title = "3.1.14 Ensure That 'Notify about alerts with the following severity' is Set to 'High'" + description = "Enables emailing security alerts to the subscription owner or other designated security contact." + query = query.securitycenter_notify_alerts_configured + documentation = file("./cis_v300/docs/cis_v300_3_1_14.md") + + tags = merge(local.cis_v300_3_1_common_tags, { + cis_item_id = "3.1.14" + cis_type = "automated" + cis_level = "1" + service = "Azure/SecurityCenter" + }) +} + +control "cis_v300_3_1_15" { + title = "3.1.15 Ensure that Microsoft Defender External Attack Surface Monitoring (EASM) is enabled" + description = "An organization's attack surface is the collection of assets with a public network identifier or URI that an external threat actor can see or access from outside your cloud. It is the set of points on the boundary of a system, a system element, system component, or an environment where an attacker can try to enter, cause an effect on, or extract data from, that system, system element, system component, or environment. The larger the attack surface, the harder it is to protect." + query = query.manual_control + documentation = file("./cis_v300/docs/cis_v300_3_1_15.md") + + tags = merge(local.cis_v300_3_1_common_tags, { + cis_item_id = "3.1.15" + cis_type = "manual" + cis_level = "2" + service = "Azure/SecurityCenter" + }) +} + +control "cis_v300_3_1_16" { + title = "3.1.16 [LEGACY] Ensure That Microsoft Defender for DNS Is Set To 'On'" + description = "Microsoft Defender for DNS scans all network traffic exiting from within a subscription." + query = query.securitycenter_azure_defender_on_for_dns + documentation = file("./cis_v300/docs/cis_v300_3_1_16.md") + + tags = merge(local.cis_v300_3_1_common_tags, { + cis_item_id = "3.1.16" + cis_type = "automated" + cis_level = "2" + service = "Azure/SecurityCenter" + }) +} + +benchmark "cis_v300_3_2" { + title = "3.2 Microsoft Defender for IoT" + documentation = file("./cis_v300/docs/cis_v300_3_2.md") + children = [ + control.cis_v300_3_2_1 + ] + + tags = merge(local.cis_v300_3_2_common_tags, { + type = "Benchmark" + service = "Azure/SecurityCenter" + }) +} + +control "cis_v300_3_2_1" { + title = "3.2.1 Ensure That Microsoft Defender for IoT Hub Is Set To 'On'" + description = "Microsoft Defender for IoT acts as a central security hub for IoT devices within your organization." + query = query.manual_control + documentation = file("./cis_v300/docs/cis_v300_3_2_1.md") + + tags = merge(local.cis_v300_3_2_common_tags, { + cis_item_id = "3.2.1" + cis_type = "manual" + cis_level = "2" + service = "Azure/SecurityCenter" + }) +} + +benchmark "cis_v300_3_3" { + title = "3.3 Key Vault" + documentation = file("./cis_v300/docs/cis_v300_3_3.md") + children = [ + control.cis_v300_3_3_1, + control.cis_v300_3_3_2, + control.cis_v300_3_3_3, + control.cis_v300_3_3_4, + control.cis_v300_3_3_5, + control.cis_v300_3_3_6, + control.cis_v300_3_3_7, + control.cis_v300_3_3_8 + ] + + tags = merge(local.cis_v300_3_3_common_tags, { + type = "Benchmark" + }) +} + +control "cis_v300_3_3_1" { + title = "3.3.1 Ensure that the Expiration Date is set for all Keys in RBAC Key Vaults" + description = "Ensure that all Keys in Role Based Access Control (RBAC) Azure Key Vaults have an expiration date set." + query = query.keyvault_with_rbac_key_expiration_set + documentation = file("./cis_v300/docs/cis_v300_3_3_1.md") + + tags = merge(local.cis_v300_3_3_common_tags, { + cis_item_id = "3.3.1" + cis_level = "1" + cis_type = "automated" + service = "Azure/KeyVault" + }) +} + +control "cis_v300_3_3_2" { + title = "3.3.2 Ensure that the Expiration Date is set for all Keys in Non-RBAC Key Vaults" + description = "Ensure that all Keys in Non Role Based Access Control (RBAC) Azure Key Vaults have an expiration date set." + query = query.keyvault_with_non_rbac_key_expiration_set + documentation = file("./cis_v300/docs/cis_v300_3_3_2.md") + + tags = merge(local.cis_v300_3_3_common_tags, { + cis_item_id = "3.3.2" + cis_level = "1" + cis_type = "automated" + service = "Azure/KeyVault" + }) +} + +control "cis_v300_3_3_3" { + title = "3.3.3 Ensure that the Expiration Date is set for all Secrets in RBAC Key Vaults" + description = "Ensure that all Secrets in Role Based Access Control (RBAC) Azure Key Vaults have an expiration date set." + query = query.keyvault_with_rbac_secret_expiration_set + documentation = file("./cis_v300/docs/cis_v300_3_3_3.md") + + tags = merge(local.cis_v300_3_3_common_tags, { + cis_item_id = "3.3.3" + cis_level = "1" + cis_type = "automated" + service = "Azure/KeyVault" + }) +} + +control "cis_v300_3_3_4" { + title = "3.3.4 Ensure that the Expiration Date is set for all Secrets in Non-RBAC Key Vaults" + description = "Ensure that all Secrets in Non Role Based Access Control (RBAC) Azure Key Vaults have an expiration date set." + query = query.keyvault_with_non_rbac_secret_expiration_set + documentation = file("./cis_v300/docs/cis_v300_3_3_4.md") + + tags = merge(local.cis_v300_3_3_common_tags, { + cis_item_id = "3.3.4" + cis_level = "1" + cis_type = "automated" + service = "Azure/KeyVault" + }) +} + +control "cis_v300_3_3_5" { + title = "3.3.5 Ensure the Key Vault is Recoverable" + description = "The key vault contains object keys, secrets and certificates. Accidental unavailability of a key vault can cause immediate data loss or loss of security functions (authentication, validation, verification, non-repudiation, etc.) supported by the key vault objects. It is recommended the key vault be made recoverable by enabling the \"Do Not Purge\" and \"Soft Delete\" functions." + query = query.keyvault_vault_recoverable + documentation = file("./cis_v300/docs/cis_v300_3_3_5.md") + + tags = merge(local.cis_v300_3_3_common_tags, { + cis_item_id = "3.3.5" + cis_level = "1" + cis_type = "automated" + service = "Azure/KeyVault" + }) +} + +control "cis_v300_3_3_6" { + title = "3.3.6 Enable Role Based Access Control for Azure Key Vault" + description = "Role assignments disappear when a Key Vault has been deleted (soft-delete) and recovered. Afterwards it will be required to recreate all role assignments. This is a limitation of the soft-delete feature across all Azure services." + query = query.keyvault_rbac_enabled + documentation = file("./cis_v300/docs/cis_v300_3_3_6.md") + + tags = merge(local.cis_v300_3_3_common_tags, { + cis_item_id = "3.3.6" + cis_level = "2" + cis_type = "automated" + service = "Azure/KeyVault" + }) +} + +control "cis_v300_3_3_7" { + title = "3.3.7 Ensure that Private Endpoints are Used for Azure Key Vault" + description = "Private endpoints will secure network traffic from Azure Key Vault to the resources requesting secrets and keys." + query = query.keyvault_vault_private_link_used + documentation = file("./cis_v300/docs/cis_v300_3_3_7.md") + + tags = merge(local.cis_v300_3_3_common_tags, { + cis_item_id = "3.3.7" + cis_level = "2" + cis_type = "manual" + service = "Azure/KeyVault" + }) +} + +control "cis_v300_3_3_8" { + title = "3.3.8 Ensure Automatic Key Rotation is Enabled Within Azure Key Vault for the Supported Services" + description = "Automatic Key Rotation is available in Public Preview. The currently supported applications are Key Vault, Managed Disks, and Storage accounts accessing keys within Key Vault. The number of supported applications will incrementally increased." + query = query.manual_control + documentation = file("./cis_v300/docs/cis_v300_3_3_8.md") + + tags = merge(local.cis_v300_3_3_common_tags, { + cis_item_id = "3.3.8" + cis_level = "2" + cis_type = "manual" + service = "Azure/KeyVault" + }) +} diff --git a/cis_v300/section_4.pp b/cis_v300/section_4.pp new file mode 100644 index 00000000..5674d55f --- /dev/null +++ b/cis_v300/section_4.pp @@ -0,0 +1,272 @@ +locals { + cis_v300_4_common_tags = merge(local.cis_v300_common_tags, { + cis_section_id = "4" + }) +} + +benchmark "cis_v300_4" { + title = "4 Storage Accounts" + documentation = file("./cis_v300/docs/cis_v300_4.md") + children = [ + control.cis_v300_4_1, + control.cis_v300_4_2, + control.cis_v300_4_3, + control.cis_v300_4_4, + control.cis_v300_4_5, + control.cis_v300_4_6, + control.cis_v300_4_7, + control.cis_v300_4_8, + control.cis_v300_4_9, + control.cis_v300_4_10, + control.cis_v300_4_11, + control.cis_v300_4_12, + control.cis_v300_4_13, + control.cis_v300_4_14, + control.cis_v300_4_15, + control.cis_v300_4_16, + control.cis_v300_4_17 + ] + + tags = merge(local.cis_v300_4_common_tags, { + type = "Benchmark" + service = "Azure/Storage" + }) +} + +control "cis_v300_4_1" { + title = "4.1 Ensure that 'Secure transfer required' is set to 'Enabled'" + description = "Enable data encryption in transit." + query = query.storage_account_secure_transfer_required_enabled + documentation = file("./cis_v300/docs/cis_v300_4_1.md") + + tags = merge(local.cis_v300_4_common_tags, { + cis_item_id = "4.1" + cis_level = "1" + cis_type = "automated" + service = "Azure/Storage" + }) +} + +control "cis_v300_4_2" { + title = "4.2 Ensure that 'Enable Infrastructure Encryption' for Each Storage Account in Azure Storage is Set to 'enabled'" + description = "Enabling encryption at the hardware level on top of the default software encryption for Storage Accounts accessing Azure storage solutions." + query = query.storage_account_infrastructure_encryption_enabled + documentation = file("./cis_v300/docs/cis_v300_4_2.md") + + tags = merge(local.cis_v300_4_common_tags, { + cis_item_id = "4.2" + cis_level = "2" + cis_type = "automated" + service = "Azure/Storage" + }) +} + +control "cis_v300_4_3" { + title = "4.3 Ensure that 'Enable key rotation reminders' is enabled for each Storage Account" + description = "Access Keys authenticate application access requests to data contained in Storage Accounts. A periodic rotation of these keys is recommended to ensure that potentially compromised keys cannot result in a long-term exploitable credential. The 'Rotation Reminder' is an automatic reminder feature for a manual procedure." + query = query.manual_control + documentation = file("./cis_v300/docs/cis_v300_4_3.md") + + tags = merge(local.cis_v300_4_common_tags, { + cis_item_id = "4.3" + cis_level = "1" + cis_type = "manual" + service = "Azure/Storage" + }) +} + +control "cis_v300_4_4" { + title = "4.4 Ensure that Storage Account Access Keys are Periodically Regenerated" + description = "For increased security, regenerate storage account access keys periodically." + query = query.manual_control + documentation = file("./cis_v300/docs/cis_v300_4_4.md") + + tags = merge(local.cis_v300_4_common_tags, { + cis_item_id = "4.4" + cis_level = "1" + cis_type = "manual" + service = "Azure/Storage" + }) +} + +control "cis_v300_4_5" { + title = "4.5 Ensure that Shared Access Signature Tokens Expire Within an Hour" + description = "Expire shared access signature tokens within an hour." + query = query.manual_control + documentation = file("./cis_v300/docs/cis_v300_4_5.md") + + tags = merge(local.cis_v300_4_common_tags, { + cis_item_id = "4.5" + cis_level = "1" + cis_type = "manual" + service = "Azure/Storage" + }) +} + +control "cis_v300_4_6" { + title = "4.6 Ensure that 'Public Network Access' is `Disabled' for storage accounts" + description = "Disallowing public network access for a storage account overrides the public access settings for individual containers in that storage account for Azure Resource Manager Deployment Model storage accounts. Azure Storage accounts that use the classic deployment model will be retired on August 31, 2024." + query = query.storage_account_block_public_access + documentation = file("./cis_v300/docs/cis_v300_4_6.md") + + tags = merge(local.cis_v300_4_common_tags, { + cis_item_id = "4.6" + cis_level = "1" + cis_type = "automated" + service = "Azure/Storage" + }) +} + +control "cis_v300_4_7" { + title = "4.7 Ensure Default Network Access Rule for Storage Accounts is Set to Deny" + description = "Restricting default network access helps to provide a new layer of security, since storage accounts accept connections from clients on any network. To limit access to selected networks, the default action must be changed." + query = query.storage_account_default_network_access_rule_denied + documentation = file("./cis_v300/docs/cis_v300_4_7.md") + + tags = merge(local.cis_v300_4_common_tags, { + cis_item_id = "4.7" + cis_level = "1" + cis_type = "automated" + service = "Azure/Storage" + }) +} + +control "cis_v300_4_8" { + title = "4.8 Ensure 'Allow Azure services on the trusted services list to access this storage account' is Enabled for Storage Account Access" + description = "Some Azure services that interact with storage accounts operate from networks that can't be granted access through network rules. To help this type of service work as intended, allow the set of trusted Azure services to bypass the network rules. These services will then use strong authentication to access the storage account." + query = query.storage_account_trusted_microsoft_services_enabled + documentation = file("./cis_v300/docs/cis_v300_4_8.md") + + tags = merge(local.cis_v300_4_common_tags, { + cis_item_id = "4.8" + cis_level = "2" + cis_type = "automated" + service = "Azure/Storage" + }) +} + +control "cis_v300_4_9" { + title = "4.9 Ensure Private Endpoints are used to access Storage Accounts" + description = "Use private endpoints for your Azure Storage accounts to allow clients and services to securely access data located over a network via an encrypted Private Link. To do this, the private endpoint uses an IP address from the VNet for each service. Network traffic between disparate services securely traverses encrypted over the VNet." + query = query.storage_account_uses_private_link + documentation = file("./cis_v300/docs/cis_v300_4_9.md") + + tags = merge(local.cis_v300_4_common_tags, { + cis_item_id = "4.9" + cis_level = "1" + cis_type = "automated" + service = "Azure/Storage" + }) +} + +control "cis_v300_4_10" { + title = "4.10 Ensure Soft Delete is Enabled for Azure Containers and Blob Storage" + description = "The Azure Storage blobs contain data like ePHI or Financial, which can be secret or personal. Data that is erroneously modified or deleted by an application or other storage account user will cause data loss or unavailability." + query = query.storage_account_soft_delete_enabled + documentation = file("./cis_v300/docs/cis_v300_4_10.md") + + tags = merge(local.cis_v300_4_common_tags, { + cis_item_id = "4.10" + cis_level = "1" + cis_type = "automated" + service = "Azure/Storage" + }) +} + +control "cis_v300_4_11" { + title = "4.11 Ensure Storage for Critical Data are Encrypted with Customer Managed Keys" + description = "Enable sensitive data encryption at rest using Customer Managed Keys rather than Microsoft Managed keys." + query = query.storage_account_encryption_at_rest_using_cmk + documentation = file("./cis_v300/docs/cis_v300_4_11.md") + + tags = merge(local.cis_v300_4_common_tags, { + cis_item_id = "4.11" + cis_level = "2" + cis_type = "manual" + service = "Azure/Storage" + }) +} + +control "cis_v300_4_12" { + title = "4.12 Ensure Storage Logging is Enabled for Queue Service for 'Read', 'Write', and 'Delete' requests" + description = "The Storage Queue service stores messages that may be read by any client who has access to the storage account. A queue can contain an unlimited number of messages, each of which can be up to 64KB in size using version 2011-08-18 or newer. Storage Logging happens server-side and allows details for both successful and failed requests to be recorded in the storage account." + query = query.storage_account_queue_services_logging_enabled + documentation = file("./cis_v300/docs/cis_v300_4_12.md") + + tags = merge(local.cis_v300_4_common_tags, { + cis_item_id = "4.12" + cis_level = "2" + cis_type = "automated" + service = "Azure/Storage" + }) +} + +control "cis_v300_4_13" { + title = "4.13 Ensure Storage logging is Enabled for Blob Service for 'Read', 'Write', and 'Delete' requests" + description = "The Storage Blob service provides scalable, cost-efficient object storage in the cloud. Storage Logging happens server-side and allows details for both successful and failed requests to be recorded in the storage account. These logs allow users to see the details of read, write, and delete operations against the blobs. Storage Logging log entries contain the following information about individual requests: timing information such as start time, end-to-end latency, and server latency; authentication details; concurrency information; and the sizes of the request and response messages." + query = query.storage_account_blob_service_logging_enabled + documentation = file("./cis_v300/docs/cis_v300_4_13.md") + + tags = merge(local.cis_v300_4_common_tags, { + cis_item_id = "4.13" + cis_level = "2" + cis_type = "automated" + service = "Azure/Storage" + }) +} + +control "cis_v300_4_14" { + title = "4.14 Ensure Storage Logging is Enabled for Table Service for 'Read', 'Write', and 'Delete' Requests" + description = "Azure Table storage is a service that stores structured NoSQL data in the cloud, providing a key/attribute store with a schema-less design. Storage Logging happens server-side and allows details for both successful and failed requests to be recorded in the storage account. These logs allow users to see the details of read, write, and delete operations against the tables. Storage Logging log entries contain the following information about individual requests: timing information such as start time, end-to-end latency, and server latency; authentication details; concurrency information; and the sizes of the request and response messages." + query = query.storage_account_table_service_logging_enabled + documentation = file("./cis_v300/docs/cis_v300_4_14.md") + + tags = merge(local.cis_v300_4_common_tags, { + cis_item_id = "4.14" + cis_level = "2" + cis_type = "automated" + service = "Azure/Storage" + }) +} + +control "cis_v300_4_15" { + title = "4.15 Ensure the 'Minimum TLS version' for storage accounts is set to 'Version 1.2'" + description = "In some cases, Azure Storage sets the minimum TLS version to be version 1.0 by default. TLS 1.0 is a legacy version and has known vulnerabilities. This minimum TLS version can be configured to be later protocols such as TLS 1.2." + query = query.storage_account_min_tls_1_2 + documentation = file("./cis_v300/docs/cis_v300_4_15.md") + + tags = merge(local.cis_v300_4_common_tags, { + cis_item_id = "4.15" + cis_level = "1" + cis_type = "automated" + service = "Azure/Storage" + }) +} + +control "cis_v300_4_16" { + title = "4.16 Ensure 'Cross Tenant Replication' is not enabled" + description = "Cross Tenant Replication in Azure allows data to be replicated across multiple Azure tenants. While this feature can be beneficial for data sharing and availability, it also poses a significant security risk if not properly managed. Unauthorized data access, data leakage, and compliance violations are potential risks. Disabling Cross Tenant Replication ensures that data is not inadvertently replicated across different tenant boundaries without explicit authorization." + query = query.manual_control + documentation = file("./cis_v300/docs/cis_v300_4_16.md") + + tags = merge(local.cis_v300_4_common_tags, { + cis_item_id = "4.16" + cis_level = "1" + cis_type = "automated" + service = "Azure/Storage" + }) +} + +control "cis_v300_4_17" { + title = "4.17 Ensure that `Allow Blob Anonymous Access` is set to `Disabled`" + description = "The Azure Storage setting 'Allow Blob Anonymous Access' (aka 'allowBlobPublicAccess') controls whether anonymous access is allowed for blob data in a storage account. When this property is set to True, it enables public read access to blob data, which can be convenient for sharing data but may carry security risks. When set to False, it disallows public access to blob data, providing a more secure storage environment." + query = query.storage_account_blob_containers_public_access_private + documentation = file("./cis_v300/docs/cis_v300_4_17.md") + + tags = merge(local.cis_v300_4_common_tags, { + cis_item_id = "4.17" + cis_level = "1" + cis_type = "automated" + service = "Azure/Storage" + }) +} diff --git a/cis_v300/section_5.pp b/cis_v300/section_5.pp new file mode 100644 index 00000000..01dd5382 --- /dev/null +++ b/cis_v300/section_5.pp @@ -0,0 +1,412 @@ +locals { + cis_v300_5_common_tags = merge(local.cis_v300_common_tags, { + cis_section_id = "5" + }) +} + +locals { + cis_v300_5_1_common_tags = merge(local.cis_v300_5_common_tags, { + cis_section_id = "5.1" + }) + cis_v300_5_2_common_tags = merge(local.cis_v300_5_common_tags, { + cis_section_id = "5.2" + }) + cis_v300_5_3_common_tags = merge(local.cis_v300_5_common_tags, { + cis_section_id = "5.3" + }) + cis_v300_5_4_common_tags = merge(local.cis_v300_5_common_tags, { + cis_section_id = "5.4" + }) +} + +benchmark "cis_v300_5" { + title = "5 Database Services" + documentation = file("./cis_v300/docs/cis_v300_5.md") + children = [ + benchmark.cis_v300_5_1, + benchmark.cis_v300_5_2, + benchmark.cis_v300_5_3, + benchmark.cis_v300_5_4 + ] + + tags = merge(local.cis_v300_5_common_tags, { + type = "Benchmark" + }) +} + +benchmark "cis_v300_5_1" { + title = "5.1 SQL Azure SQL Database" + documentation = file("./cis_v300/docs/cis_v300_5_1.md") + children = [ + control.cis_v300_5_1_1, + control.cis_v300_5_1_2, + control.cis_v300_5_1_3, + control.cis_v300_5_1_4, + control.cis_v300_5_1_5, + control.cis_v300_5_1_6, + control.cis_v300_5_1_7 + ] + + tags = merge(local.cis_v300_5_1_common_tags, { + type = "Benchmark" + service = "Azure/SQL" + }) +} + +control "cis_v300_5_1_1" { + title = "5.1.1 Ensure that 'Auditing' is set to 'On'" + description = "Enable auditing on SQL Servers." + query = query.sql_server_auditing_on + documentation = file("./cis_v300/docs/cis_v300_5_1_1.md") + + tags = merge(local.cis_v300_5_1_common_tags, { + cis_item_id = "5.1.1" + cis_level = "1" + cis_type = "automated" + service = "Azure/SQL" + }) +} + +control "cis_v300_5_1_2" { + title = "5.1.2 Ensure no Azure SQL Databases allow ingress from 0.0.0.0/0 (ANY IP)" + description = "Ensure that no SQL Databases allow ingress from 0.0.0.0/0 (ANY IP)." + query = query.sql_database_allow_internet_access + documentation = file("./cis_v300/docs/cis_v300_5_1_2.md") + + tags = merge(local.cis_v300_5_1_common_tags, { + cis_item_id = "5.1.2" + cis_level = "1" + cis_type = "automated" + service = "Azure/SQL" + }) +} + +control "cis_v300_5_1_3" { + title = "5.1.3 Ensure SQL server's Transparent Data Encryption (TDE) protector is encrypted with Customer-managed key" + description = "Transparent Data Encryption (TDE) with Customer-managed key support provides increased transparency and control over the TDE Protector, increased security with an HSM-backed external service, and promotion of separation of duties." + query = query.sql_server_tde_protector_cmk_encrypted + documentation = file("./cis_v300/docs/cis_v300_5_1_3.md") + + tags = merge(local.cis_v300_5_1_common_tags, { + cis_item_id = "5.1.3" + cis_level = "2" + cis_type = "automated" + service = "Azure/SQL" + }) +} + +control "cis_v300_5_1_4" { + title = "5.1.4 Ensure that Microsoft Entra authentication is Configured for SQL Servers" + description = "Use Azure Active Directory Authentication for authentication with SQL Database to manage credentials in a single place." + query = query.sql_db_active_directory_admin_configured + documentation = file("./cis_v300/docs/cis_v300_5_1_4.md") + + tags = merge(local.cis_v300_5_1_common_tags, { + cis_item_id = "5.1.4" + cis_level = "1" + cis_type = "automated" + service = "Azure/SQL" + }) +} + +control "cis_v300_5_1_5" { + title = "5.1.5 Ensure that 'Data encryption' is set to 'On' on a SQL Database" + description = "Enable Transparent Data Encryption on every SQL server." + query = query.sql_database_transparent_data_encryption_enabled + documentation = file("./cis_v300/docs/cis_v300_5_1_5.md") + + tags = merge(local.cis_v300_5_1_common_tags, { + cis_item_id = "5.1.5" + cis_level = "1" + cis_type = "automated" + service = "Azure/SQL" + }) +} + +control "cis_v300_5_1_6" { + title = "5.1.6 Ensure that 'Auditing' Retention is 'greater than 90 days'" + description = "SQL Server Audit Retention should be configured to be greater than 90 days." + query = query.sql_server_auditing_retention_period_90 + documentation = file("./cis_v300/docs/cis_v300_5_1_6.md") + + tags = merge(local.cis_v300_5_1_common_tags, { + cis_item_id = "5.1.6" + cis_level = "1" + cis_type = "automated" + service = "Azure/SQL" + }) +} + +control "cis_v300_5_1_7" { + title = "5.1.7 Ensure Public Network Access is Disabled" + description = "Disabling public network access restricts the service from accessing public networks." + query = query.sql_db_public_network_access_disabled + documentation = file("./cis_v300/docs/cis_v300_5_1_7.md") + + tags = merge(local.cis_v300_5_1_common_tags, { + cis_item_id = "5.1.7" + cis_level = "1" + cis_type = "manual" + service = "Azure/SQL" + }) +} + +benchmark "cis_v300_5_2" { + title = "5.2 Azure Database for PostgreSQL" + documentation = file("./cis_v300/docs/cis_v300_5_2.md") + children = [ + control.cis_v300_5_2_1, + control.cis_v300_5_2_2, + control.cis_v300_5_2_3, + control.cis_v300_5_2_4, + control.cis_v300_5_2_5, + control.cis_v300_5_2_6, + control.cis_v300_5_2_7, + control.cis_v300_5_2_8 + ] + + tags = merge(local.cis_v300_5_2_common_tags, { + type = "Benchmark" + }) +} + +control "cis_v300_5_2_1" { + title = "5.2.1 Ensure server parameter 'require_secure_transport' is set to 'ON' for PostgreSQL flexible server" + description = "Enable 'require_secure_transport' on 'PostgreSQL flexible servers'." + query = query.postgres_sql_flexible_server_ssl_enabled + documentation = file("./cis_v300/docs/cis_v300_5_2_1.md") + + tags = merge(local.cis_v300_5_2_common_tags, { + cis_item_id = "5.2.1" + cis_level = "1" + cis_type = "automated" + service = "Azure/PostgreSQL" + }) +} + +control "cis_v300_5_2_2" { + title = "5.2.2 Ensure server parameter 'log_checkpoints' is set to 'ON' for PostgreSQL flexible Server" + description = "Enable 'log_checkpoints' on 'PostgreSQL Servers'." + query = query.postgres_flexible_server_log_checkpoints_on + documentation = file("./cis_v300/docs/cis_v300_5_2_2.md") + + tags = merge(local.cis_v300_5_2_common_tags, { + cis_item_id = "5.2.2" + cis_level = "1" + cis_type = "automated" + service = "Azure/PostgreSQL" + }) +} + +control "cis_v300_5_2_3" { + title = "5.2.3 Ensure server parameter 'connection_throttle.enable' is set to 'ON' for PostgreSQL flexible Server" + description = "Enable connection_throttling on PostgreSQL flexible Servers." + query = query.postgres_flexible_server_connection_throttling_on + documentation = file("./cis_v300/docs/cis_v300_5_2_3.md") + + tags = merge(local.cis_v300_5_2_common_tags, { + cis_item_id = "5.2.3" + cis_level = "1" + cis_type = "automated" + service = "Azure/PostgreSQL" + }) +} + +control "cis_v300_5_2_4" { + title = "5.2.4 Ensure Server Parameter 'logfiles.retention_days' is greater than 3 days for PostgreSQL flexible Server" + description = "Ensure logfiles.retention_days on PostgreSQL flexible Servers is set to an appropriate value." + query = query.postgres_flexible_server_log_retention_days_3 + documentation = file("./cis_v300/docs/cis_v300_5_2_4.md") + + tags = merge(local.cis_v300_5_2_common_tags, { + cis_item_id = "5.2.4" + cis_level = "1" + cis_type = "automated" + service = "Azure/PostgreSQL" + }) +} + +control "cis_v300_5_2_5" { + title = "5.2.5 Ensure 'Allow public access from any Azure service within Azure to this server' for PostgreSQL flexible server is disabled" + description = "Disable access from Azure services to PostgreSQL flexible server." + query = query.postgres_db_server_allow_access_to_azure_services_disabled + documentation = file("./cis_v300/docs/cis_v300_5_2_5.md") + + tags = merge(local.cis_v300_5_2_common_tags, { + cis_item_id = "5.2.5" + cis_level = "1" + cis_type = "automated" + service = "Azure/PostgreSQL" + }) +} + +control "cis_v300_5_2_6" { + title = "5.2.6 [LEGACY]Ensure server parameter 'log_connections' is set to 'ON' for PostgreSQL single Server" + description = "Enable 'log_connections' on 'PostgreSQL single Servers'." + query = query.postgres_db_server_log_connections_on + documentation = file("./cis_v300/docs/cis_v300_5_2_6.md") + + tags = merge(local.cis_v300_5_2_common_tags, { + cis_item_id = "5.2.6" + cis_level = "1" + cis_type = "automated" + service = "Azure/PostgreSQL" + }) +} + +control "cis_v300_5_2_7" { + title = "5.2.7 [LEGACY]Ensure server parameter 'log_disconnections' is set to 'ON' for PostgreSQL single Server" + description = "Enable 'log_disconnections' on 'PostgreSQL Servers'." + query = query.postgres_db_server_log_disconnections_on + documentation = file("./cis_v300/docs/cis_v300_5_2_7.md") + + tags = merge(local.cis_v300_5_2_common_tags, { + cis_item_id = "5.2.7" + cis_level = "1" + cis_type = "automated" + service = "Azure/PostgreSQL" + }) +} + +control "cis_v300_5_2_8" { + title = "5.2.8 [LEGACY]Ensure 'Infrastructure double encryption' for PostgreSQL Database Server is 'Enabled'" + description = "Azure Database for PostgreSQL servers should be created with 'infrastructure double encryption' enabled." + query = query.postgresql_server_infrastructure_encryption_enabled + documentation = file("./cis_v300/docs/cis_v300_5_2_8.md") + + tags = merge(local.cis_v300_5_2_common_tags, { + cis_item_id = "5.2.8" + cis_level = "1" + cis_type = "automated" + service = "Azure/PostgreSQL" + }) +} + +benchmark "cis_v300_5_3" { + title = "5.3 Azure Database for MySQL" + documentation = file("./cis_v300/docs/cis_v300_5_3.md") + children = [ + control.cis_v300_5_3_1, + control.cis_v300_5_3_2, + control.cis_v300_5_3_3, + control.cis_v300_5_3_4 + ] + + tags = merge(local.cis_v300_5_3_common_tags, { + type = "Benchmark" + service = "Azure/SQL" + }) +} + +control "cis_v300_5_3_1" { + title = "5.3.1 Ensure server parameter 'require_secure_transport' is set to 'ON' for MySQL flexible server" + description = "Enable require_secure_transport on MySQL flexible servers." + query = query.mysql_flexible_server_ssl_enabled + documentation = file("./cis_v300/docs/cis_v300_5_3_1.md") + + tags = merge(local.cis_v300_5_3_common_tags, { + cis_item_id = "5.3.1" + cis_level = "1" + cis_type = "automated" + service = "Azure/MySQL" + }) +} + +control "cis_v300_5_3_2" { + title = "5.3.2 Ensure server parameter 'tls_version' is set to 'TLSv1.2' (or higher) for MySQL flexible server" + description = "Ensure tls_version on MySQL flexible servers is set to use TLS version 1.2 or higher." + query = query.mysql_flexible_server_min_tls_1_2 + documentation = file("./cis_v300/docs/cis_v300_5_3_2.md") + + tags = merge(local.cis_v300_5_3_common_tags, { + cis_item_id = "5.3.2" + cis_level = "1" + cis_type = "automated" + service = "Azure/MySQL" + }) +} + +control "cis_v300_5_3_3" { + title = "5.3.3 Ensure server parameter 'audit_log_enabled' is set to 'ON' for MySQL flexible Server" + description = "Enable audit_log_enabled on MySQL flexible Servers." + query = query.mysql_flexible_server_audit_logging_enabled + documentation = file("./cis_v300/docs/cis_v300_5_3_3.md") + + tags = merge(local.cis_v300_5_3_common_tags, { + cis_item_id = "5.3.3" + cis_level = "2" + cis_type = "automated" + service = "Azure/MySQL" + }) +} + +control "cis_v300_5_3_4" { + title = "5.3.4 Ensure server parameter 'audit_log_events' has 'CONNECTION' set for MySQL flexible Server" + description = "Set audit_log_enabled to include CONNECTION on MySQL flexible servers." + query = query.mysql_flexible_server_audit_logging_events_connection_set + documentation = file("./cis_v300/docs/cis_v300_5_3_4.md") + + tags = merge(local.cis_v300_5_3_common_tags, { + cis_item_id = "5.3.4" + cis_level = "2" + cis_type = "manual" + service = "Azure/MySQL" + }) +} + +benchmark "cis_v300_5_4" { + title = "5.4 Azure Cosmos DB" + documentation = file("./cis_v300/docs/cis_v300_5_4.md") + children = [ + control.cis_v300_5_4_1, + control.cis_v300_5_4_2, + control.cis_v300_5_4_3 + ] + + tags = merge(local.cis_v300_5_common_tags, { + type = "Benchmark" + service = "Azure/SQL" + }) +} + +control "cis_v300_5_4_1" { + title = "5.4.1 Ensure That 'Firewalls & Networks' Is Limited to Use Selected Networks Instead of All Networks" + description = "Limiting your Cosmos DB to only communicate on whitelisted networks lowers its attack footprint." + query = query.cosmosdb_account_virtual_network_filter_enabled + documentation = file("./cis_v300/docs/cis_v300_5_4_1.md") + + tags = merge(local.cis_v300_5_4_common_tags, { + cis_item_id = "5.4.1" + cis_level = "2" + cis_type = "automated" + service = "Azure/SQL" + }) +} + +control "cis_v300_5_4_2" { + title = "5.4.2 Ensure That Private Endpoints Are Used Where Possible" + description = "Private endpoints limit network traffic to approved sources." + query = query.cosmosdb_account_uses_private_link + documentation = file("./cis_v300/docs/cis_v300_5_4_2.md") + + tags = merge(local.cis_v300_5_4_common_tags, { + cis_item_id = "5.4.2" + cis_level = "2" + cis_type = "automated" + service = "Azure/SQL" + }) +} + +control "cis_v300_5_4_3" { + title = "5.4.3 Use Entra ID Client Authentication and Azure RBAC where possible" + description = "Cosmos DB can use tokens or AAD for client authentication which in turn will use Azure RBAC for authorization. Using AAD is significantly more secure because AAD handles the credentials and allows for MFA and centralized management, and the Azure RBAC better integrated with the rest of Azure." + query = query.manual_control + documentation = file("./cis_v300/docs/cis_v300_5_4_3.md") + + tags = merge(local.cis_v300_5_4_common_tags, { + cis_item_id = "5.4.3" + cis_level = "1" + cis_type = "manual" + service = "Azure/SQL" + }) +} diff --git a/cis_v300/section_6.pp b/cis_v300/section_6.pp new file mode 100644 index 00000000..c7eb5bfa --- /dev/null +++ b/cis_v300/section_6.pp @@ -0,0 +1,356 @@ +locals { + cis_v300_6_common_tags = merge(local.cis_v300_common_tags, { + cis_section_id = "6" + }) +} + +locals { + cis_v300_6_1_common_tags = merge(local.cis_v300_6_common_tags, { + cis_section_id = "6.1" + }) + cis_v300_6_2_common_tags = merge(local.cis_v300_6_common_tags, { + cis_section_id = "6.2" + }) + cis_v300_6_3_common_tags = merge(local.cis_v300_6_common_tags, { + cis_section_id = "6.3" + }) +} + +benchmark "cis_v300_6" { + title = "6 Logging and Monitoring" + documentation = file("./cis_v300/docs/cis_v300_6.md") + children = [ + benchmark.cis_v300_6_1, + benchmark.cis_v300_6_2, + benchmark.cis_v300_6_3, + benchmark.cis_v300_6_5, + control.cis_v300_6_4 + ] + + tags = merge(local.cis_v300_6_common_tags, { + type = "Benchmark" + }) +} + +benchmark "cis_v300_6_1" { + title = "6.1 Configuring Diagnostic Settings" + documentation = file("./cis_v300/docs/cis_v300_6_1.md") + children = [ + control.cis_v300_6_1_1, + control.cis_v300_6_1_2, + control.cis_v300_6_1_3, + control.cis_v300_6_1_4, + control.cis_v300_6_1_5, + control.cis_v300_6_1_6 + ] + + tags = merge(local.cis_v300_6_common_tags, { + type = "Benchmark" + }) +} + +control "cis_v300_6_1_1" { + title = "6.1.1 Ensure that a 'Diagnostic Setting' exists for Subscription Activity Logs" + description = "Enable Diagnostic settings for exporting activity logs. Diagnostic settings are available for each individual resource within a subscription. Settings should be configured for all appropriate resources for your environment." + query = query.manual_control + documentation = file("./cis_v300/docs/cis_v300_6_1_1.md") + + tags = merge(local.cis_v300_6_1_common_tags, { + cis_item_id = "6.1.1" + cis_level = "1" + cis_type = "manual" + service = "Azure/Monitor" + }) +} + +control "cis_v300_6_1_2" { + title = "6.1.2 Ensure Diagnostic Setting captures appropriate categories" + description = "A Diagnostic Setting must exist. If a Diagnostic Setting does not exist, the navigation and options within this recommendation will not be available. Please review the recommendation at the beginning of this subsection titled: 'Ensure that a 'Diagnostic Setting' exists.' The diagnostic setting should be configured to log the appropriate activities from the control/management plane." + query = query.monitor_diagnostic_settings_captures_proper_categories + documentation = file("./cis_v300/docs/cis_v300_6_1_2.md") + + tags = merge(local.cis_v300_6_1_common_tags, { + cis_item_id = "6.1.2" + cis_level = "1" + cis_type = "automated" + service = "Azure/Monitor" + }) +} + +control "cis_v300_6_1_3" { + title = "6.1.3 Ensure the storage account containing the container with activity logs is encrypted with Customer Managed Key" + description = "Storage accounts with the activity log exports can be configured to use Customer Managed Keys (CMK)." + query = query.monitor_logs_storage_container_insights_activity_logs_encrypted_with_byok + documentation = file("./cis_v300/docs/cis_v300_6_1_3.md") + + tags = merge(local.cis_v300_6_1_common_tags, { + cis_item_id = "6.1.3" + cis_level = "2" + cis_type = "automated" + service = "Azure/Monitor" + }) +} + +control "cis_v300_6_1_4" { + title = "6.1.4 Ensure that logging for Azure Key Vault is 'Enabled'" + description = "Enable AuditEvent logging for key vault instances to ensure interactions with key vaults are logged and available." + query = query.keyvault_logging_enabled + documentation = file("./cis_v300/docs/cis_v300_6_1_4.md") + + tags = merge(local.cis_v300_6_1_common_tags, { + cis_item_id = "6.1.4" + cis_level = "1" + cis_type = "automated" + service = "Azure/KeyVault" + }) +} + +control "cis_v300_6_1_5" { + title = "6.1.5 Ensure that Network Security Group Flow logs are captured and sent to Log Analytics" + description = "Ensure that network flow logs are captured and fed into a central log analytics workspace." + query = query.manual_control + documentation = file("./cis_v300/docs/cis_v300_6_1_5.md") + + tags = merge(local.cis_v300_6_1_common_tags, { + cis_item_id = "6.1.5" + cis_level = "2" + cis_type = "manual" + service = "Azure/KeyVault" + }) +} + +control "cis_v300_6_1_6" { + title = "6.1.6 Ensure that logging for Azure AppService 'HTTP logs' is enabled" + description = "Enable AppServiceHTTPLogs diagnostic log category for Azure App Service instances to ensure all http requests are captured and centrally logged." + query = query.manual_control + documentation = file("./cis_v300/docs/cis_v300_6_1_6.md") + + tags = merge(local.cis_v300_6_1_common_tags, { + cis_item_id = "6.1.6" + cis_level = "2" + cis_type = "manual" + service = "Azure/KeyVault" + }) +} + +benchmark "cis_v300_6_2" { + title = "6.2 Monitoring using Activity Log Alerts" + documentation = file("./cis_v300/docs/cis_v300_6_2.md") + children = [ + control.cis_v300_6_2_1, + control.cis_v300_6_2_2, + control.cis_v300_6_2_3, + control.cis_v300_6_2_4, + control.cis_v300_6_2_5, + control.cis_v300_6_2_6, + control.cis_v300_6_2_7, + control.cis_v300_6_2_8, + control.cis_v300_6_2_9, + control.cis_v300_6_2_10 + ] + + tags = merge(local.cis_v300_6_common_tags, { + type = "Benchmark" + service = "Azure/Monitor" + }) +} + +control "cis_v300_6_2_1" { + title = "6.2.1 Ensure that Activity Log Alert exists for Create Policy Assignment" + description = "Create an activity log alert for the Create Policy Assignment event." + query = query.monitor_log_alert_create_policy_assignment + documentation = file("./cis_v300/docs/cis_v300_6_2_1.md") + + tags = merge(local.cis_v300_6_2_common_tags, { + cis_item_id = "6.2.1" + cis_level = "1" + cis_type = "automated" + service = "Azure/Monitor" + }) +} + +control "cis_v300_6_2_2" { + title = "6.2.2 Ensure that Activity Log Alert exists for Delete Policy Assignment" + description = "Create an activity log alert for the Delete Policy Assignment event." + query = query.monitor_log_alert_delete_policy_assignment + documentation = file("./cis_v300/docs/cis_v300_6_2_2.md") + + tags = merge(local.cis_v300_6_2_common_tags, { + cis_item_id = "6.2.2" + cis_level = "1" + cis_type = "automated" + service = "Azure/Monitor" + }) +} + +control "cis_v300_6_2_3" { + title = "6.2.3 Ensure that Activity Log Alert exists for Create or Update Network Security Group" + description = "Create an Activity Log Alert for the Create or Update Network Security Group event." + query = query.monitor_log_alert_create_update_nsg + documentation = file("./cis_v300/docs/cis_v300_6_2_3.md") + + tags = merge(local.cis_v300_6_2_common_tags, { + cis_item_id = "6.2.3" + cis_level = "1" + cis_type = "automated" + service = "Azure/Monitor" + }) +} + +control "cis_v300_6_2_4" { + title = "6.2.4 Ensure that Activity Log Alert exists for Delete Network Security Group" + description = "Create an activity log alert for the Delete Network Security Group event." + query = query.monitor_log_alert_delete_nsg + documentation = file("./cis_v300/docs/cis_v300_6_2_4.md") + + tags = merge(local.cis_v300_6_2_common_tags, { + cis_item_id = "6.2.4" + cis_level = "1" + cis_type = "automated" + service = "Azure/Monitor" + }) +} + +control "cis_v300_6_2_5" { + title = "6.2.5 Ensure that Activity Log Alert exists for Create or Update Security Solution" + description = "Create an activity log alert for the Create or Update Security Solution event." + query = query.monitor_log_alert_create_update_security_solution + documentation = file("./cis_v300/docs/cis_v300_6_2_5.md") + + tags = merge(local.cis_v300_6_2_common_tags, { + cis_item_id = "6.2.5" + cis_level = "1" + cis_type = "automated" + service = "Azure/Monitor" + }) +} + +control "cis_v300_6_2_6" { + title = "6.2.6 Ensure that Activity Log Alert exists for Delete Security Solution" + description = "Create an activity log alert for the Delete Security Solution event." + query = query.monitor_log_alert_delete_security_solution + documentation = file("./cis_v300/docs/cis_v300_6_2_6.md") + + tags = merge(local.cis_v300_6_2_common_tags, { + cis_item_id = "6.2.6" + cis_level = "1" + cis_type = "automated" + service = "Azure/Monitor" + }) +} + +control "cis_v300_6_2_7" { + title = "6.2.7 Ensure that Activity Log Alert exists for Create or Update SQL Server Firewall Rule" + description = "Create an activity log alert for the Create or Update SQL Server Firewall Rule event." + query = query.monitor_log_alert_create_update_sql_servers_firewall_rule + documentation = file("./cis_v300/docs/cis_v300_6_2_7.md") + + tags = merge(local.cis_v300_6_2_common_tags, { + cis_item_id = "6.2.7" + cis_level = "1" + cis_type = "automated" + service = "Azure/Monitor" + }) +} + +control "cis_v300_6_2_8" { + title = "6.2.8 Ensure that Activity Log Alert exists for Delete SQL Server Firewall Rule" + description = "Create an activity log alert for the 'Delete SQL Server Firewall Rule.'" + query = query.monitor_log_alert_delete_sql_servers_firewall_rule + documentation = file("./cis_v300/docs/cis_v300_6_2_8.md") + + tags = merge(local.cis_v300_6_2_common_tags, { + cis_item_id = "6.2.8" + cis_level = "1" + cis_type = "automated" + service = "Azure/Monitor" + }) +} + +control "cis_v300_6_2_9" { + title = "6.2.9 Ensure that Activity Log Alert exists for Create or Update Public IP Address rule" + description = "Create an activity log alert for the Create or Update Public IP Addresses rule." + query = query.monitor_log_alert_create_update_public_ip_address + documentation = file("./cis_v300/docs/cis_v300_6_2_9.md") + + tags = merge(local.cis_v300_6_2_common_tags, { + cis_item_id = "6.2.9" + cis_level = "1" + cis_type = "automated" + service = "Azure/Monitor" + }) +} + +control "cis_v300_6_2_10" { + title = "6.2.10 Ensure that Activity Log Alert exists for Delete Public IP Address rule" + description = "Create an activity log alert for the Delete Public IP Address rule." + query = query.monitor_log_alert_delete_public_ip_address + documentation = file("./cis_v300/docs/cis_v300_6_2_10.md") + + tags = merge(local.cis_v300_6_common_tags, { + cis_item_id = "6.2.10" + cis_level = "1" + cis_type = "automated" + service = "Azure/Monitor" + }) +} + +benchmark "cis_v300_6_3" { + title = "6.3 Configuring Application Insights" + documentation = file("./cis_v300/docs/cis_v300_6_3.md") + children = [ + control.cis_v300_6_3_1 + ] + + tags = merge(local.cis_v300_6_common_tags, { + type = "Benchmark" + service = "Azure/Monitor" + }) +} + +control "cis_v300_6_3_1" { + title = "6.3.1 Ensure Application Insights are Configured" + description = "Application Insights within Azure act as an Application Performance Monitoring solution providing valuable data into how well an application performs and additional information when performing incident response. The types of log data collected include application metrics, telemetry data, and application trace logging data providing organizations with detailed information about application activity and application transactions." + query = query.monitor_application_insights_configured + documentation = file("./cis_v300/docs/cis_v300_6_3_1.md") + + tags = merge(local.cis_v140_5_common_tags, { + cis_item_id = "6.3.1" + cis_level = "2" + cis_type = "automated" + service = "Azure/Monitor" + }) +} + +control "cis_v300_6_4" { + title = "6.4 Ensure that Azure Monitor Resource Logging is Enabled for All Services that Support it" + description = "Resource Logs capture activity to the data access plane while the Activity log is a subscription-level log for the control plane. Resource-level diagnostic logs provide insight into operations that were performed within that resource itself; for example, reading or updating a secret from a Key Vault." + query = query.manual_control + documentation = file("./cis_v300/docs/cis_v300_6_4.md") + + tags = merge(local.cis_v300_6_common_tags, { + cis_item_id = "6.4" + cis_level = "1" + cis_type = "manual" + service = "Azure/Monitor" + }) +} + +benchmark "cis_v300_6_5" { + title = "6.5 Ensure that SKU Basic/Consumption is not used on artifacts that need to be monitored (Particularly for Production Workloads)" + description = "The use of Basic or Free SKUs in Azure whilst cost effective have significant limitations in terms of what can be monitored and what support can be realized from Microsoft. Typically, these SKU's do not have a service SLA and Microsoft will usually refuse to provide support for them. Consequently Basic/Free SKUs should never be used for production workloads." + documentation = file("./cis_v300/docs/cis_v300_6_5.md") + children = [ + control.network_lb_no_basic_sku, + control.network_public_ip_no_basic_sku, + control.network_virtual_network_gateway_no_basic_sku, + control.redis_cache_no_basic_sku + ] + + tags = merge(local.cis_v300_6_common_tags, { + cis_item_id = "6.5" + cis_level = "2" + cis_type = "manual" + service = "Azure/Monitor" + }) +} diff --git a/cis_v300/section_7.pp b/cis_v300/section_7.pp new file mode 100644 index 00000000..8976a43d --- /dev/null +++ b/cis_v300/section_7.pp @@ -0,0 +1,122 @@ +locals { + cis_v300_7_common_tags = merge(local.cis_v300_common_tags, { + cis_section_id = "7" + }) +} + +benchmark "cis_v300_7" { + title = "7 Networking" + documentation = file("./cis_v300/docs/cis_v300_7.md") + children = [ + control.cis_v300_7_1, + control.cis_v300_7_2, + control.cis_v300_7_3, + control.cis_v300_7_4, + control.cis_v300_7_5, + control.cis_v300_7_6, + control.cis_v300_7_7 + ] + + tags = merge(local.cis_v300_7_common_tags, { + type = "Benchmark" + service = "Azure/Network" + }) +} + +control "cis_v300_7_1" { + title = "7.1 Ensure that RDP access from the Internet is evaluated and restricted" + description = "Network security groups should be periodically evaluated for port misconfigurations. Where certain ports and protocols may be exposed to the Internet, they should be evaluated for necessity and restricted wherever they are not explicitly required." + query = query.network_security_group_rdp_access_restricted + documentation = file("./cis_v300/docs/cis_v300_7_1.md") + + tags = merge(local.cis_v300_7_common_tags, { + cis_item_id = "7.1" + cis_level = "1" + cis_type = "automated" + service = "Azure/Network" + }) +} + +control "cis_v300_7_2" { + title = "7.2 Ensure that SSH access from the Internet is evaluated and restricted" + description = "Network security groups should be periodically evaluated for port misconfigurations. Where certain ports and protocols may be exposed to the Internet, they should be evaluated for necessity and restricted wherever they are not explicitly required." + query = query.network_security_group_ssh_access_restricted + documentation = file("./cis_v300/docs/cis_v300_7_2.md") + + tags = merge(local.cis_v300_7_common_tags, { + cis_item_id = "7.2" + cis_level = "1" + cis_type = "automated" + service = "Azure/Network" + }) +} + +control "cis_v300_7_3" { + title = "7.3 Ensure that UDP access from the Internet is evaluated and restricted" + description = "Network security groups should be periodically evaluated for port misconfigurations. Where certain ports and protocols may be exposed to the Internet, they should be evaluated for necessity and restricted wherever they are not explicitly required." + query = query.network_security_group_udp_service_restricted + documentation = file("./cis_v300/docs/cis_v300_7_3.md") + + tags = merge(local.cis_v300_7_common_tags, { + cis_item_id = "7.3" + cis_level = "1" + cis_type = "automated" + service = "Azure/Network" + }) +} + +control "cis_v300_7_4" { + title = "7.4 Ensure that HTTP(S) access from the Internet is evaluated and restricted" + description = "Network security groups should be periodically evaluated for port misconfigurations. Where certain ports and protocols may be exposed to the Internet, they should be evaluated for necessity and restricted wherever they are not explicitly required and narrowly configured." + query = query.network_security_group_https_access_restricted + documentation = file("./cis_v300/docs/cis_v300_7_4.md") + + tags = merge(local.cis_v300_7_common_tags, { + cis_item_id = "7.4" + cis_level = "1" + cis_type = "automated" + service = "Azure/Network" + }) +} + +control "cis_v300_7_5" { + title = "7.5 Ensure that Network Security Group Flow Log retention period is 'greater than 90 days'" + description = "Network Security Group Flow Logs should be enabled and the retention period set to greater than or equal to 90 days." + query = query.network_sg_flowlog_retention_period_greater_than_90 + documentation = file("./cis_v300/docs/cis_v300_7_5.md") + + tags = merge(local.cis_v300_7_common_tags, { + cis_item_id = "7.5" + cis_level = "2" + cis_type = "automated" + service = "Azure/Network" + }) +} + +control "cis_v300_7_6" { + title = "7.6 Ensure that Network Watcher is 'Enabled' for Azure Regions that are in use" + description = "Enable Network Watcher for physical regions in Azure subscriptions." + query = query.network_watcher_enabled + documentation = file("./cis_v300/docs/cis_v300_7_6.md") + + tags = merge(local.cis_v300_7_common_tags, { + cis_item_id = "7.6" + cis_level = "2" + cis_type = "automated" + service = "Azure/Network" + }) +} + +control "cis_v300_7_7" { + title = "7.7 Ensure that Public IP addresses are Evaluated on a Periodic Basis" + description = "Public IP Addresses provide tenant accounts with Internet connectivity for resources contained within the tenant. During the creation of certain resources in Azure, a Public IP Address may be created. All Public IP Addresses within the tenant should be periodically reviewed for accuracy and necessity." + query = query.manual_control + documentation = file("./cis_v300/docs/cis_v300_7_7.md") + + tags = merge(local.cis_v300_7_common_tags, { + cis_item_id = "7.7" + cis_level = "1" + cis_type = "manual" + service = "Azure/Network" + }) +} diff --git a/cis_v300/section_8.pp b/cis_v300/section_8.pp new file mode 100644 index 00000000..7046ff81 --- /dev/null +++ b/cis_v300/section_8.pp @@ -0,0 +1,182 @@ +locals { + cis_v300_8_common_tags = merge(local.cis_v300_common_tags, { + cis_section_id = "8" + }) +} + +benchmark "cis_v300_8" { + title = "8 Virtual Machines" + documentation = file("./cis_v300/docs/cis_v300_8.md") + children = [ + control.cis_v300_8_1, + control.cis_v300_8_2, + control.cis_v300_8_3, + control.cis_v300_8_4, + control.cis_v300_8_5, + control.cis_v300_8_6, + control.cis_v300_8_7, + control.cis_v300_8_8, + control.cis_v300_8_9, + control.cis_v300_8_10, + control.cis_v300_8_11 + ] + + tags = merge(local.cis_v300_8_common_tags, { + type = "Benchmark" + service = "Azure/Compute" + }) +} + +control "cis_v300_8_1" { + title = "8.1 Ensure an Azure Bastion Host Exists" + description = "The Azure Bastion service allows secure remote access to Azure Virtual Machines over the Internet without exposing remote access protocol ports and services directly to the Internet. The Azure Bastion service provides this access using TLS over 443/TCP, and subscribes to hardened configurations within an organization's Azure Active Directory service." + query = query.network_bastion_host_min_1 + documentation = file("./cis_v300/docs/cis_v300_8_1.md") + + tags = merge(local.cis_v300_8_common_tags, { + cis_item_id = "8.1" + cis_level = "2" + cis_type = "automated" + service = "Azure/Compute" + }) +} + +control "cis_v300_8_2" { + title = "8.2 Ensure Virtual Machines are utilizing Managed Disks" + description = "Migrate blob-based VHDs to Managed Disks on Virtual Machines to exploit the default features of this configuration." + query = query.compute_vm_utilizing_managed_disk + documentation = file("./cis_v300/docs/cis_v300_8_2.md") + + tags = merge(local.cis_v300_8_common_tags, { + cis_item_id = "8.2" + cis_level = "1" + cis_type = "automated" + service = "Azure/Compute" + }) +} + +control "cis_v300_8_3" { + title = "8.3 Ensure that 'OS and Data' disks are encrypted with Customer Managed Key (CMK)" + description = "Ensure that OS disks (boot volumes) and data disks (non-boot volumes) are encrypted with CMK (Customer Managed Keys). Customer Managed keys can be either ADE or Server Side Encryption(SSE)." + query = query.compute_os_and_data_disk_encrypted_with_cmk + documentation = file("./cis_v300/docs/cis_v300_8_3.md") + + tags = merge(local.cis_v300_8_common_tags, { + cis_item_id = "8.3" + cis_level = "2" + cis_type = "automated" + service = "Azure/Compute" + }) +} + +control "cis_v300_8_4" { + title = "8.4 Ensure that 'Unattached disks' are encrypted with 'Customer Managed Key' (CMK)" + description = "Ensure that unattached disks in a subscription are encrypted with a Customer Managed Key (CMK)." + query = query.compute_unattached_disk_encrypted_with_cmk + documentation = file("./cis_v300/docs/cis_v300_8_4.md") + + tags = merge(local.cis_v300_8_common_tags, { + cis_item_id = "8.4" + cis_level = "2" + cis_type = "automated" + service = "Azure/Compute" + }) +} + +control "cis_v300_8_5" { + title = "8.5 Ensure that 'Disk Network Access' is NOT set to 'Enable public access from all networks'" + description = "Virtual Machine Disks and snapshots can be configured to allow access from different network resources." + query = query.compute_disk_public_access_disabled + documentation = file("./cis_v300/docs/cis_v300_8_5.md") + + tags = merge(local.cis_v300_8_common_tags, { + cis_item_id = "8.5" + cis_level = "1" + cis_type = "automated" + service = "Azure/Compute" + }) +} + +control "cis_v300_8_6" { + title = "8.6 Ensure that 'Enable Data Access Authentication Mode' is 'Checked'" + description = "Data Access Authentication Mode provides a method of uploading or exporting Virtual Machine Disks." + query = query.compute_disk_data_access_auth_mode_enabled + documentation = file("./cis_v300/docs/cis_v300_8_6.md") + + tags = merge(local.cis_v300_8_common_tags, { + cis_item_id = "8.6" + cis_level = "1" + cis_type = "automated" + service = "Azure/Compute" + }) +} + +control "cis_v300_8_7" { + title = "8.7 Ensure that Only Approved Extensions Are Installed" + description = "For added security, only install organization-approved extensions on VMs." + query = query.manual_control + documentation = file("./cis_v300/docs/cis_v300_8_7.md") + + tags = merge(local.cis_v300_8_common_tags, { + cis_item_id = "8.7" + cis_level = "1" + cis_type = "manual" + service = "Azure/Compute" + }) +} + +control "cis_v300_8_8" { + title = "8.8 Ensure that Endpoint Protection for all Virtual Machines is installed" + description = "Install endpoint protection for all virtual machines." + query = query.manual_control + documentation = file("./cis_v300/docs/cis_v300_8_8.md") + + tags = merge(local.cis_v300_8_common_tags, { + cis_item_id = "8.8" + cis_level = "2" + cis_type = "manual" + service = "Azure/Compute" + }) +} + +control "cis_v300_8_9" { + title = "8.9 [Legacy] Ensure that VHDs are Encrypted" + description = "VHD (Virtual Hard Disks) are stored in blob storage and are the old-style disks that were attached to Virtual Machines. The blob VHD was then leased to the VM. By default, storage accounts are not encrypted, and Microsoft Defender will then recommend that the OS disks should be encrypted. Storage accounts can be encrypted as a whole using PMK or CMK. This should be turned on for storage accounts containing VHDs." + query = query.manual_control + documentation = file("./cis_v300/docs/cis_v300_8_9.md") + + tags = merge(local.cis_v300_8_common_tags, { + cis_item_id = "8.9" + cis_level = "2" + cis_type = "manual" + service = "Azure/Compute" + }) +} + +control "cis_v300_8_10" { + title = "8.10 Ensure only MFA enabled identities can access privileged Virtual Machine" + description = "Verify identities without MFA that can log in to a privileged virtual machine using separate login credentials. An adversary can leverage the access to move laterally and perform actions with the virtual machine's managed identity. Make sure the virtual machine only has necessary permissions, and revoke the admin-level permissions according to the least privileges principal." + query = query.manual_control + documentation = file("./cis_v300/docs/cis_v300_8_10.md") + + tags = merge(local.cis_v300_8_common_tags, { + cis_item_id = "8.10" + cis_level = "2" + cis_type = "manual" + service = "Azure/Compute" + }) +} + +control "cis_v300_8_11" { + title = "8.11 Ensure Trusted Launch is enabled on Virtual Machines" + description = "When Secure Boot and vTPM are enabled together, they provide a strong foundation for protecting your VM from boot attacks. For example, if an attacker attempts to replace the bootloader with a malicious version, Secure Boot will prevent the VM from booting." + query = query.manual_control + documentation = file("./cis_v300/docs/cis_v300_8_11.md") + + tags = merge(local.cis_v300_8_common_tags, { + cis_item_id = "8.11" + cis_level = "1" + cis_type = "automated" + service = "Azure/Compute" + }) +} \ No newline at end of file diff --git a/cis_v300/section_9.pp b/cis_v300/section_9.pp new file mode 100644 index 00000000..7be2a627 --- /dev/null +++ b/cis_v300/section_9.pp @@ -0,0 +1,197 @@ +locals { + cis_v300_9_common_tags = merge(local.cis_v300_common_tags, { + cis_section_id = "9" + }) +} + +benchmark "cis_v300_9" { + title = "9 AppService" + documentation = file("./cis_v300/docs/cis_v300_9.md") + children = [ + control.cis_v300_9_1, + control.cis_v300_9_2, + control.cis_v300_9_3, + control.cis_v300_9_4, + control.cis_v300_9_5, + control.cis_v300_9_6, + control.cis_v300_9_7, + control.cis_v300_9_8, + control.cis_v300_9_9, + control.cis_v300_9_10, + control.cis_v300_9_11, + control.cis_v300_9_12 + ] + + tags = merge(local.cis_v300_9_common_tags, { + type = "Benchmark" + service = "Azure/AppService" + }) +} + +control "cis_v300_9_1" { + title = "9.1 Ensure 'HTTPS Only' is set to `On`" + description = "Azure App Service allows apps to run under both HTTP and HTTPS by default. Apps can be accessed by anyone using non-secure HTTP links by default. Non-secure HTTP requests can be restricted and all HTTP requests redirected to the secure HTTPS port. It is recommended to enforce HTTPS-only traffic." + query = query.appservice_web_app_use_https + documentation = file("./cis_v300/docs/cis_v300_9_1.md") + + tags = merge(local.cis_v300_9_common_tags, { + cis_item_id = "9.1" + cis_level = "1" + cis_type = "manual" + service = "Azure/AppService" + }) +} + +control "cis_v300_9_2" { + title = "9.2 Ensure App Service Authentication is set up for apps in Azure App Service" + description = "Azure App Service Authentication is a feature that can prevent anonymous HTTP requests from reaching a Web Application or authenticate those with tokens before they reach the app. If an anonymous request is received from a browser, App Service will redirect to a logon page. To handle the logon process, a choice from a set of identity providers can be made, or a custom authentication mechanism can be implemented." + query = query.appservice_authentication_enabled + documentation = file("./cis_v300/docs/cis_v300_9_2.md") + + tags = merge(local.cis_v300_9_common_tags, { + cis_item_id = "9.2" + cis_level = "2" + cis_type = "automated" + service = "Azure/AppService" + }) +} + +control "cis_v300_9_3" { + title = "9.3 Ensure 'FTP State' is set to 'FTPS Only' or 'Disabled'" + description = "By default, App Services can be deployed over FTP. If FTP is required for an essential deployment workflow, FTPS should be required for FTP login for all App Services. If FTPS is not expressly required for the App, the recommended setting is Disabled." + query = query.appservice_ftp_deployment_disabled + documentation = file("./cis_v300/docs/cis_v300_9_3.md") + + tags = merge(local.cis_v300_9_common_tags, { + cis_item_id = "9.3" + cis_level = "1" + cis_type = "automated" + service = "Azure/AppService" + }) +} + +control "cis_v300_9_4" { + title = "9.4 Ensure Web App is using the latest version of TLS encryption" + description = "The TLS (Transport Layer Security) protocol secures transmission of data over the internet using standard encryption technology. Encryption should be set with the latest version of TLS. App service allows TLS 1.2 by default, which is the recommended TLS level by industry standards such as PCI DSS." + query = query.appservice_web_app_latest_tls_version + documentation = file("./cis_v300/docs/cis_v300_9_4.md") + + tags = merge(local.cis_v300_9_common_tags, { + cis_item_id = "9.4" + cis_level = "1" + cis_type = "automated" + service = "Azure/AppService" + }) +} + +control "cis_v300_9_5" { + title = "9.5 Ensure that Register with Entra ID is enabled on App Service" + description = "Managed service identity in App Service provides more security by eliminating secrets from the app, such as credentials in the connection strings. When registering an App Service with Entra ID, the app will connect to other Azure services securely without the need for usernames and passwords." + query = query.appservice_web_app_register_with_active_directory_enabled + documentation = file("./cis_v300/docs/cis_v300_9_5.md") + + tags = merge(local.cis_v300_9_common_tags, { + cis_item_id = "9.5" + cis_level = "1" + cis_type = "automated" + service = "Azure/AppService" + }) +} + +control "cis_v300_9_6" { + title = "9.6 Ensure that 'Basic Authentication' is 'Disabled'" + description = "Basic Authentication provides the ability to create identities and authentication for an App Service without a centralized Identity Provider. For a more effective, capable, and secure solution for Identity, Authentication, Authorization, and Accountability, a centralized Identity Provider such as Entra ID is strongly advised." + query = query.manual_control + documentation = file("./cis_v300/docs/cis_v300_9_6.md") + + tags = merge(local.cis_v300_9_common_tags, { + cis_item_id = "9.6" + cis_level = "1" + cis_type = "automated" + service = "Azure/AppService" + }) +} + +control "cis_v300_9_7" { + title = "9.7 Ensure that 'PHP version' is currently supported (if in use)" + description = "Periodically, older versions of PHP may be deprecated and no longer supported. Using a supported version of PHP for app services is recommended to avoid potential unpatched vulnerabilities." + query = query.appservice_web_app_latest_php_version + documentation = file("./cis_v300/docs/cis_v300_9_7.md") + + tags = merge(local.cis_v300_9_common_tags, { + cis_item_id = "9.7" + cis_level = "1" + cis_type = "manual" + service = "Azure/AppService" + }) +} + +control "cis_v300_9_8" { + title = "9.8 Ensure that 'Python version' is currently supported (if in use)" + description = "Periodically, older versions of Python may be deprecated and no longer supported. Using a supported version of Python for app services is recommended to avoid potential unpatched vulnerabilities." + query = query.appservice_web_app_latest_python_version + documentation = file("./cis_v300/docs/cis_v300_9_8.md") + + tags = merge(local.cis_v300_9_common_tags, { + cis_item_id = "9.8" + cis_level = "1" + cis_type = "manual" + service = "Azure/AppService" + }) +} + +control "cis_v300_9_9" { + title = "9.9 Ensure that 'Java version' is currently supported (if in use)" + description = "Periodically, newer versions are released for Java software either due to security flaws or to include additional functionality. Using the latest Java version for web apps is recommended in order to take advantage of security fixes, if any, and/or new functionalities of the newer version." + query = query.appservice_web_app_latest_java_version + documentation = file("./cis_v300/docs/cis_v300_9_9.md") + + tags = merge(local.cis_v300_9_common_tags, { + cis_item_id = "9.9" + cis_level = "1" + cis_type = "manual" + service = "Azure/AppService" + }) +} + +control "cis_v300_9_10" { + title = "9.10 Ensure that 'HTTP20enabled' is set to 'true' (if in use)" + description = "Periodically, newer versions are released for HTTP either due to security flaws or to include additional functionality. Using the latest HTTP version for apps to take advantage of security fixes, if any, and/or new functionalities of the newer version." + query = query.appservice_web_app_latest_http_version + documentation = file("./cis_v300/docs/cis_v300_9_10.md") + + tags = merge(local.cis_v300_9_common_tags, { + cis_item_id = "9.10" + cis_level = "1" + cis_type = "automated" + service = "Azure/AppService" + }) +} + +control "cis_v300_9_11" { + title = "9.11 Ensure Azure Key Vaults are Used to Store Secrets" + description = "Azure Key Vault will store multiple types of sensitive information such as encryption keys, certificate thumbprints, and Managed Identity Credentials. Access to these 'Secrets' can be controlled through granular permissions." + query = query.manual_control + documentation = file("./cis_v300/docs/cis_v300_9_11.md") + + tags = merge(local.cis_v300_9_common_tags, { + cis_item_id = "9.11" + cis_level = "2" + cis_type = "manual" + service = "Azure/AppService" + }) +} + +control "cis_v300_9_12" { + title = "9.12 Ensure that 'Remote debugging' is set to 'Off'" + description = "Remote Debugging allows Azure App Service to be debugged in real-time directly on the Azure environment. When remote debugging is enabled, it opens a communication channel that could potentially be exploited by unauthorized users if not properly secured." + query = query.appservice_web_app_remote_debugging_disabled + documentation = file("./cis_v300/docs/cis_v300_9_12.md") + + tags = merge(local.cis_v300_9_common_tags, { + cis_item_id = "9.12" + cis_level = "1" + cis_type = "manual" + service = "Azure/AppService" + }) +} \ No newline at end of file diff --git a/docs/index.md b/docs/index.md index 8bcc3303..028fa713 100644 --- a/docs/index.md +++ b/docs/index.md @@ -72,7 +72,7 @@ powerpipe benchmark list Run a benchmark: ```sh -powerpipe benchmark run azure_compliance.benchmark.cis_v200 +powerpipe benchmark run azure_compliance.benchmark.cis_v300 ``` Different output formats are also available, for more information please see @@ -92,7 +92,7 @@ vi powerpipe.ppvars Alternatively you can pass variables on the command line: ```sh -powerpipe benchmark run azure_compliance.benchmark.cis_v200 --var 'tag_dimensions=["Environment", "Owner"]' +powerpipe benchmark run azure_compliance.benchmark.cis_v300 --var 'tag_dimensions=["Environment", "Owner"]' ``` Or through environment variables: @@ -100,7 +100,7 @@ Or through environment variables: ```sh export PP_VAR_common_dimensions='["subscription_id", "connection_name", "resource_group"]' export PP_VAR_tag_dimensions='["Environment", "Owner"]' -powerpipe benchmark run azure_compliance.benchmark.cis_v200 +powerpipe benchmark run azure_compliance.benchmark.cis_v300 ``` ## Open Source & Contributing diff --git a/mod.pp b/mod.pp index 212ae9e8..655dbaf1 100644 --- a/mod.pp +++ b/mod.pp @@ -15,7 +15,7 @@ require { plugin "azure" { - min_version = "0.55.0" + min_version = "0.66.0" } plugin "azuread" { min_version = "0.0.3" diff --git a/regulatory_compliance/appservice.pp b/regulatory_compliance/appservice.pp index 10686df1..f6dc7d5d 100644 --- a/regulatory_compliance/appservice.pp +++ b/regulatory_compliance/appservice.pp @@ -478,7 +478,7 @@ when not https_only then name || ' does not redirect all HTTP traffic to HTTPS.' else name || ' redirects all HTTP traffic to HTTPS.' end as reason - ${local.tag_dimensions_sql} + ${replace(local.tag_dimensions_qualifier_sql, "__QUALIFIER__", "app.")} ${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "app.")} ${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")} from @@ -526,7 +526,7 @@ when configuration -> 'properties' ->> 'remoteDebuggingEnabled' = 'false' then name || ' remote debugging disabled.' else name || ' remote debugging enabled.' end as reason - ${local.tag_dimensions_sql} + ${replace(local.tag_dimensions_qualifier_sql, "__QUALIFIER__", "app.")} ${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "app.")} ${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")} from @@ -595,7 +595,7 @@ when configuration -> 'properties' ->> 'minTlsVersion' < '1.2' then name || ' not using the latest version of TLS encryption.' else name || ' using the latest version of TLS encryption.' end as reason - ${local.tag_dimensions_sql} + ${replace(local.tag_dimensions_qualifier_sql, "__QUALIFIER__", "app.")} ${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "app.")} ${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")} from @@ -1297,7 +1297,7 @@ when not (configuration -> 'properties' ->> 'http20Enabled') :: boolean then name || ' HTTP version not latest.' else name || ' HTTP version is latest.' end as reason - ${local.tag_dimensions_sql} + ${replace(local.tag_dimensions_qualifier_sql, "__QUALIFIER__", "app.")} ${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "app.")} ${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")} from @@ -1430,7 +1430,7 @@ when configuration -> 'properties' ->> 'linuxFxVersion' like '%11' then a.name || ' using the latest JAVA version.' else a.name || ' not using latest JAVA version.' end as reason - ${local.tag_dimensions_sql} + ${replace(local.tag_dimensions_qualifier_sql, "__QUALIFIER__", "a.")} ${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "a.")} ${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")} from @@ -1480,7 +1480,7 @@ when configuration -> 'properties' ->> 'linuxFxVersion' = 'PHP|8.0' then a.name || ' using the latest php version.' else a.name || ' not using latest php version.' end as reason - ${local.tag_dimensions_sql} + ${replace(local.tag_dimensions_qualifier_sql, "__QUALIFIER__", "a.")} ${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "a.")} ${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")} from @@ -1580,7 +1580,7 @@ when configuration -> 'properties' ->> 'linuxFxVersion' = 'PYTHON|3.9' then a.name || ' using the latest python version.' else a.name || ' not using latest python version.' end as reason - ${local.tag_dimensions_sql} + ${replace(local.tag_dimensions_qualifier_sql, "__QUALIFIER__", "a.")} ${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "a.")} ${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")} from @@ -1606,7 +1606,7 @@ when not (auth_settings -> 'properties' ->> 'enabled') :: boolean then name || ' authentication not set.' else name || ' authentication set.' end as reason - ${local.tag_dimensions_sql} + ${replace(local.tag_dimensions_qualifier_sql, "__QUALIFIER__", "app.")} ${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "app.")} ${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")} from @@ -1629,7 +1629,7 @@ when configuration -> 'properties' ->> 'ftpsState' = 'AllAllowed' then name || ' FTP deployments enabled.' else name || ' FTP deployments disabled.' end as reason - ${local.tag_dimensions_sql} + ${replace(local.tag_dimensions_qualifier_sql, "__QUALIFIER__", "fa.")} ${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "fa.")} ${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")} from @@ -1648,7 +1648,7 @@ when configuration -> 'properties' ->> 'ftpsState' = 'AllAllowed' then name || ' FTP deployments enabled.' else name || ' FTP deployments disabled.' end as reason - ${local.tag_dimensions_sql} + ${replace(local.tag_dimensions_qualifier_sql, "__QUALIFIER__", "wa.")} ${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "wa.")} ${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")} from @@ -1671,7 +1671,7 @@ when identity = '{}' then name || ' register with azure active directory disabled.' else name || ' register with azure active directory enabled.' end as reason - ${local.tag_dimensions_sql} + ${replace(local.tag_dimensions_qualifier_sql, "__QUALIFIER__", "app.")} ${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "app.")} ${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")} from diff --git a/regulatory_compliance/compute.pp b/regulatory_compliance/compute.pp index 26774524..b54bd0ed 100644 --- a/regulatory_compliance/compute.pp +++ b/regulatory_compliance/compute.pp @@ -887,6 +887,22 @@ }) } +control "compute_disk_public_access_disabled" { + title = "Ensure that 'Disk Network Access' is NOT set to 'Enable public access from all networks'" + description = "Virtual Machine Disks and snapshots can be configured to allow access from different network resources." + query = query.compute_disk_public_access_disabled + + tags = local.regulatory_compliance_compute_common_tags +} + +control "compute_disk_data_access_auth_mode_enabled" { + title = "Ensure that 'Enable Data Access Authentication Mode' is 'Checked'" + description = "Data Access Authentication Mode provides a method of uploading or exporting Virtual Machine Disks." + query = query.compute_disk_data_access_auth_mode_enabled + + tags = local.regulatory_compliance_compute_common_tags +} + query "compute_os_and_data_disk_encrypted_with_cmk" { sql = <<-EOQ select @@ -899,7 +915,7 @@ when encryption_type = 'EncryptionAtRestWithCustomerKey' then disk.name || ' encrypted with CMK.' else disk.name || ' not encrypted with CMK.' end as reason - ${local.tag_dimensions_sql} + ${replace(local.tag_dimensions_qualifier_sql, "__QUALIFIER__", "disk.")} ${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "disk.")} ${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")} from @@ -986,7 +1002,7 @@ when encryption_type = 'EncryptionAtRestWithCustomerKey' then disk.name || ' encrypted with CMK.' else disk.name || ' not encrypted with CMK.' end as reason - ${local.tag_dimensions_sql} + ${replace(local.tag_dimensions_qualifier_sql, "__QUALIFIER__", "disk.")} ${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "disk.")} ${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")} from @@ -2573,7 +2589,7 @@ when managed_disk_id is null then vm.name || ' VM not utilizing managed disks.' else vm.name || ' VM utilizing managed disks.' end as reason - ${local.tag_dimensions_sql} + ${replace(local.tag_dimensions_qualifier_sql, "__QUALIFIER__", "vm.")} ${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "vm.")} ${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")} from @@ -2683,7 +2699,7 @@ or managed_by != '' or encryption_type = 'EncryptionAtRestWithCustomerKey' or encryption_type = 'EncryptionAtRestWithPlatformAndCustomerKeys' - then 'ok' + then 'ok' else 'alarm' end as status, case @@ -2775,4 +2791,50 @@ where sub.subscription_id = a.subscription_id EOQ -} \ No newline at end of file +} + +query "compute_disk_public_access_disabled" { + sql = <<-EOQ + select + disk.id as resource, + case + when network_access_policy in ('DenyAll','AllowPrivate') and public_network_access = 'Disabled' then 'ok' + else 'alarm' + end as status, + case + when network_access_policy in ('DenyAll','AllowPrivate') and public_network_access = 'Disabled' then disk.name || ' network access disabled.' + else disk.name || ' network access enabled.' + end as reason + ${replace(local.tag_dimensions_qualifier_sql, "__QUALIFIER__", "disk.")} + ${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "disk.")} + ${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")} + from + azure_compute_disk disk, + azure_subscription sub + where + sub.subscription_id = disk.subscription_id; + EOQ +} + +query "compute_disk_data_access_auth_mode_enabled" { + sql = <<-EOQ + select + disk.id as resource, + case + when data_access_auth_mode = 'AzureActiveDirectory' then 'ok' + else 'alarm' + end as status, + case + when data_access_auth_mode = 'AzureActiveDirectory' then disk.name || ' data authentication mode enabled.' + else disk.name || ' data authentication mode disabled.' + end as reason + ${replace(local.tag_dimensions_qualifier_sql, "__QUALIFIER__", "disk.")} + ${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "disk.")} + ${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")} + from + azure_compute_disk disk, + azure_subscription sub + where + sub.subscription_id = disk.subscription_id; + EOQ +} diff --git a/regulatory_compliance/cosmosdb.pp b/regulatory_compliance/cosmosdb.pp index efca8571..33389029 100644 --- a/regulatory_compliance/cosmosdb.pp +++ b/regulatory_compliance/cosmosdb.pp @@ -159,7 +159,7 @@ when c.id is null then a.name || ' not uses private link.' else a.name || ' uses private link.' end as reason - ${local.tag_dimensions_sql} + ${replace(local.tag_dimensions_qualifier_sql, "__QUALIFIER__", "a.")} ${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "a.")} ${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")} from @@ -233,7 +233,7 @@ when public_network_access = 'Enabled' and is_virtual_network_filter_enabled = 'true' then a.name || ' virtual network filter enabled.' else a.name || ' virtual network filter disabled.' end as reason - ${local.tag_dimensions_sql} + ${replace(local.tag_dimensions_qualifier_sql, "__QUALIFIER__", "a.")} ${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "a.")} ${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")} from diff --git a/regulatory_compliance/keyvault.pp b/regulatory_compliance/keyvault.pp index bb68bf5c..471ea458 100644 --- a/regulatory_compliance/keyvault.pp +++ b/regulatory_compliance/keyvault.pp @@ -242,7 +242,7 @@ when l.key_vault_name not like concat('%', v.name, '%') then v.name || ' logging not enabled.' else v.name || ' logging enabled.' end as reason - ${local.tag_dimensions_sql} + ${replace(local.tag_dimensions_qualifier_sql, "__QUALIFIER__", "v.")} ${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "v.")} ${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")} from @@ -374,7 +374,7 @@ then a.name || ' using private link.' else a.name || ' private link not enabled.' end as reason - ${local.tag_dimensions_sql} + ${replace(local.tag_dimensions_qualifier_sql, "__QUALIFIER__", "a.")} ${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "a.")} ${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")} from @@ -491,7 +491,7 @@ when enable_rbac_authorization then name || ' has RBAC enabled.' else name || ' have RBAC disabled.' end as reason - ${local.tag_dimensions_sql} + ${replace(local.tag_dimensions_qualifier_sql, "__QUALIFIER__", "kv.")} ${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "kv.")} ${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")} from @@ -525,7 +525,7 @@ when not enabled then ' disabled.' else ' expiration date set to ' || to_char(expires_at, 'DD-Mon-YYYY') || '.' end as reason - ${local.tag_dimensions_sql} + ${replace(local.tag_dimensions_qualifier_sql, "__QUALIFIER__", "kvk.")} ${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "kvk.")} ${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")} from @@ -551,7 +551,7 @@ when not purge_protection_enabled then name || ' "do not purge" not enabled.' else name || ' "soft delete" and "do not purge" enabled.' end as reason - ${local.tag_dimensions_sql} + ${replace(local.tag_dimensions_qualifier_sql, "__QUALIFIER__", "kv.")} ${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "kv.")} ${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")} from @@ -585,7 +585,7 @@ when not enabled then ' disabled.' else ' expiration date set to ' || to_char(expires_at, 'DD-Mon-YYYY') || '.' end as reason - ${local.tag_dimensions_sql} + ${replace(local.tag_dimensions_qualifier_sql, "__QUALIFIER__", "kvs.")} ${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "kvs.")} ${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")} from @@ -620,7 +620,7 @@ when not enabled then ' disabled.' else ' expiration date set to ' || to_char(expires_at, 'DD-Mon-YYYY') || '.' end as reason - ${local.tag_dimensions_sql} + ${replace(local.tag_dimensions_qualifier_sql, "__QUALIFIER__", "kvk.")} ${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "kvk.")} ${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")} from @@ -655,7 +655,7 @@ when not enabled then ' disabled.' else ' expiration date set to ' || to_char(expires_at, 'DD-Mon-YYYY') || '.' end as reason - ${local.tag_dimensions_sql} + ${replace(local.tag_dimensions_qualifier_sql, "__QUALIFIER__", "kvs.")} ${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "kvs.")} ${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")} from diff --git a/regulatory_compliance/monitor.pp b/regulatory_compliance/monitor.pp index a4c23ca8..6007f964 100644 --- a/regulatory_compliance/monitor.pp +++ b/regulatory_compliance/monitor.pp @@ -1175,7 +1175,7 @@ then a.name || ' container insights-activity-logs encrypted with BYOK.' else a.name || ' container insights-activity-logs not encrypted with BYOK.' end as reason - ${local.tag_dimensions_sql} + ${replace(local.tag_dimensions_qualifier_sql, "__QUALIFIER__", "a.")} ${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "a.")} ${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")} from diff --git a/regulatory_compliance/mysql.pp b/regulatory_compliance/mysql.pp index ede10792..8fe4b0b1 100644 --- a/regulatory_compliance/mysql.pp +++ b/regulatory_compliance/mysql.pp @@ -424,3 +424,138 @@ sub.subscription_id = s.subscription_id; EOQ } + +query "mysql_flexible_server_ssl_enabled" { + sql = <<-EOQ + with ssl_enabled as( + select + id + from + azure_mysql_flexible_server, + jsonb_array_elements(flexible_server_configurations) as config + where + config ->> 'Name' = 'require_secure_transport' and config -> 'ConfigurationProperties' ->> 'value' = 'ON' + ) + select + s.id as resource, + case + when a.id is not null then 'ok' + else 'alarm' + end as status, + case + when a.id is not null then s.title || ' SSL connection enabled.' + else s.title || ' SSL connection disabled.' + end as reason + ${replace(local.tag_dimensions_qualifier_sql, "__QUALIFIER__", "s.")} + ${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "s.")} + ${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")} + from + azure_mysql_flexible_server as s + left join ssl_enabled as a on s.id = a.id, + azure_subscription as sub + where + sub.subscription_id = s.subscription_id; + EOQ +} + +query "mysql_flexible_server_min_tls_1_2" { + sql = <<-EOQ + with tls_version as( + select + id + from + azure_mysql_flexible_server, + jsonb_array_elements(flexible_server_configurations) as config + where + config ->> 'Name' = 'tls_version' + and config -> 'ConfigurationProperties' ->> 'value' = 'TLSv1.2,TLSv1.3' + ) + select + s.id as resource, + case + when a.id is not null then 'ok' + else 'alarm' + end as status, + case + when a.id is not null then s.title || ' minimum TLS version set to TLSv1.2,TLSv1.3.' + else s.title || ' minimum TLS version not set to TLSv1.2,TLSv1.3.' + end as reason + ${replace(local.tag_dimensions_qualifier_sql, "__QUALIFIER__", "s.")} + ${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "s.")} + ${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")} + from + azure_mysql_flexible_server as s + left join tls_version as a on s.id = a.id, + azure_subscription as sub + where + sub.subscription_id = s.subscription_id; + EOQ +} + +query "mysql_flexible_server_audit_logging_enabled" { + sql = <<-EOQ + with audit_log_enabled as( + select + id + from + azure_mysql_flexible_server, + jsonb_array_elements(flexible_server_configurations) as config + where + config ->> 'Name' = 'audit_log_enabled' + and config -> 'ConfigurationProperties' ->> 'value' = 'ON' + ) + select + s.id as resource, + case + when a.id is not null then 'ok' + else 'alarm' + end as status, + case + when a.id is not null then s.title || ' audit logging enabled.' + else s.title || ' audit logging disabled.' + end as reason + ${replace(local.tag_dimensions_qualifier_sql, "__QUALIFIER__", "s.")} + ${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "s.")} + ${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")} + from + azure_mysql_flexible_server as s + left join audit_log_enabled as a on s.id = a.id, + azure_subscription as sub + where + sub.subscription_id = s.subscription_id; + EOQ +} + +query "mysql_flexible_server_audit_logging_events_connection_set" { + sql = <<-EOQ + with audit_log_events as( + select + id + from + azure_mysql_flexible_server, + jsonb_array_elements(flexible_server_configurations) as config + where + config ->> 'Name' = 'audit_log_events' + and config -> 'ConfigurationProperties' ->> 'value' = 'CONNECTION' + ) + select + s.id as resource, + case + when a.id is not null then 'ok' + else 'alarm' + end as status, + case + when a.id is not null then s.title || ' server parameter audit_log_events has connection set.' + else s.title || ' server parameter audit_log_events connection not set.' + end as reason + ${replace(local.tag_dimensions_qualifier_sql, "__QUALIFIER__", "s.")} + ${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "s.")} + ${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")} + from + azure_mysql_flexible_server as s + left join audit_log_events as a on s.id = a.id, + azure_subscription as sub + where + sub.subscription_id = s.subscription_id; + EOQ +} diff --git a/regulatory_compliance/network.pp b/regulatory_compliance/network.pp index 544540ac..e1d292b4 100644 --- a/regulatory_compliance/network.pp +++ b/regulatory_compliance/network.pp @@ -478,7 +478,7 @@ then sg.title || ' restricts RDP access from internet.' else sg.title || ' allows RDP access from internet.' end as reason - ${local.tag_dimensions_sql} + ${replace(local.tag_dimensions_qualifier_sql, "__QUALIFIER__", "sg.")} ${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "sg.")} ${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")} from @@ -501,7 +501,7 @@ else 'Network watcher enabled in ' || loc.name || '.' end as reason, loc.name - ${local.tag_dimensions_sql} + ${replace(local.tag_dimensions_qualifier_sql, "__QUALIFIER__", "watcher.")} ${replace(local.common_dimensions_subscription_id_qualifier_sql, "__QUALIFIER__", "loc.")} ${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")} from @@ -679,7 +679,7 @@ when g.sku_name = 'Basic' then g.title || ' using basic SKU.' else g.title || ' using ' || sku_name || ' SKU.' end as reason - ${local.tag_dimensions_sql} + ${replace(local.tag_dimensions_qualifier_sql, "__QUALIFIER__", "g.")} ${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "g.")} ${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")} from @@ -702,7 +702,7 @@ when l.sku_name = 'Basic' then l.title || ' using basic SKU.' else l.title || ' using ' || sku_name || ' SKU.' end as reason - ${local.tag_dimensions_sql} + ${replace(local.tag_dimensions_qualifier_sql, "__QUALIFIER__", "l.")} ${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "l.")} ${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")} from @@ -725,7 +725,7 @@ when i.sku_name = 'Basic' then i.title || ' using basic SKU.' else i.title || ' using ' || sku_name || ' SKU.' end as reason - ${local.tag_dimensions_sql} + ${replace(local.tag_dimensions_qualifier_sql, "__QUALIFIER__", "i.")} ${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "i.")} ${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")} from @@ -820,7 +820,7 @@ when nsg.sg_name is null then sg.title || ' restricts HTTPS access from internet.' else sg.title || ' allows HTTPS access from internet.' end as reason - ${local.tag_dimensions_sql} + ${replace(local.tag_dimensions_qualifier_sql, "__QUALIFIER__", "sg.")} ${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "sg.")} ${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")} from @@ -865,7 +865,7 @@ then sg.title || ' restricts SSH access from internet.' else sg.title || ' allows SSH access from internet.' end as reason - ${local.tag_dimensions_sql} + ${replace(local.tag_dimensions_qualifier_sql, "__QUALIFIER__", "sg.")} ${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "sg.")} ${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")} from @@ -915,7 +915,7 @@ then sg.title || ' restricts UDP services from internet.' else sg.title || ' allows UDP services from internet.' end as reason - ${local.tag_dimensions_sql} + ${replace(local.tag_dimensions_qualifier_sql, "__QUALIFIER__", "sg.")} ${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "sg.")} ${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")} from diff --git a/regulatory_compliance/postgres.pp b/regulatory_compliance/postgres.pp index 05f5111b..a0aa4608 100644 --- a/regulatory_compliance/postgres.pp +++ b/regulatory_compliance/postgres.pp @@ -234,7 +234,7 @@ when infrastructure_encryption = 'Enabled' then name || ' infrastructure encryption enabled.' else name || ' infrastructure encryption disabled.' end as reason - ${local.tag_dimensions_sql} + ${replace(local.tag_dimensions_qualifier_sql, "__QUALIFIER__", "s.")} ${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "s.")} ${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")} from @@ -365,7 +365,7 @@ when lower(config -> 'ConfigurationProperties' ->> 'value') != 'on' then s.name || ' server parameter log_connections off.' else s.name || ' server parameter log_connections on.' end as reason - ${local.tag_dimensions_sql} + ${replace(local.tag_dimensions_qualifier_sql, "__QUALIFIER__", "s.")} ${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "s.")} ${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")} from @@ -390,7 +390,7 @@ when lower(config -> 'ConfigurationProperties' ->> 'value') != 'on' then name || ' server parameter log_disconnections off.' else name || ' server parameter log_disconnections on.' end as reason - ${local.tag_dimensions_sql} + ${replace(local.tag_dimensions_qualifier_sql, "__QUALIFIER__", "s.")} ${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "s.")} ${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")} from @@ -475,7 +475,7 @@ when a.id is not null then s.title || ' does not restrict access to azure services.' else s.title || ' restricts access to azure services.' end as reason - ${local.tag_dimensions_sql} + ${replace(local.tag_dimensions_qualifier_sql, "__QUALIFIER__", "s.")} ${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "s.")} ${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")} from @@ -509,3 +509,127 @@ sub.subscription_id = s.subscription_id; EOQ } + +query "postgres_sql_flexible_server_ssl_enabled" { + sql = <<-EOQ + with ssl_enabled as( + select + id + from + azure_postgresql_flexible_server, + jsonb_array_elements(flexible_server_configurations) as config + where + config ->> 'Name' = 'require_secure_transport' and config -> 'ConfigurationProperties' ->> 'value' = 'on' + ) + select + s.id as resource, + case + when a.id is not null then 'ok' + else 'alarm' + end as status, + case + when a.id is not null then s.title || ' SSL connection enabled.' + else s.title || ' SSL connection disabled.' + end as reason + ${replace(local.tag_dimensions_qualifier_sql, "__QUALIFIER__", "s.")} + ${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "s.")} + ${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")} + from + azure_postgresql_flexible_server as s + left join ssl_enabled as a on s.id = a.id, + azure_subscription as sub + where + sub.subscription_id = s.subscription_id; + EOQ +} + +query "postgres_flexible_server_log_checkpoints_on" { + sql = <<-EOQ + with log_checkpoints_on as( + select + id + from + azure_postgresql_flexible_server, + jsonb_array_elements(flexible_server_configurations) as config + where + config ->> 'Name' = 'log_checkpoints' and config -> 'ConfigurationProperties' ->> 'value' = 'on' + ) + select + s.id as resource, + case + when a.id is not null then 'ok' + else 'alarm' + end as status, + case + when a.id is not null then s.title || ' server parameter log_checkpoints on.' + else s.title || ' server parameter log_checkpoints off.' + end as reason + ${replace(local.tag_dimensions_qualifier_sql, "__QUALIFIER__", "s.")} + ${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "s.")} + ${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")} + from + azure_postgresql_flexible_server as s + left join log_checkpoints_on as a on s.id = a.id, + azure_subscription as sub + where + sub.subscription_id = s.subscription_id; + EOQ +} + +query "postgres_flexible_server_connection_throttling_on" { + sql = <<-EOQ + with connection_throttling_on as( + select + id + from + azure_postgresql_flexible_server, + jsonb_array_elements(flexible_server_configurations) as config + where + config ->> 'Name' = 'connection_throttle.enable' and config -> 'ConfigurationProperties' ->> 'value' = 'on' + ) + select + s.id as resource, + case + when a.id is not null then 'ok' + else 'alarm' + end as status, + case + when a.id is not null then s.title || ' server parameter connection_throttling on.' + else s.title || ' server parameter connection_throttling off.' + end as reason + ${replace(local.tag_dimensions_qualifier_sql, "__QUALIFIER__", "s.")} + ${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "s.")} + ${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")} + from + azure_postgresql_flexible_server as s + left join connection_throttling_on as a on s.id = a.id, + azure_subscription as sub + where + sub.subscription_id = s.subscription_id; + EOQ +} + +query "postgres_flexible_server_log_retention_days_3" { + sql = <<-EOQ + select + s.id as resource, + case + when (config -> 'ConfigurationProperties' ->> 'value')::integer <= 3 then 'alarm' + else 'ok' + end as status, + case + when (config -> 'ConfigurationProperties' ->> 'value')::integer <= 3 then s.name || ' log files are retained for 3 days or lesser.' + else s.name || ' log files are retained for more than 3 days.' + end as reason + ${replace(local.tag_dimensions_qualifier_sql, "__QUALIFIER__", "s.")} + ${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "s.")} + ${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")} + from + azure_postgresql_flexible_server s, + jsonb_array_elements(flexible_server_configurations) as config, + azure_subscription sub + where + config ->> 'Name' = 'logfiles.retention_days' + and sub.subscription_id = s.subscription_id; + EOQ +} diff --git a/regulatory_compliance/redis.pp b/regulatory_compliance/redis.pp index e2487f55..7a0f7663 100644 --- a/regulatory_compliance/redis.pp +++ b/regulatory_compliance/redis.pp @@ -145,7 +145,7 @@ when c.sku_name = 'Basic' then c.title || ' using basic SKU.' else c.title || ' using ' || sku_name || ' SKU.' end as reason - ${local.tag_dimensions_sql} + ${replace(local.tag_dimensions_qualifier_sql, "__QUALIFIER__", "c.")} ${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "c.")} ${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")} from diff --git a/regulatory_compliance/sql.pp b/regulatory_compliance/sql.pp index b8fb6d98..f9231908 100644 --- a/regulatory_compliance/sql.pp +++ b/regulatory_compliance/sql.pp @@ -293,7 +293,7 @@ when audit -> 'properties' ->> 'state' = 'Disabled' then name || ' auditing disabled.' else name || ' auditing enabled.' end as reason - ${local.tag_dimensions_sql} + ${replace(local.tag_dimensions_qualifier_sql, "__QUALIFIER__", "s.")} ${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "s.")} ${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")} from @@ -349,7 +349,7 @@ when encryption ->> 'kind' = 'servicemanaged' then s.name || ' TDE protector not encrypted with CMK.' else s.name || ' TDE protector encrypted with CMK.' end as reason - ${local.tag_dimensions_sql} + ${replace(local.tag_dimensions_qualifier_sql, "__QUALIFIER__", "s.")} ${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "s.")} ${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")} from @@ -441,7 +441,7 @@ when transparent_data_encryption ->> 'status' = 'Enabled' or transparent_data_encryption ->> 'state' = 'Enabled' then s.title || ' transparent data encryption enabled.' else s.title || ' transparent data encryption disabled.' end as reason - ${local.tag_dimensions_sql} + ${replace(local.tag_dimensions_qualifier_sql, "__QUALIFIER__", "s.")} ${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "s.")} ${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")} from @@ -534,7 +534,7 @@ when public_network_access = 'Enabled' then name || ' public network access enabled.' else name || ' public network access disabled.' end as reason - ${local.tag_dimensions_sql} + ${replace(local.tag_dimensions_qualifier_sql, "__QUALIFIER__", "s.")} ${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "s.")} ${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")} from @@ -637,7 +637,7 @@ then s.title || ' allows ingress 0.0.0.0/0 or any ip over internet.' else s.title || ' not allows ingress 0.0.0.0/0 or any ip over internet.' end as reason - ${local.tag_dimensions_sql} + ${replace(local.tag_dimensions_qualifier_sql, "__QUALIFIER__", "s.")} ${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "s.")} ${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")} from @@ -660,7 +660,7 @@ when server_azure_ad_administrator is null then name || ' Azure AD authentication not configured.' else name || ' Azure AD authentication configured.' end as reason - ${local.tag_dimensions_sql} + ${replace(local.tag_dimensions_qualifier_sql, "__QUALIFIER__", "s.")} ${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "s.")} ${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")} from @@ -709,7 +709,7 @@ when (audit -> 'properties' ->> 'retentionDays')::integer >= 90 then name || ' audit retention greater than 90 days.' else name || ' audit retention less than 90 days.' end as reason - ${local.tag_dimensions_sql} + ${replace(local.tag_dimensions_qualifier_sql, "__QUALIFIER__", "s.")} ${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "s.")} ${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")} from diff --git a/regulatory_compliance/storage.pp b/regulatory_compliance/storage.pp index 7d9750d7..20efe8b4 100644 --- a/regulatory_compliance/storage.pp +++ b/regulatory_compliance/storage.pp @@ -243,7 +243,7 @@ when not enable_https_traffic_only then sa.name || ' encryption in transit not enabled.' else sa.name || ' encryption in transit enabled.' end as reason - ${local.tag_dimensions_sql} + ${replace(local.tag_dimensions_qualifier_sql, "__QUALIFIER__", "sa.")} ${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "sa.")} ${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")} from @@ -266,7 +266,7 @@ when sa.network_rule_default_action = 'Allow' then name || ' allows traffic from all networks.' else name || ' allows traffic from specific networks.' end as reason - ${local.tag_dimensions_sql} + ${replace(local.tag_dimensions_qualifier_sql, "__QUALIFIER__", "sa.")} ${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "sa.")} ${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")} from @@ -336,7 +336,7 @@ when s.id is null then a.name || ' not uses private link.' else a.name || ' uses private link.' end as reason - ${local.tag_dimensions_sql} + ${replace(local.tag_dimensions_qualifier_sql, "__QUALIFIER__", "a.")} ${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "a.")} ${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")} from @@ -360,7 +360,7 @@ when require_infrastructure_encryption then name || ' infrastructure encryption enabled.' else name || ' infrastructure encryption disabled.' end as reason - ${local.tag_dimensions_sql} + ${replace(local.tag_dimensions_qualifier_sql, "__QUALIFIER__", "s.")} ${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "s.")} ${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")} from @@ -383,7 +383,7 @@ when lower(sa.public_network_access) = 'disabled' then sa.name || ' not publicy accessible.' else sa.name || ' publicy accessible.' end as reason - ${local.tag_dimensions_sql} + ${replace(local.tag_dimensions_qualifier_sql, "__QUALIFIER__", "sa.")} ${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "sa.")} ${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")} from @@ -452,7 +452,7 @@ when sa.encryption_key_source = 'Microsoft.Storage' then sa.name || ' not encrypted with CMK.' else sa.name || ' encrypted with CMK.' end as reason - ${local.tag_dimensions_sql} + ${replace(local.tag_dimensions_qualifier_sql, "__QUALIFIER__", "sa.")} ${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "sa.")} ${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")} from @@ -534,7 +534,7 @@ then account.name || ' container ' || container.name || ' doesn''t allow anonymous access.' else account.name || ' container ' || container.name || ' allows anonymous access.' end as reason - ${local.tag_dimensions_sql} + ${replace(local.tag_dimensions_qualifier_sql, "__QUALIFIER__", "account.")} ${replace(local.common_dimensions_global_qualifier_sql, "__QUALIFIER__", "container.")} ${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")} from @@ -565,7 +565,7 @@ ) || ' requests.' else name || ' blob service logging enabled for read, write, delete requests.' end as reason - ${local.tag_dimensions_sql} + ${replace(local.tag_dimensions_qualifier_sql, "__QUALIFIER__", "sa.")} ${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "sa.")} ${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")} from @@ -594,7 +594,7 @@ case when not table_logging_delete then 'delete' end ) || ' requests.' end as reason - ${local.tag_dimensions_sql} + ${replace(local.tag_dimensions_qualifier_sql, "__QUALIFIER__", "sa.")} ${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "sa.")} ${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")} from @@ -619,7 +619,7 @@ when minimum_tls_version = 'TLS1_2' then sa.name || ' minimum TLS version set to ' || minimum_tls_version || '.' else sa.name || ' minimum TLS version set to ' || minimum_tls_version || '.' end as reason - ${local.tag_dimensions_sql} + ${replace(local.tag_dimensions_qualifier_sql, "__QUALIFIER__", "sa.")} ${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "sa.")} ${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")} from @@ -648,7 +648,7 @@ case when not queue_logging_delete then 'delete' end ) || ' requests.' end as reason - ${local.tag_dimensions_sql} + ${replace(local.tag_dimensions_qualifier_sql, "__QUALIFIER__", "sa.")} ${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "sa.")} ${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")} from @@ -671,7 +671,7 @@ when not blob_soft_delete_enabled then sa.name || ' blobs soft delete disabled.' else sa.name || ' blobs soft delete enabled.' end as reason - ${local.tag_dimensions_sql} + ${replace(local.tag_dimensions_qualifier_sql, "__QUALIFIER__", "sa.")} ${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "sa.")} ${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")} from @@ -694,7 +694,7 @@ when network_rule_bypass not like '%AzureServices%' then sa.name || ' trusted Microsoft services not enabled.' else sa.name || ' trusted Microsoft services enabled.' end as reason - ${local.tag_dimensions_sql} + ${replace(local.tag_dimensions_qualifier_sql, "__QUALIFIER__", "sa.")} ${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "sa.")} ${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")} from