Skip to content

Commit

Permalink
Implement CIS Azure 7.4 (elastic#311)
Browse files Browse the repository at this point in the history
Ensure disks are encrypted either with Customer
Managed Key (CMK) or both Platform and Customer Managed Key.
  • Loading branch information
orestisfl authored Oct 2, 2023
1 parent 7bc93d9 commit 5a838cb
Show file tree
Hide file tree
Showing 7 changed files with 197 additions and 6 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
[![CIS EKS](https://img.shields.io/badge/CIS-Amazon%20EKS%20(60%25)-FF9900?logo=Amazon+EKS)](RULES.md#eks-cis-benchmark)
[![CIS AWS](https://img.shields.io/badge/CIS-AWS%20(87%25)-232F3E?logo=Amazon+AWS)](RULES.md#aws-cis-benchmark)
[![CIS GCP](https://img.shields.io/badge/CIS-GCP%20(85%25)-4285F4?logo=Google+Cloud)](RULES.md#gcp-cis-benchmark)
[![CIS AZURE](https://img.shields.io/badge/CIS-AZURE%20(4%25)-F00EE8?logo=Microsoft+Azure)](RULES.md#azure-cis-benchmark)
[![CIS AZURE](https://img.shields.io/badge/CIS-AZURE%20(5%25)-F00EE8?logo=Microsoft+Azure)](RULES.md#azure-cis-benchmark)

![Coverage Badge](https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/oren-zohar/a7160df46e48dff45b24096de9302d38/raw/csp-security-policies_coverage.json)

Expand Down
6 changes: 3 additions & 3 deletions RULES.md
Original file line number Diff line number Diff line change
Expand Up @@ -370,9 +370,9 @@

## AZURE CIS Benchmark

### 6/151 implemented rules (4%)
### 7/151 implemented rules (5%)

#### Automated rules: 6/77 (8%)
#### Automated rules: 7/77 (9%)

#### Manual rules: 0/74 (0%)

Expand Down Expand Up @@ -506,7 +506,7 @@
| 7.1 | Virtual Machines | Ensure an Azure Bastion Host Exists | :x: | Automated |
| 7.2 | Virtual Machines | Ensure Virtual Machines are utilizing Managed Disks | :x: | Automated |
| 7.3 | Virtual Machines | Ensure that 'OS and Data' disks are encrypted with Customer Managed Key (CMK) | :x: | Automated |
| 7.4 | Virtual Machines | Ensure that 'Unattached disks' are encrypted with 'Customer Managed Key' (CMK) | :x: | Automated |
| [7.4](bundle/compliance/cis_azure/rules/cis_7_4) | Virtual Machines | Ensure that 'Unattached disks' are encrypted with 'Customer Managed Key' (CMK) | :white_check_mark: | Automated |
| 7.5 | Virtual Machines | Ensure that Only Approved Extensions Are Installed | :x: | Manual |
| 7.6 | Virtual Machines | Ensure that Endpoint Protection for all Virtual Machines is installed | :x: | Manual |
| 7.7 | Virtual Machines | [Legacy] Ensure that VHDs are Encrypted | :x: | Manual |
Expand Down
82 changes: 82 additions & 0 deletions bundle/compliance/cis_azure/rules/cis_7_4/data.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
metadata:
id: 02ca1a3a-559e-53d7-afcd-8e3774c4efb9
name: Ensure that 'Unattached disks' are encrypted with 'Customer Managed Key' (CMK)
profile_applicability: '* Level 2'
description: Ensure that unattached disks in a subscription are encrypted with a
Customer Managed Key (CMK).
rationale: |-
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.
audit: |-
**From Azure Portal**
1. Go to `Disks`
2. Click on `Add Filter`
3. In the `filter` field select `Disk state`
4. In the `Value` field select `Unattached`
5. Click `Apply`
6. for each disk listed ensure that `Encryption type` in the `encryption` blade is `Encryption at-rest with a customer-managed key'
**From Azure CLI**
Ensure command below does not return any output.
```
az disk list --query '[? diskstate == `Unattached`].{encryptionSettings: encryptionSettings, name: name}' -o json
```
Sample Output:
```
[
{
"encryptionSettings": null,
"name": "<Disk1>"
},
{
"encryptionSettings": null,
"name": "<Disk2>"
}
]
```
remediation: |-
If data stored in the disk is no longer useful, refer to Azure documentation to delete unattached data disks at:
```
-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 azure documentation at:
```
-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
```
impact: |-
**NOTE:** You must have your key vault set up to utilize this.
Encryption is available only on Standard tier VMs. This might cost you more.
Utilizing and maintaining Customer-managed keys will require additional work to create, protect, and rotate keys.
default_value: ''
references: |-
1. https://docs.microsoft.com/en-us/azure/security/fundamentals/azure-disk-encryption-vms-vmss
2. https://docs.microsoft.com/en-us/azure/security-center/security-center-disk-encryption?toc=%2fazure%2fsecurity%2ftoc.json
3. https://docs.microsoft.com/en-us/rest/api/compute/disks/delete
4. https://docs.microsoft.com/en-us/cli/azure/disk?view=azure-cli-latest#az-disk-delete
5. https://docs.microsoft.com/en-us/rest/api/compute/disks/update#encryptionsettings
6. https://docs.microsoft.com/en-us/cli/azure/disk?view=azure-cli-latest#az-disk-update
7. https://docs.microsoft.com/en-us/security/benchmark/azure/security-controls-v3-data-protection#dp-5-encrypt-sensitive-data-at-rest
section: Virtual Machines
version: '1.0'
tags:
- CIS
- AZURE
- CIS 7.4
- Virtual Machines
benchmark:
name: CIS Microsoft Azure Foundations
version: v2.0.0
id: cis_azure
rule_number: '7.4'
posture_type: cspm
16 changes: 16 additions & 0 deletions bundle/compliance/cis_azure/rules/cis_7_4/rule.rego
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package compliance.cis_azure.rules.cis_7_4

import data.compliance.lib.common
import data.compliance.policy.azure.data_adapter
import data.compliance.policy.azure.disk.ensure_encryption as audit

finding = result {
# filter
data_adapter.is_unattached_disk

# set result
result := common.generate_result_without_expected(
common.calculate_result(audit.is_encryption_enabled),
{"Resource": data_adapter.resource},
)
}
71 changes: 71 additions & 0 deletions bundle/compliance/cis_azure/rules/cis_7_4/test.rego
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package compliance.cis_azure.rules.cis_7_4

import data.compliance.policy.azure.data_adapter
import data.lib.test

generate_encryption_settings(type) = {
"diskEncryptionSetId": "/subscriptions/dead-beef/resourceGroups/RESOURCEGROUP/providers/Microsoft.Compute/diskEncryptionSets/double-disk-encryption-set",
"type": type,
}

generate_unattached_disk_with_encryption(settings) = generate_disk_with_encryption("Unattached", settings)

generate_disk_with_encryption(state, settings) = {
"type": "azure-disk",
"subType": "",
"resource": {
"id": "/subscriptions/dead-beef/resourceGroups/resourceGroup/providers/Microsoft.Compute/disks/unattached-disk",
"location": "eastus",
"name": "unattached-disk",
"properties": {
"creationData": {"createOption": "Empty"},
"dataAccessAuthMode": "None",
"diskIOPSReadWrite": 500,
"diskMBpsReadWrite": 60,
"diskSizeBytes": 4294967296,
"diskSizeGB": 4,
"diskState": state,
"encryption": settings,
"networkAccessPolicy": "DenyAll",
"provisioningState": "Succeeded",
"publicNetworkAccess": "Disabled",
"timeCreated": "2023-09-28T19:05:41.631Z",
"uniqueId": "12345-abcdef",
},
"resource_group": "resourceGroup",
"subscription_id": "dead-beef",
"tenant_id": "beef-dead",
"type": "microsoft.compute/disks",
},
}

test_violation {
eval_fail with input as generate_unattached_disk_with_encryption(null)
eval_fail with input as generate_unattached_disk_with_encryption({"data": "in", "unknown": "format"})
eval_fail with input as generate_unattached_disk_with_encryption(generate_encryption_settings("EncryptionAtRestWithPlatformKey"))
eval_fail with input as generate_unattached_disk_with_encryption(generate_encryption_settings("InvalidValue"))
}

test_pass {
eval_pass with input as generate_unattached_disk_with_encryption(generate_encryption_settings("EncryptionAtRestWithCustomerKey"))
eval_pass with input as generate_unattached_disk_with_encryption(generate_encryption_settings("EncryptionAtRestWithPlatformAndCustomerKeys"))
}

test_not_evaluated {
not_eval with input as {}
not_eval with input as {"type": "other-type", "resource": {"encryption": {}}}
not_eval with input as generate_disk_with_encryption("Attached", generate_encryption_settings("EncryptionAtRestWithPlatformAndCustomerKeys"))
not_eval with input as generate_disk_with_encryption("OtherState", generate_encryption_settings("EncryptionAtRestWithPlatformAndCustomerKeys"))
}

eval_fail {
test.assert_fail(finding) with data.benchmark_data_adapter as data_adapter
}

eval_pass {
test.assert_pass(finding) with data.benchmark_data_adapter as data_adapter
}

not_eval {
not finding with data.benchmark_data_adapter as data_adapter
}
11 changes: 9 additions & 2 deletions bundle/compliance/policy/azure/data_adapter.rego
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
package compliance.policy.azure.data_adapter

# import data.compliance.lib.common

resource = input.resource

properties = resource.properties

is_disk {
input.type == "azure-disk"
}

is_unattached_disk {
is_disk
properties.diskState == "Unattached"
}

private_endpoint_connections = properties.privateEndpointConnections

network_acls = properties.networkAcls
Expand Down
15 changes: 15 additions & 0 deletions bundle/compliance/policy/azure/disk/ensure_encryption.rego
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package compliance.policy.azure.disk.ensure_encryption

import data.compliance.policy.azure.data_adapter

encryption_type = data_adapter.properties.encryption.type

default is_encryption_enabled = false

is_encryption_enabled {
encryption_type == "EncryptionAtRestWithCustomerKey"
}

is_encryption_enabled {
encryption_type == "EncryptionAtRestWithPlatformAndCustomerKeys"
}

0 comments on commit 5a838cb

Please sign in to comment.