AZURE HEROES
  • Home-Updates
  • Blog
    • Azure Blog
    • Azure Heroes Events >
      • Azure Heroes Sessions #1
      • Azure Heroes Sessions #2
      • Azure Heroes Sessions #3
      • Azure Heroes Sessions #4
      • Azure Heroes Sessions #5
      • Azure Heroes Sessions #6
      • Azure Heroes Sessions #7
  • Who We Are!
  • eBooks
  • Azure All In One!
    • Azure Disk & Storage
    • Azure Network
    • Azure VPN
    • Azure VMs
  • Free Azure Support!
  • Contact Us
  • Events
    • Beginners Event
    • Developers Event
    • Special Event
    • Azure Workshop #4
    • Azure Workshop #5
    • Azure Workshop #6
    • Azure Workshop #7
    • Azure Workshop #8
    • Upcoming Events
  • Registration Form
  • Privacy Policy
  • Home-Updates
  • Blog
    • Azure Blog
    • Azure Heroes Events >
      • Azure Heroes Sessions #1
      • Azure Heroes Sessions #2
      • Azure Heroes Sessions #3
      • Azure Heroes Sessions #4
      • Azure Heroes Sessions #5
      • Azure Heroes Sessions #6
      • Azure Heroes Sessions #7
  • Who We Are!
  • eBooks
  • Azure All In One!
    • Azure Disk & Storage
    • Azure Network
    • Azure VPN
    • Azure VMs
  • Free Azure Support!
  • Contact Us
  • Events
    • Beginners Event
    • Developers Event
    • Special Event
    • Azure Workshop #4
    • Azure Workshop #5
    • Azure Workshop #6
    • Azure Workshop #7
    • Azure Workshop #8
    • Upcoming Events
  • Registration Form
  • Privacy Policy

Terraform Deploy Key Vault with Private Endpoint

1/29/2022

1 Comment

 
The purpose of Azure Key Vault is to store cryptographic keys and other secrets used by cloud applications and services in a HSM (Hardware security module).

In this example, we will create and mange Azure Key Vault using Terraform

Picture
First, we will create main configuration file for Key vault:

# Azure Provider#
##################################
##################################

provider
"azurerm" {
  features {
    key_vault {
      purge_soft_delete_on_destroy = true
    }
  }
}
# To get/import Subscription details#
data "azurerm_client_config" "current" {}

# use existing subnet which it will be used to creare the private endpoint#
data "azurerm_subnet" "appsnet" {
  name                 = "app01-snet"
  virtual_network_name = "hub01-vnet"
  resource_group_name  = "vm02-rg"
}

data "azurerm_subnet" "devopssnet" {
  name                 = "default"
  virtual_network_name = "Devios01-rg-vnet"
  resource_group_name  = "Devios01-rg"
}

# Create Key vault#
resource "azurerm_key_vault" "key_vault" {
  name                            = var.name
  location                        = var.location
  resource_group_name             = var.resource_group_name
  tenant_id                       = data.azurerm_client_config.current.tenant_id
  sku_name                        = var.sku_name
  tags                            = var.tags
  enabled_for_deployment          = var.enabled_for_deployment
  enabled_for_disk_encryption     = var.enabled_for_disk_encryption
  enabled_for_template_deployment = var.enabled_for_template_deployment
  enable_rbac_authorization       = var.enable_rbac_authorization
  purge_protection_enabled        = var.purge_protection_enabled
  soft_delete_retention_days      = var.soft_delete_retention_days
  timeouts {
    delete = "60m"
  }
access_policy {
#to provide the current user with access to Key vault

    tenant_id = data.azurerm_client_config.current.tenant_id
    object_id = data.azurerm_client_config.current.object_id
    key_permissions = [
      "create",
      "get",
      "create",
      "list"
    ]
    certificate_permissions = [
      "create",
      "get",
      "create",
      "list"
    ]
    secret_permissions = [
      "set",
      "get",
      "delete",
      "purge",
      "recover"
    ]
  }
#prvent external access/ from other subnet not declared in variables file#

  network_acls {
    bypass                     = var.bypass
    default_action             = var.default_action
    ip_rules                   = var.ip_rules
    virtual_network_subnet_ids = [data.azurerm_subnet.appsnet.id,data.azurerm_subnet.devopssnet.id]
  }
  lifecycle {
      ignore_changes = [
          tags
      ]
  }
}

# Create Private endpoint#

resource "azurerm_private_endpoint" "private_endpoint" {
  name                = var.private_end_name
  location            = var.location
  resource_group_name = var.resource_group_name
  subnet_id           = "${data.azurerm_subnet.appsnet.id}"
  tags                = var.tags
  private_service_connection {
    name                           = "${var.name}Connection"
    private_connection_resource_id = azurerm_key_vault.key_vault.id
    is_manual_connection           = var.is_manual_connection
    subresource_names              = try([var.subresource_name], null)
    request_message                = try(var.request_message, null)
  }
  private_dns_zone_group {
    name                 = var.private_dns_zone_group_name
    private_dns_zone_ids = [azurerm_private_dns_zone.main.id]
  }
  lifecycle {
    ignore_changes = [
      tags
    ]
  }
  depends_on = [azurerm_key_vault.key_vault]
}
#Create Private DNS Zone#
resource "azurerm_private_dns_zone" "main" {
  name                = "privatelink.vaultcore.azure.net"
  resource_group_name = var.resource_group_name
}

#Create Secrets#

resource "azurerm_key_vault_secret" "kv_secret" {
  name         = "secret1"
  value        = "P2ssw0rd123"
  key_vault_id = azurerm_key_vault.key_vault.id
}
resource "azurerm_key_vault_secret" "kv_secret2" {
  name         = "secret2"
  value        = "P2ssw0rd1234"
  key_vault_id = azurerm_key_vault.key_vault.id
}

Variables File
variable "name" {
  description = "(Required) Specifies the name of the key vault."
  type        = string
  default = "keyvault01"
}
variable "resource_group_name" {
  description = "(Required) Specifies the resource group name of the key vault."
  type        = string
  default = "vm02-rg"
}
variable "location" {
  description = "(Required) Specifies the location where the key vault will be deployed."
  type        = string
  default = "northeurope"
}
variable "sku_name" {
  description = "(Required) The Name of the SKU used for this Key Vault. Possible values are standard and premium."
  type        = string
  default     = "standard"
  validation {
    condition = contains(["standard", "premium" ], var.sku_name)
    error_message = "The value of the sku name property of the key vault is invalid."
  }
}

variable "tags" {
  description = "(Optional) Specifies the tags of the log analytics workspace"
  default     = {
    createdWith = "Terraform"
  }
}
variable "enabled_for_deployment" {
  description = "(Optional) Boolean flag to specify whether Azure Virtual Machines are permitted to retrieve certificates stored as secrets from the key vault. Defaults to false."
  type        = bool
  default     = false
}
variable "enabled_for_disk_encryption" {
  description = " (Optional) Boolean flag to specify whether Azure Disk Encryption is permitted to retrieve secrets from the vault and unwrap keys. Defaults to false."
  type        = bool
  default     = false
}
variable "enabled_for_template_deployment" {
  description = "(Optional) Boolean flag to specify whether Azure Resource Manager is permitted to retrieve secrets from the key vault. Defaults to false."
  type        = bool
  default     = false
}
variable "enable_rbac_authorization" {
  description = "(Optional) Boolean flag to specify whether Azure Key Vault uses Role Based Access Control (RBAC) for authorization of data actions. Defaults to false."
  type        = bool
  default     = false
}
variable "purge_protection_enabled" {
  description = "(Optional) Is Purge Protection enabled for this Key Vault? Defaults to false."
  type        = bool
  default     = false
}
variable "soft_delete_retention_days" {
  description = "(Optional) The number of days that items should be retained for once soft-deleted. This value can be between 7 and 90 (the default) days."
  type        = number
  default     = 30
}
variable "bypass" {
  description = "(Required) Specifies which traffic can bypass the network rules. Possible values are AzureServices and None."
  type        = string
  default     = "AzureServices"
  validation {
    condition = contains(["AzureServices", "None" ], var.bypass)
    error_message = "The valut of the bypass property of the key vault is invalid."
  }
}
variable "default_action" {
  description = "(Required) The Default Action to use when no rules match from ip_rules / virtual_network_subnet_ids. Possible values are Allow and Deny."
  type        = string
  default     = "Deny"
  validation {
    condition = contains(["Allow", "Deny" ], var.default_action)
    error_message = "The value of the default action property of the key vault is invalid."
  }
}
variable "ip_rules" {
  description = "(Optional) One or more IP Addresses, or CIDR Blocks which should be able to access the Key Vault."
  default     = ["10.0.0.5"]
}
variable "virtual_network_subnet_ids" {
  description = "(Optional) One or more Subnet ID's which should be able to access this Key Vault."
  default     = []
}

#####
variable "private_end_name" {
  description = "(Required) Specifies the name of the private endpoint. Changing this forces a new resource to be created."
  type        = string
  default = "Vault01PrivateEndpoint"
}


variable "is_manual_connection" {
  description = "(Optional) Specifies whether the private endpoint connection requires manual approval from the remote resource owner."
  type        = string
  default     = false  
}
variable "subresource_name" {
  description = "(Optional) Specifies a subresource name which the Private Endpoint is able to connect to."
  type        = string
  default     = "vault"
}
variable "request_message" {
  description = "(Optional) Specifies a message passed to the owner of the remote resource when the private endpoint attempts to establish the connection to the remote resource."
  type        = string
  default     = null
}
variable "private_dns_zone_group_name" {
  description = "(Required) Specifies the Name of the Private DNS Zone Group. Changing this forces a new private_dns_zone_group resource to be created."
  type        = string
  default = "KeyVaultPrivateDnsZoneGroup"
}
variable "private_dns" {
  default = {}
}
Result
Picture
Picture
Picture
Proof that External Access is not allowd
Picture
1 Comment
Mrtin
2/1/2022 01:41:22 pm

Awsome

Reply



Leave a Reply.

    Author

    Mohammad Al Rousan is a Microsoft MVP (Azure), Microsoft Certified Solution Expert (MCSE) in Cloud Platform & Azure DevOps & Infrastructure, An active community blogger and speaker. Al Rousan has over 8 years of professional experience in IT Infrastructure and very passionate about Microsoft technologies and products.

    Picture
    Picture
    Top 10 Microsoft Azure Blogs

    Archives

    November 2022
    October 2022
    July 2022
    June 2022
    May 2022
    April 2022
    March 2022
    February 2022
    January 2022
    December 2021
    November 2021
    May 2021
    February 2021
    December 2020
    November 2020
    October 2020
    September 2020
    August 2020
    June 2020
    April 2020
    January 2020
    July 2019
    June 2019
    May 2019
    February 2019
    January 2019

    Categories

    All
    AKS
    Azure
    Beginner
    CDN
    DevOps
    End Of Support
    Fundamentals
    Guide
    Hybrid
    License
    Migration
    Network
    Security
    SQL
    Storage
    Virtual Machines
    WAF

    RSS Feed

    Follow
    Free counters!
Powered by Create your own unique website with customizable templates.