Deploy a Azure Key Vault with TerraForm

Azure Key Vault, What is it?

Azure Key Vault helps solve the following problems:

  • Secrets Management – Azure Key Vault can be used to Securely store and tightly control access to tokens, passwords, certificates, API keys, and other secrets
  • Key Management – Azure Key Vault can also be used as a Key Management solution. Azure Key Vault makes it easy to create and control the encryption keys used to encrypt your data.
  • Certificate Management – Azure Key Vault is also a service that lets you easily provision, manage, and deploy public and private Secure Sockets Layer/Transport Layer Security (SSL/TLS) certificates for use with Azure and your internal connected resources.
  • Store secrets backed by Hardware Security Modules – The secrets and keys can be protected either by software or FIPS 140-2 Level 2 validates HSMs

More information about it can be found here

Deploy Key Vault via Terraform, How-To?

Creating a App registration and define the correct role

For Terraform, we will us a App registration to deploy the environment. This app registration (Service Principal) will get the “Contributor”- role at the subscription level in Azure.

App registration

Go to “Azure Active Directory” in the portal and select “App Registrations” and click “New registration

New App registration

Fill in the name and select “Account in this organizational directory only …“, click “Register

Click “Certificate & Secret“, by clicking the “New client secret” an new value secret will be generated.

Create Secret
Add new secret

Entering a description name, an expiration value. After clicking “Add” will generated the secret.


Make note of the following ID’s:

  • Application (client) ID
  • Directory (tenant) ID
  • Secret ID
  • Subscription ID

Create a bash file with the about values:

#!/bin/sh
echo "Setting environment variables for Terraform"
export ARM_CLIENT_ID="f6xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxd5"
export ARM_CLIENT_SECRET="huwXxxxxxxxxxxxxxxxxxxxxxxxxxxc6"
export ARM_SUBSCRIPTION_ID="a9bexxxxxxxxxxxxxxxxxxxxxxxxxxxxxxa4"
export ARM_TENANT_ID="c4xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx95"

This bash file need to be execute in the cloud shell where terraform has been initialized.

Define role for the service principal.

The SP – account need to have the “Contributor”- role in Azure at the subscription level. Go to the subscription and select subscription name and select “Access Control (IAM)“. Click “Add” and select “Add Role Assignment

Select Role > Contributor and search the newly created service principal.

Assign contributor – role at subscription level


Click “Save” to add the service principal as contributor. This defined we can continue to create the Terraform code and deploy the Azure Key Vault service to Azure.

TerraForm Code

variables.tf

###########
# GENERAL #
###########
variable "RegionWE" {
    default="West Europe"
}

variable "Cloud01_TenantID" {
    default="c46xxxxx-xxxx-xxxx-xxxx-xxxxxxxxx95"
}

variable "Acc_SPTerraform_ObjID" {
    default = "95xxxxxx-xxxx-xxx-xxxx-xxxxxxxxb8"
}

variable "Acc_DExMachFBI_ObjectID" {
    default="3cxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx03"
}
########
# TAGS #
########
variable "TagEnvPRD" {
    default="Production"
}
variable "TagEnvDEMO" {
    default="Demo"
}
variable "TagEnvDEV" {
    default="Development"
}
variable "TagDepIT" {
    default="IT"
}
variable "TagDepHR" {
    default="Human Resources"
}
###################
# RESOURCE GROUPS #
###################
variable "RGSecurity" {
    default="rg-security"
}
###################
# AZURE KEY VAULT #
###################
variable "AKVNme_Demo01" {
    default="AKVDemo01"
}
#Remote network IP Address 
variable "RemoteNetworks" {
    default="xxx.xxx.xxx.xxx/32"
}

main.tf

provider "azurerm" {
    version = "1.28.0"
}

#RESOURCE GROUP NAME
resource "azurerm_resource_group" "RGSecurity" {
    name = "${var.RGSecurity}"
    location = "${var.RegionWE}"
    tags = {
        Environment = "${var.TagEnvDEMO}"
        Departement = "${var.TagDepIT}"
    }
}
#AZURE KEY VAULT
resource "azurerm_key_vault" "AKVDemo01" {
    name                            = "${var.AKVNme_Demo01}"
    location                        = "${azurerm_resource_group.RGSecurity.location}"
    resource_group_name             = "${azurerm_resource_group.RGSecurity.name}"
    #Azure Active Directory tenant ID
    tenant_id                       = "${var.Cloud01_TenantID}"
    #specify whether Azure Virtual Machines are permitted to retrieve certificates stored as secrets from the key vault
    enabled_for_deployment          = true
    #specify whether Azure Disk Encryption is permitted to retrieve secrets from the vault and unwrap keys
    enabled_for_disk_encryption     = true
    #specify whether Azure Resource Manager is permitted to retrieve secrets from the key vault
    enabled_for_template_deployment = true
#Sku standard/premium
    sku {
        name = "standard"
    }
    access_policy {
        #Azure Active Directory tenant ID, need to be the same GUID as tenant_id
        tenant_id = "${var.Cloud01_TenantID}"
        #The object ID of a user, service principal or security group in the Azure Active Directory tenant for the vault.
        #Service principal, App registration account
        object_id = "${var.Acc_SPTerraform_ObjID}"
        key_permissions = [
            "get","list"
        ]
        #Secret permissions set for the service principal account (backup, get, list, recover, restore, set)
        secret_permissions = [
            "backup","get","list","recover","restore","set"
        ]
        storage_permissions = [
            "get","list"
        ]
    }

    access_policy {
        tenant_id = "${var.Cloud01_TenantID}"
        #Access policy second account
        object_id = "${var.Acc_DExMachFBI_ObjectID}"
        certificate_permissions = [
            "backup","create","delete","deleteissuers","get","getissuers","import","list","listissuers","managecontacts","manageissuers","purge","recover","restore","setissuers","update"
        ]

        key_permissions = [
            #All types of security permissions for Key Vault
            "backup","create","decrypt","delete","encrypt","get","import","list","purge","recover","restore","sign","unwrapKey","update","verify","wrapKey"
        ]
        #Secret permissions set for the service principal account (backup, get, list, recover, restore, set)
        secret_permissions = [
            "backup","get","list","purge","recover","restore","set"
        ]
        storage_permissions = [
            "backup","delete","deletesas","get","getsas","list","listsas","purge","recover","regeneratekey","restore","set","setsas","update"
        ]
    }
#Network Access Lists, Security is bypassed for the Azure Services and Azure
#Key Vault is reachable from a remote network based on a IP. Azure Key Vault
#is not reachable from the Internet (Deny)
    network_acls {
        #which traffic can bypass the network rules
        bypass          = "AzureServices"
        #Default action is Deny
        default_action  = "Deny"
        ip_rules        = ["${var.RemoteNetworks}"]
    }

    tags = {
        Environment = "${var.TagEnvDEMO}"
        Departement = "${var.TagDepIT}"
    }
}

This will deploy an Azure Key Vault that has two access policies for a Azure AD account and the service principal, each with there own permissions for storage, secret, key and certification permissions

AKV Access Lists
AKV Network security

You can start using AKV know.


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.