# Enhanced Key Vault Module
# Implements Well-Architected Framework best practices for Key Vault

variable "resource_group_name" {
  description = "Name of the resource group"
  type        = string
}

variable "location" {
  description = "Azure region"
  type        = string
}

variable "key_vault_name" {
  description = "Name of the Key Vault"
  type        = string
}

variable "environment" {
  description = "Environment (prod, dev, test, staging)"
  type        = string
}

variable "enable_rbac" {
  description = "Enable RBAC authorization (recommended)"
  type        = bool
  default     = true
}

variable "enable_private_endpoint" {
  description = "Enable private endpoint"
  type        = bool
  default     = true
}

variable "private_endpoint_subnet_id" {
  description = "Subnet ID for private endpoint"
  type        = string
  default     = ""
}

variable "allowed_subnet_ids" {
  description = "List of subnet IDs allowed to access Key Vault"
  type        = list(string)
  default     = []
}

variable "allowed_ip_ranges" {
  description = "List of IP ranges allowed to access Key Vault (management)"
  type        = list(string)
  default     = []
}

variable "soft_delete_retention_days" {
  description = "Soft delete retention days"
  type        = number
  default     = 90
}

variable "purge_protection_enabled" {
  description = "Enable purge protection"
  type        = bool
  default     = true
}

variable "tags" {
  description = "Tags to apply to Key Vault"
  type        = map(string)
  default     = {}
}

# Get current client config for RBAC assignments
data "azurerm_client_config" "current" {}

# Private DNS Zone for Key Vault
resource "azurerm_private_dns_zone" "keyvault" {
  count = var.enable_private_endpoint ? 1 : 0
  
  name                = "privatelink.vaultcore.azure.net"
  resource_group_name = var.resource_group_name
  
  tags = var.tags
}

# Private DNS Zone Virtual Network Link
# Note: This requires the virtual network to be in the same resource group or accessible
# For production, create the DNS zone link separately or use a shared DNS zone
resource "azurerm_private_dns_zone_virtual_network_link" "keyvault" {
  count = var.enable_private_endpoint && length(var.allowed_subnet_ids) > 0 ? 1 : 0
  
  name                  = "kv-vnet-link-${replace(var.key_vault_name, "-", "")}"
  resource_group_name   = var.resource_group_name
  private_dns_zone_name = azurerm_private_dns_zone.keyvault[0].name
  virtual_network_id    = data.azurerm_subnet.main[0].virtual_network_id
  registration_enabled  = false
  
  tags = var.tags
}

# Key Vault
resource "azurerm_key_vault" "main" {
  name                = var.key_vault_name
  location            = var.location
  resource_group_name = var.resource_group_name
  tenant_id           = data.azurerm_client_config.current.tenant_id
  sku_name            = "standard"
  
  # Enable RBAC (recommended)
  enable_rbac_authorization = var.enable_rbac
  
  # Soft delete and purge protection
  soft_delete_retention_days = var.soft_delete_retention_days
  purge_protection_enabled   = var.purge_protection_enabled
  
  # Network ACLs (restrict access)
  network_acls {
    default_action = "Deny"  # Deny by default
    bypass         = "AzureServices"
    
    # Allow from specific subnets
    virtual_network_subnet_ids = var.allowed_subnet_ids
    
    # Allow from specific IPs (management)
    ip_rules = var.allowed_ip_ranges
  }
  
  # Public network access (disable if using private endpoint)
  public_network_access_enabled = !var.enable_private_endpoint
  
  tags = merge(var.tags, {
    Environment = var.environment
    Purpose     = "Secrets"
    Security    = "High"
  })
}

# Private Endpoint for Key Vault
resource "azurerm_private_endpoint" "keyvault" {
  count = var.enable_private_endpoint && var.private_endpoint_subnet_id != "" ? 1 : 0
  
  name                = "${var.key_vault_name}-pe"
  location            = var.location
  resource_group_name = var.resource_group_name
  subnet_id           = var.private_endpoint_subnet_id
  
  private_service_connection {
    name                           = "${var.key_vault_name}-psc"
    private_connection_resource_id = azurerm_key_vault.main.id
    subresource_names              = ["vault"]
    is_manual_connection           = false
  }
  
  private_dns_zone_group {
    name                 = "default"
    private_dns_zone_ids = [azurerm_private_dns_zone.keyvault[0].id]
  }
  
  tags = var.tags
}

# RBAC Role Assignment (if RBAC enabled)
resource "azurerm_role_assignment" "keyvault_administrator" {
  count = var.enable_rbac ? 1 : 0
  
  scope                = azurerm_key_vault.main.id
  role_definition_name = "Key Vault Administrator"
  principal_id         = data.azurerm_client_config.current.object_id
}

# Get Virtual Network data (only if subnets are provided)
data "azurerm_subnet" "main" {
  count = length(var.allowed_subnet_ids) > 0 ? 1 : 0
  
  name                 = split("/", var.allowed_subnet_ids[0])[10]
  resource_group_name  = split("/", var.allowed_subnet_ids[0])[4]
  virtual_network_name = split("/", var.allowed_subnet_ids[0])[8]
}

# Outputs
output "key_vault_id" {
  value = azurerm_key_vault.main.id
}

output "key_vault_name" {
  value = azurerm_key_vault.main.name
}

output "key_vault_uri" {
  value = azurerm_key_vault.main.vault_uri
}

output "private_endpoint_id" {
  value = var.enable_private_endpoint && var.private_endpoint_subnet_id != "" ? azurerm_private_endpoint.keyvault[0].id : null
}

