# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.

# E2E Test: Compute/ManagedDiskEncryptionSetsAllowed_Deny
# Real Azure Policy: "Managed disks should use a specific set of disk encryption sets for the customer-managed key encryption"
# Features: anyOf, allOf nesting, field (type + alias), exists, notIn, in,
#   length(), count, not, multiple resource types
#   (VM, VMSS, disks, images, galleries/images/versions)

aliases: test_aliases.json

policy_definition: |
  {
    "properties": {
      "displayName": "Managed disks should use a specific set of disk encryption sets for the customer-managed key encryption",
      "policyType": "BuiltIn",
      "mode": "Indexed",
      "description": "Requiring a specific set of disk encryption sets to be used with managed disks give you control over the keys used for encryption at rest. You are able to select the allowed encrypted sets and all others are rejected when attached to a disk. Learn more at https://aka.ms/disks-cmk.",
      "metadata": {
        "category": "Compute",
        "version": "2.0.0"
      },
      "version": "2.0.0",
      "parameters": {
        "allowedEncryptionSets": {
          "type": "Array",
          "metadata": {
            "displayName": "Allowed disk encryption set",
            "description": "The list of allowed disk encryption sets for managed disks.",
            "strongType": "Microsoft.Compute/diskEncryptionSets"
          }
        },
        "effect": {
          "type": "string",
          "defaultValue": "Audit",
          "allowedValues": [
            "Audit",
            "Deny",
            "Disabled"
          ],
          "metadata": {
            "displayName": "Effect",
            "description": "Enable or disable the execution of the policy"
          }
        }
      },
      "policyRule": {
        "if": {
          "anyOf": [
            {
              "allOf": [
                {
                  "field": "type",
                  "equals": "Microsoft.Compute/disks"
                },
                {
                  "field": "Microsoft.Compute/disks/managedBy",
                  "exists": "False"
                },
                {
                  "field": "Microsoft.Compute/disks/encryption.diskEncryptionSetId",
                  "notIn": "[parameters('allowedEncryptionSets')]"
                }
              ]
            },
            {
              "allOf": [
                {
                  "field": "type",
                  "equals": "Microsoft.Compute/virtualMachines"
                },
                {
                  "field": "Microsoft.Compute/virtualMachines/storageProfile.osDisk.managedDisk.diskEncryptionSet.id",
                  "notIn": "[parameters('allowedEncryptionSets')]"
                }
              ]
            },
            {
              "allOf": [
                {
                  "field": "type",
                  "equals": "Microsoft.Compute/virtualMachineScaleSets"
                },
                {
                  "field": "Microsoft.Compute/virtualMachineScaleSets/virtualMachineProfile.storageProfile.osDisk.managedDisk.diskEncryptionSet.id",
                  "notIn": "[parameters('allowedEncryptionSets')]"
                }
              ]
            },
            {
              "allOf": [
                {
                  "field": "type",
                  "equals": "Microsoft.Compute/virtualMachineScaleSets"
                },
                {
                  "count": {
                    "field": "Microsoft.Compute/virtualMachineScaleSets/virtualMachineProfile.storageProfile.dataDisks[*]"
                  },
                  "greater": 0
                },
                {
                  "not": {
                    "field": "Microsoft.Compute/virtualMachineScaleSets/virtualMachineProfile.storageProfile.dataDisks[*].managedDisk.diskEncryptionSet.id",
                    "in": "[parameters('allowedEncryptionSets')]"
                  }
                }
              ]
            },
            {
              "allOf": [
                {
                  "field": "type",
                  "equals": "Microsoft.Compute/galleries/images/versions"
                },
                {
                  "not": {
                    "field": "Microsoft.Compute/galleries/images/versions/publishingProfile.targetRegions[*].encryption.osDiskImage.diskEncryptionSetId",
                    "in": "[parameters('allowedEncryptionSets')]"
                  }
                }
              ]
            },
            {
              "allOf": [
                {
                  "field": "type",
                  "equals": "Microsoft.Compute/galleries/images/versions"
                },
                {
                  "value": "[length(field('Microsoft.Compute/galleries/images/versions/storageProfile.dataDiskImages[*]'))]",
                  "greater": 0
                },
                {
                  "not": {
                    "field": "Microsoft.Compute/galleries/images/versions/publishingProfile.targetRegions[*].encryption.dataDiskImages[*].diskEncryptionSetId",
                    "in": "[parameters('allowedEncryptionSets')]"
                  }
                }
              ]
            },
            {
              "allOf": [
                {
                  "field": "type",
                  "equals": "Microsoft.Compute/images"
                },
                {
                  "field": "Microsoft.Compute/images/storageProfile.osDisk.diskEncryptionSet.id",
                  "notIn": "[parameters('allowedEncryptionSets')]"
                }
              ]
            },
            {
              "allOf": [
                {
                  "field": "type",
                  "equals": "Microsoft.Compute/images"
                },
                {
                  "value": "[length(field('Microsoft.Compute/images/storageProfile.dataDisks[*]'))]",
                  "greater": 0
                },
                {
                  "field": "Microsoft.Compute/images/storageProfile.dataDisks[*].diskEncryptionSet.id",
                  "notIn": "[parameters('allowedEncryptionSets')]"
                }
              ]
            }
          ]
        },
        "then": {
          "effect": "[parameters('effect')]"
        }
      },
      "versions": [
        "2.0.0"
      ]
    },
    "id": "/providers/Microsoft.Authorization/policyDefinitions/d461a302-a187-421a-89ac-84acdb4edc04",
    "name": "d461a302-a187-421a-89ac-84acdb4edc04"
  }

cases:
  # =========================================================================
  # 1. VM with OS disk DES in allowed list → pass
  # =========================================================================

  - note: pass_vm_osdisk_in_allowed
    parameters:
      effect: "Deny"
      allowedEncryptionSets:
        - "/subscriptions/sub1/resourceGroups/rg1/providers/Microsoft.Compute/diskEncryptionSets/des1"
        - "/subscriptions/sub1/resourceGroups/rg1/providers/Microsoft.Compute/diskEncryptionSets/des2"
    resource:
      type: "Microsoft.Compute/virtualMachines"
      name: "test-vm"
      properties:
        storageProfile:
          osDisk:
            managedDisk:
              diskEncryptionSet:
                id: "/subscriptions/sub1/resourceGroups/rg1/providers/Microsoft.Compute/diskEncryptionSets/des1"
    want_undefined: true

  # =========================================================================
  # 2. VM with OS disk DES NOT in allowed list → Deny
  # =========================================================================

  - note: deny_vm_osdisk_not_in_allowed
    parameters:
      effect: "Deny"
      allowedEncryptionSets:
        - "/subscriptions/sub1/resourceGroups/rg1/providers/Microsoft.Compute/diskEncryptionSets/des1"
        - "/subscriptions/sub1/resourceGroups/rg1/providers/Microsoft.Compute/diskEncryptionSets/des2"
    resource:
      type: "Microsoft.Compute/virtualMachines"
      name: "test-vm-bad"
      properties:
        storageProfile:
          osDisk:
            managedDisk:
              diskEncryptionSet:
                id: "/subscriptions/sub1/resourceGroups/rg1/providers/Microsoft.Compute/diskEncryptionSets/des-other"
    want_effect: "Deny"

  # =========================================================================
  # 3. Managed disk with allowed DES → pass
  # =========================================================================

  - note: pass_disk_in_allowed
    parameters:
      effect: "Deny"
      allowedEncryptionSets:
        - "/subscriptions/sub1/resourceGroups/rg1/providers/Microsoft.Compute/diskEncryptionSets/des1"
        - "/subscriptions/sub1/resourceGroups/rg1/providers/Microsoft.Compute/diskEncryptionSets/des2"
    resource:
      type: "Microsoft.Compute/disks"
      name: "test-disk-allowed"
      properties:
        diskSizeGB: 128
        encryption:
          diskEncryptionSetId: "/subscriptions/sub1/resourceGroups/rg1/providers/Microsoft.Compute/diskEncryptionSets/des1"
          type: "EncryptionAtRestWithCustomerKey"
    want_undefined: true

  # =========================================================================
  # 4. Managed disk with disallowed DES → Deny
  # =========================================================================

  - note: deny_disk_not_in_allowed
    parameters:
      effect: "Deny"
      allowedEncryptionSets:
        - "/subscriptions/sub1/resourceGroups/rg1/providers/Microsoft.Compute/diskEncryptionSets/des1"
        - "/subscriptions/sub1/resourceGroups/rg1/providers/Microsoft.Compute/diskEncryptionSets/des2"
    resource:
      type: "Microsoft.Compute/disks"
      name: "test-disk-bad"
      properties:
        diskSizeGB: 128
        encryption:
          diskEncryptionSetId: "/subscriptions/sub1/resourceGroups/rg1/providers/Microsoft.Compute/diskEncryptionSets/des-other"
          type: "EncryptionAtRestWithCustomerKey"
    want_effect: "Deny"

  # =========================================================================
  # 5. Disk without managedBy (unmanaged) with disallowed DES → Deny
  #    (managedBy does not exist, so the disk clause fires)
  #    But if the DES is in the allowed list, it passes.
  #    Here we test: disk without managedBy but WITH managedBy present → pass
  #    (the disk clause requires managedBy exists=False)
  # =========================================================================

  - note: pass_disk_unmanaged
    parameters:
      effect: "Deny"
      allowedEncryptionSets:
        - "/subscriptions/sub1/resourceGroups/rg1/providers/Microsoft.Compute/diskEncryptionSets/des1"
    resource:
      type: "Microsoft.Compute/disks"
      name: "test-disk-managed-by-vm"
      properties:
        managedBy: "/subscriptions/sub1/resourceGroups/rg1/providers/Microsoft.Compute/virtualMachines/myVM"
        diskSizeGB: 128
        encryption:
          diskEncryptionSetId: "/subscriptions/sub1/resourceGroups/rg1/providers/Microsoft.Compute/diskEncryptionSets/des-other"
          type: "EncryptionAtRestWithCustomerKey"
    want_undefined: true

  # =========================================================================
  # 6. Wrong resource type → pass
  # =========================================================================

  - note: pass_wrong_type
    parameters:
      effect: "Deny"
      allowedEncryptionSets:
        - "/subscriptions/sub1/resourceGroups/rg1/providers/Microsoft.Compute/diskEncryptionSets/des1"
    resource:
      type: "Microsoft.Storage/storageAccounts"
      name: "myStorage"
      properties: {}
    want_undefined: true

  # =========================================================================
  # 7. Image with OS disk DES not in allowed list → Deny
  # =========================================================================

  - note: deny_image_osdisk_not_allowed
    parameters:
      effect: "Deny"
      allowedEncryptionSets:
        - "/subscriptions/sub1/resourceGroups/rg1/providers/Microsoft.Compute/diskEncryptionSets/des1"
        - "/subscriptions/sub1/resourceGroups/rg1/providers/Microsoft.Compute/diskEncryptionSets/des2"
    resource:
      type: "Microsoft.Compute/images"
      name: "test-image-bad"
      properties:
        storageProfile:
          osDisk:
            osType: "Linux"
            osState: "Generalized"
            diskEncryptionSet:
              id: "/subscriptions/sub1/resourceGroups/rg1/providers/Microsoft.Compute/diskEncryptionSets/des-other"
    want_effect: "Deny"
