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

# E2E Test: Cosmos DB/Cosmos_MaxThroughput_Deny
# Real Azure Policy: "Azure Cosmos DB throughput should be limited"
# Source: regolator/policyDefinitions/Cosmos DB/Cosmos_MaxThroughput_Deny.json
#
# Features exercised:
#   - allOf with nested anyOf (type check + condition check)
#   - type "like" pattern matching (*/throughputSettings)
#   - type "in" with 9 resource types
#   - Template expressions: if(), equals(), int(), field()
#   - containsKey operator
#   - exists operator
#   - greater operator with parameterized threshold
#   - Parameters: throughputMax (Integer), effect (String)

aliases: test_aliases.json

policy_definition: |
  {
    "properties": {
      "displayName": "Azure Cosmos DB throughput should be limited",
      "policyType": "BuiltIn",
      "mode": "All",
      "description": "This policy enables you to restrict the maximum throughput your organization can specify when creating Azure Cosmos DB databases and containers through the resource provider. It blocks the creation of autoscale resources.",
      "metadata": {
        "version": "1.1.0",
        "category": "Cosmos DB"
      },
      "version": "1.1.0",
      "parameters": {
        "throughputMax": {
          "type": "Integer",
          "metadata": {
            "displayName": "Max RUs",
            "description": "The maximum throughput (RU/s) that can be assigned to a container via the Resource Provider during create or update."
          }
        },
        "effect": {
          "type": "String",
          "metadata": {
            "displayName": "Policy Effect",
            "description": "The desired effect of the policy."
          },
          "allowedValues": [
            "audit",
            "Audit",
            "deny",
            "Deny",
            "disabled",
            "Disabled"
          ],
          "defaultValue": "Deny"
        }
      },
      "policyRule": {
        "if": {
          "allOf": [
            {
              "anyOf": [
                {
                  "field": "type",
                  "like": "Microsoft.DocumentDB/databaseAccounts/*/throughputSettings"
                },
                {
                  "field": "type",
                  "in": [
                    "Microsoft.DocumentDB/databaseAccounts/sqlDatabases",
                    "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers",
                    "Microsoft.DocumentDB/databaseAccounts/mongodbDatabases",
                    "Microsoft.DocumentDB/databaseAccounts/mongodbDatabases/collections",
                    "Microsoft.DocumentDB/databaseAccounts/gremlinDatabases",
                    "Microsoft.DocumentDB/databaseAccounts/gremlinDatabases/graphs",
                    "Microsoft.DocumentDB/databaseAccounts/cassandraKeyspaces",
                    "Microsoft.DocumentDB/databaseAccounts/cassandraKeyspaces/tables",
                    "Microsoft.DocumentDB/databaseAccounts/tables"
                  ]
                }
              ]
            },
            {
              "anyOf": [
                {
                  "value": "[requestContext().apiVersion]",
                  "less": "2019-08-01"
                },
                {
                  "value": "[if(equals(field('Microsoft.DocumentDB/databaseAccounts/sqlDatabases/options.throughput'), ''), 0, int(field('Microsoft.DocumentDB/databaseAccounts/sqlDatabases/options.throughput')))]",
                  "greater": "[parameters('throughputMax')]"
                },
                {
                  "field": "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/options",
                  "containsKey": "ProvisionedThroughputSettings"
                },
                {
                  "field": "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/throughputSettings/default.resource.throughput",
                  "greater": "[parameters('throughputMax')]"
                },
                {
                  "field": "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/throughputSettings/default.resource.provisionedThroughputSettings",
                  "exists": "true"
                },
                {
                  "value": "[if(equals(field('Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/options.throughput'), ''), 0, int(field('Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/options.throughput')))]",
                  "greater": "[parameters('throughputMax')]"
                },
                {
                  "field": "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/options",
                  "containsKey": "ProvisionedThroughputSettings"
                },
                {
                  "field": "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/throughputSettings/default.resource.throughput",
                  "greater": "[parameters('throughputMax')]"
                },
                {
                  "field": "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/throughputSettings/default.resource.provisionedThroughputSettings",
                  "exists": "true"
                },
                {
                  "value": "[if(equals(field('Microsoft.DocumentDB/databaseAccounts/cassandraKeyspaces/options.throughput'), ''), 0, int(field('Microsoft.DocumentDB/databaseAccounts/cassandraKeyspaces/options.throughput')))]",
                  "greater": "[parameters('throughputMax')]"
                },
                {
                  "field": "Microsoft.DocumentDB/databaseAccounts/cassandraKeyspaces/options",
                  "containsKey": "ProvisionedThroughputSettings"
                },
                {
                  "field": "Microsoft.DocumentDB/databaseAccounts/cassandraKeyspaces/throughputSettings/default.resource.throughput",
                  "greater": "[parameters('throughputMax')]"
                },
                {
                  "field": "Microsoft.DocumentDB/databaseAccounts/cassandraKeyspaces/throughputSettings/default.resource.provisionedThroughputSettings",
                  "exists": "true"
                },
                {
                  "value": "[if(equals(field('Microsoft.DocumentDB/databaseAccounts/cassandraKeyspaces/tables/options.throughput'), ''), 0, int(field('Microsoft.DocumentDB/databaseAccounts/cassandraKeyspaces/tables/options.throughput')))]",
                  "greater": "[parameters('throughputMax')]"
                },
                {
                  "field": "Microsoft.DocumentDB/databaseAccounts/cassandraKeyspaces/tables/options",
                  "containsKey": "ProvisionedThroughputSettings"
                },
                {
                  "field": "Microsoft.DocumentDB/databaseAccounts/cassandraKeyspaces/tables/throughputSettings/default.resource.throughput",
                  "greater": "[parameters('throughputMax')]"
                },
                {
                  "field": "Microsoft.DocumentDB/databaseAccounts/cassandraKeyspaces/tables/throughputSettings/default.resource.provisionedThroughputSettings",
                  "exists": "true"
                },
                {
                  "value": "[if(equals(field('Microsoft.DocumentDB/databaseAccounts/gremlinDatabases/options.throughput'), ''), 0, int(field('Microsoft.DocumentDB/databaseAccounts/gremlinDatabases/options.throughput')))]",
                  "greater": "[parameters('throughputMax')]"
                },
                {
                  "field": "Microsoft.DocumentDB/databaseAccounts/gremlinDatabases/options",
                  "containsKey": "ProvisionedThroughputSettings"
                },
                {
                  "field": "Microsoft.DocumentDB/databaseAccounts/gremlinDatabases/throughputSettings/default.resource.throughput",
                  "greater": "[parameters('throughputMax')]"
                },
                {
                  "field": "Microsoft.DocumentDB/databaseAccounts/gremlinDatabases/throughputSettings/default.resource.provisionedThroughputSettings",
                  "exists": "true"
                },
                {
                  "value": "[if(equals(field('Microsoft.DocumentDB/databaseAccounts/gremlinDatabases/graphs/options.throughput'), ''), 0, int(field('Microsoft.DocumentDB/databaseAccounts/gremlinDatabases/graphs/options.throughput')))]",
                  "greater": "[parameters('throughputMax')]"
                },
                {
                  "field": "Microsoft.DocumentDB/databaseAccounts/gremlinDatabases/graphs/options",
                  "containsKey": "ProvisionedThroughputSettings"
                },
                {
                  "field": "Microsoft.DocumentDB/databaseAccounts/gremlinDatabases/graphs/throughputSettings/default.resource.throughput",
                  "greater": "[parameters('throughputMax')]"
                },
                {
                  "field": "Microsoft.DocumentDB/databaseAccounts/gremlinDatabases/graphs/throughputSettings/default.resource.provisionedThroughputSettings",
                  "exists": "true"
                },
                {
                  "value": "[if(equals(field('Microsoft.DocumentDB/databaseAccounts/mongodbDatabases/options.throughput'), ''), 0, int(field('Microsoft.DocumentDB/databaseAccounts/mongodbDatabases/options.throughput')))]",
                  "greater": "[parameters('throughputMax')]"
                },
                {
                  "field": "Microsoft.DocumentDB/databaseAccounts/mongodbDatabases/options",
                  "containsKey": "ProvisionedThroughputSettings"
                },
                {
                  "field": "Microsoft.DocumentDB/databaseAccounts/mongodbDatabases/throughputSettings/default.resource.throughput",
                  "greater": "[parameters('throughputMax')]"
                },
                {
                  "field": "Microsoft.DocumentDB/databaseAccounts/mongodbDatabases/throughputSettings/default.resource.provisionedThroughputSettings",
                  "exists": "true"
                },
                {
                  "value": "[if(equals(field('Microsoft.DocumentDB/databaseAccounts/mongodbDatabases/collections/options.throughput'), ''), 0, int(field('Microsoft.DocumentDB/databaseAccounts/mongodbDatabases/collections/options.throughput')))]",
                  "greater": "[parameters('throughputMax')]"
                },
                {
                  "field": "Microsoft.DocumentDB/databaseAccounts/mongodbDatabases/collections/options",
                  "containsKey": "ProvisionedThroughputSettings"
                },
                {
                  "field": "Microsoft.DocumentDB/databaseAccounts/mongodbDatabases/collections/throughputSettings/default.resource.throughput",
                  "greater": "[parameters('throughputMax')]"
                },
                {
                  "field": "Microsoft.DocumentDB/databaseAccounts/mongodbDatabases/collections/throughputSettings/default.resource.provisionedThroughputSettings",
                  "exists": "true"
                },
                {
                  "value": "[if(equals(field('Microsoft.DocumentDB/databaseAccounts/tables/options.throughput'), ''), 0, int(field('Microsoft.DocumentDB/databaseAccounts/tables/options.throughput')))]",
                  "greater": "[parameters('throughputMax')]"
                },
                {
                  "field": "Microsoft.DocumentDB/databaseAccounts/tables/options",
                  "containsKey": "ProvisionedThroughputSettings"
                },
                {
                  "field": "Microsoft.DocumentDB/databaseAccounts/tables/throughputSettings/default.resource.throughput",
                  "greater": "[parameters('throughputMax')]"
                },
                {
                  "field": "Microsoft.DocumentDB/databaseAccounts/tables/throughputSettings/default.resource.provisionedThroughputSettings",
                  "exists": "true"
                }
              ]
            }
          ]
        },
        "then": {
          "effect": "[parameters('effect')]"
        }
      },
      "versions": [
        "1.1.0"
      ]
    },
    "id": "/providers/Microsoft.Authorization/policyDefinitions/0b7ef78e-a035-4f23-b9bd-aff122a1b1cf",
    "name": "0b7ef78e-a035-4f23-b9bd-aff122a1b1cf"
  }

cases:
  # =========================================================================
  # SQL Database: options.throughput exceeds max → Deny
  # =========================================================================

  - note: deny_sql_db_throughput_exceeds_max
    parameters:
      throughputMax: 400
    resource:
      type: "Microsoft.DocumentDB/databaseAccounts/sqlDatabases"
      name: "test-db"
      properties:
        options:
          throughput: "600"
    want_effect: "Deny"

  # =========================================================================
  # SQL Database: options.throughput within max → pass
  # =========================================================================

  - note: pass_sql_db_throughput_within_max
    parameters:
      throughputMax: 400
    resource:
      type: "Microsoft.DocumentDB/databaseAccounts/sqlDatabases"
      name: "test-db-ok"
      properties:
        options:
          throughput: "200"
    want_undefined: true

  # =========================================================================
  # SQL Database: autoscale (ProvisionedThroughputSettings key) → Deny
  # =========================================================================

  - note: deny_sql_db_autoscale
    parameters:
      throughputMax: 400
    resource:
      type: "Microsoft.DocumentDB/databaseAccounts/sqlDatabases"
      name: "test-db-autoscale"
      properties:
        options:
          ProvisionedThroughputSettings:
            maxThroughput: 4000
    want_effect: "Deny"

  # =========================================================================
  # Container: options.throughput exceeds max → Deny
  # =========================================================================

  - note: deny_container_throughput_exceeds_max
    parameters:
      throughputMax: 400
    resource:
      type: "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers"
      name: "test-container"
      properties:
        options:
          throughput: "600"
    want_effect: "Deny"

  # =========================================================================
  # Wrong type (parent databaseAccounts, not a sub-resource) → pass
  # =========================================================================

  - note: pass_wrong_type
    parameters:
      throughputMax: 400
    resource:
      type: "Microsoft.DocumentDB/databaseAccounts"
      name: "test-account"
      properties: {}
    want_undefined: true

  # =========================================================================
  # MongoDB: throughputSettings throughput exceeds max → Deny
  # =========================================================================

  - note: deny_mongodb_throughput_settings
    parameters:
      throughputMax: 400
    resource:
      type: "Microsoft.DocumentDB/databaseAccounts/mongodbDatabases"
      name: "test-mongo"
      properties:
        "default":
          resource:
            throughput: 600
    want_effect: "Deny"

  # =========================================================================
  # Tables: throughputSettings autoscale (provisionedThroughputSettings) → Deny
  # =========================================================================

  - note: deny_table_autoscale
    parameters:
      throughputMax: 400
    resource:
      type: "Microsoft.DocumentDB/databaseAccounts/tables"
      name: "test-table"
      properties:
        "default":
          resource:
            provisionedThroughputSettings:
              maxThroughput: 4000
    want_effect: "Deny"

  # =========================================================================
  # Container: empty options.throughput → evaluates to 0 → pass
  # =========================================================================

  - note: pass_container_no_throughput
    parameters:
      throughputMax: 400
    resource:
      type: "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers"
      name: "test-container-empty"
      properties:
        options:
          throughput: ""
    want_undefined: true

  # =========================================================================
  # Cassandra Keyspace: options.throughput exceeds max → Deny
  # =========================================================================

  - note: deny_cassandra_keyspace_throughput
    parameters:
      throughputMax: 400
    resource:
      type: "Microsoft.DocumentDB/databaseAccounts/cassandraKeyspaces"
      name: "test-cassandra-ks"
      properties:
        options:
          throughput: "600"
    want_effect: "Deny"

  # =========================================================================
  # Cassandra Table: options.throughput exceeds max → Deny
  # =========================================================================

  - note: deny_cassandra_table_throughput
    parameters:
      throughputMax: 400
    resource:
      type: "Microsoft.DocumentDB/databaseAccounts/cassandraKeyspaces/tables"
      name: "test-cassandra-table"
      properties:
        options:
          throughput: "600"
    want_effect: "Deny"

  # =========================================================================
  # Gremlin Database: options.throughput exceeds max → Deny
  # =========================================================================

  - note: deny_gremlin_database_throughput
    parameters:
      throughputMax: 400
    resource:
      type: "Microsoft.DocumentDB/databaseAccounts/gremlinDatabases"
      name: "test-gremlin-db"
      properties:
        options:
          throughput: "600"
    want_effect: "Deny"

  # =========================================================================
  # Gremlin Graph: autoscale (ProvisionedThroughputSettings key) → Deny
  # =========================================================================

  - note: deny_gremlin_graph_autoscale
    parameters:
      throughputMax: 400
    resource:
      type: "Microsoft.DocumentDB/databaseAccounts/gremlinDatabases/graphs"
      name: "test-gremlin-graph"
      properties:
        options:
          ProvisionedThroughputSettings:
            maxThroughput: 4000
    want_effect: "Deny"

  # =========================================================================
  # MongoDB Collection: options.throughput exceeds max → Deny
  # =========================================================================

  - note: deny_mongo_collection_throughput
    parameters:
      throughputMax: 400
    resource:
      type: "Microsoft.DocumentDB/databaseAccounts/mongodbDatabases/collections"
      name: "test-mongo-collection"
      properties:
        options:
          throughput: "600"
    want_effect: "Deny"
