# Azure Policies for Cloud for Sovereignty
# Ensures compliance with data residency and sovereignty requirements

variable "management_group_id" {
  description = "Root management group ID to assign policies"
  type        = string
  default     = "SOVEREIGN-ORDER-OF-HOSPITALLERS"
}

# Configure Azure Provider
provider "azurerm" {
  features {}
}

# Policy: Allowed Locations (Non-US Commercial Regions Only)
resource "azurerm_policy_definition" "allowed_locations" {
  name         = "the-order-allowed-locations"
  policy_type  = "Custom"
  mode         = "All"
  display_name = "The Order - Allowed Locations (Non-US Commercial)"
  description  = "Restricts resource deployment to non-US commercial Azure regions for data sovereignty"

  metadata = jsonencode({
    category = "Location"
  })

  policy_rule = jsonencode({
    if = {
      not = {
        field = "location"
        in = [
          "westeurope",
          "northeurope",
          "uksouth",
          "switzerlandnorth",
          "norwayeast",
          "francecentral",
          "germanywestcentral"
        ]
      }
    }
    then = {
      effect = "Deny"
    }
  })
}

# Policy: Deny US Regions
resource "azurerm_policy_definition" "deny_us_regions" {
  name         = "the-order-deny-us-regions"
  policy_type  = "Custom"
  mode         = "All"
  display_name = "The Order - Deny US Commercial and Government Regions"
  description  = "Explicitly denies deployment to any US Commercial or Government regions"

  metadata = jsonencode({
    category = "Location"
  })

  policy_rule = jsonencode({
    if = {
      field = "location"
      like  = "us*"
    }
    then = {
      effect = "Deny"
    }
  })
}

# Policy: Require Data Residency Tags
resource "azurerm_policy_definition" "require_data_residency_tag" {
  name         = "the-order-require-data-residency-tag"
  policy_type  = "Custom"
  mode         = "Indexed"
  display_name = "The Order - Require Data Residency Tag"
  description  = "Requires DataResidency tag on all resources for sovereignty tracking"

  metadata = jsonencode({
    category = "Tags"
  })

  policy_rule = jsonencode({
    if = {
      field = "[concat('tags[', parameters('tagName'), ']')]"
      exists = "false"
    }
    then = {
      effect = "Deny"
    }
  })

  parameters = jsonencode({
    tagName = {
      type = "String"
      metadata = {
        displayName = "Tag Name"
        description = "Name of the tag, such as 'DataResidency'"
      }
      defaultValue = "DataResidency"
    }
  })
}

# Policy: Require Encryption at Rest
resource "azurerm_policy_definition" "require_encryption_at_rest" {
  name         = "the-order-require-encryption-at-rest"
  policy_type  = "Custom"
  mode         = "All"
  display_name = "The Order - Require Encryption at Rest"
  description  = "Ensures all storage accounts use encryption at rest with customer-managed keys"

  metadata = jsonencode({
    category = "Security"
  })

  policy_rule = jsonencode({
    if = {
      allOf = [
        {
          field = "type"
          equals = "Microsoft.Storage/storageAccounts"
        },
        {
          field = "Microsoft.Storage/storageAccounts/encryption.keySource"
          notEquals = "Microsoft.Keyvault"
        }
      ]
    }
    then = {
      effect = "Deny"
    }
  })
}

# Policy: Require Resource Tags
resource "azurerm_policy_definition" "require_resource_tags" {
  name         = "the-order-require-resource-tags"
  policy_type  = "Custom"
  mode         = "Indexed"
  display_name = "The Order - Require Resource Tags"
  description  = "Requires specific tags on all resources for governance and cost management"

  metadata = jsonencode({
    category = "Tags"
  })

  policy_rule = jsonencode({
    if = {
      anyOf = [
        {
          field = "[concat('tags[', parameters('tagName1'), ']')]"
          exists = "false"
        },
        {
          field = "[concat('tags[', parameters('tagName2'), ']')]"
          exists = "false"
        },
        {
          field = "[concat('tags[', parameters('tagName3'), ']')]"
          exists = "false"
        }
      ]
    }
    then = {
      effect = "Deny"
    }
  })

  parameters = jsonencode({
    tagName1 = {
      type = "String"
      metadata = {
        displayName = "Tag Name 1"
      }
      defaultValue = "Environment"
    }
    tagName2 = {
      type = "String"
      metadata = {
        displayName = "Tag Name 2"
      }
      defaultValue = "Project"
    }
    tagName3 = {
      type = "String"
      metadata = {
        displayName = "Tag Name 3"
      }
      defaultValue = "DataClassification"
    }
  })
}

# Policy Initiative: Cloud for Sovereignty Compliance
resource "azurerm_policy_set_definition" "sovereignty_compliance" {
  name         = "the-order-sovereignty-compliance"
  policy_type  = "Custom"
  display_name = "The Order - Cloud for Sovereignty Compliance"
  description  = "Policy initiative ensuring compliance with Cloud for Sovereignty requirements"

  metadata = jsonencode({
    category = "Compliance"
  })

  policy_definition_reference {
    policy_definition_id = azurerm_policy_definition.allowed_locations.id
  }

  policy_definition_reference {
    policy_definition_id = azurerm_policy_definition.deny_us_regions.id
  }

  policy_definition_reference {
    policy_definition_id = azurerm_policy_definition.require_data_residency_tag.id
  }

  policy_definition_reference {
    policy_definition_id = azurerm_policy_definition.require_encryption_at_rest.id
  }

  policy_definition_reference {
    policy_definition_id = azurerm_policy_definition.require_resource_tags.id
  }
}

# Assign policy initiative to root management group
resource "azurerm_management_group_policy_assignment" "sovereignty_compliance" {
  name                 = "sovereignty-compliance-assignment"
  management_group_id  = var.management_group_id
  policy_definition_id = azurerm_policy_set_definition.sovereignty_compliance.id

  identity {
    type = "SystemAssigned"
  }
}

# Outputs
output "policy_definitions" {
  description = "Created policy definitions"
  value = {
    allowed_locations = azurerm_policy_definition.allowed_locations.id
    deny_us_regions   = azurerm_policy_definition.deny_us_regions.id
    require_data_residency_tag = azurerm_policy_definition.require_data_residency_tag.id
    require_encryption_at_rest = azurerm_policy_definition.require_encryption_at_rest.id
    require_resource_tags = azurerm_policy_definition.require_resource_tags.id
  }
}

output "policy_initiative" {
  description = "Policy initiative ID"
  value       = azurerm_policy_set_definition.sovereignty_compliance.id
}

