Sempre que vamos criar alguma infraestrutura por meio de IaC (Terraform, Bicep, Pulumi, etc ...) é de extrema importância mantermos os segredos (ex: strings de conexões) seguras. Inspirado nisso, resolvi escrever esse post com a intenção de mostrar como podemos guardar os segredos das nossas soluções no Azure Key Vault e utilizá-los dentro do nosso código do Terraform.
Vamos precisar que você tenha o Terraform instalado na sua máquina local!
Para iniciar o nosso código, devemos criar definir o provider que será utilizado. (Azure!)
terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "~>3.0"
}
random = {
source = "hashicorp/random"
version = "~>3.0"
}
}
}
provider "azurerm" {
features {}
}
Após isso, já podermos criar o arquivo variables.tf que contém as variáveis que serão utilizadas ao longo do nosso código Terraform.
Observe que a variável "my-secret" está sendo definida de uma forma bem simples. Em casos reais de produção, esse segredo deve ser inserido no código de forma segura!
variable "default_location" {
type = string
default = "eastus"
description = "Default location"
}
variable "resource_group_name_prefix" {
type = string
default = "rg"
description = "Prefix of the resource groups"
}
variable "key_vault_name_prefix" {
type = string
default = "kv"
description = "Prefix of the azure key vault"
}
variable "web_app_name_prefix" {
type = string
default = "app"
description = "Prefix of azure web app"
}
variable "app_service_plan_name_prefix" {
type = string
default = "apps"
description = "Prefix of azure app service plan"
}
variable "default_environment" {
type = string
default = "prod"
description = "Default environment"
}
variable "my-secret" {
type = string
default = "my-secret-value"
description = "Default environment"
}
Já podemos criar os arquivo main.tf. Vamos por partes!
Inicialmente vamos definir os seguintes itens:
- azurerm_client_config;
- current_user_id.
data "azurerm_client_config" "current" {}
locals {
current_user_id = data.azurerm_client_config.current.object_id
}
Para delimitar logicamente os recursos de nuvem, devemos criar um resource group.
resource "azurerm_resource_group" "rg" {
location = var.default_location
name = "${var.resource_group_name_prefix}-app-${var.default_environment}-${var.default_location}"
}
O padrão de nomenclatura utilizado nesse post será o seguinte:
<prefix>-<feature>-<envrironment>-<location>
Por exemplo, para o grupo de recursos:
rg-app-prod-eastus
Com o resource group criado, podemos criar o Azure Key Vault.
resource "azurerm_key_vault" "vault" {
name = "${var.key_vault_name_prefix}-app-${var.default_environment}-${var.default_location}"
location = azurerm_resource_group.rg.location
resource_group_name = azurerm_resource_group.rg.name
tenant_id = data.azurerm_client_config.current.tenant_id
sku_name = "standard"
soft_delete_retention_days = 7
access_policy {
tenant_id = data.azurerm_client_config.current.tenant_id
object_id = local.current_user_id
secret_permissions = ["Get", "List", "Set", "Delete"]
}
}
Observe que adicionamos access policies para o local.current_user_id (usuário logado no terminal. Ex: az login). Desse forma, quando as chaves forem criadas, teremos a permissões necessárias para acessá-las.
Vamos criar um secret dentro do Azure Key Vault definido anteriormente.
resource "azurerm_key_vault_secret" "secret" {
name = "my-secret"
value = var.my-secret
key_vault_id = azurerm_key_vault.vault.id
}
Nesse ponto, nossa infraestrutura como código já possui um segredo definido dentro do Azure Key Vault. Podemos criar outro recurso de nuvem que utilizará esse segredo, sem nunca expor seu valor!
Nesse caso, vamos criar um Azure App Service Plan e um App Service, colocando o segredo como uma configuração no aplicativo web, chamado "MY_SECRET"
resource "azurerm_service_plan" "appserviceplan" {
name = "${var.app_service_plan_name_prefix}-app-${var.default_environment}-${var.default_location}"
location = azurerm_resource_group.rg.location
resource_group_name = azurerm_resource_group.rg.name
os_type = "Linux"
sku_name = "B1"
}
resource "azurerm_linux_web_app" "webapp" {
name = "${var.web_app_name_prefix}-app-${var.default_environment}-${var.default_location}"
location = azurerm_resource_group.rg.location
resource_group_name = azurerm_resource_group.rg.name
service_plan_id = azurerm_service_plan.appserviceplan.id
https_only = true
site_config {
minimum_tls_version = "1.2"
}
app_settings = {
"MY_SECRET" = azurerm_key_vault_secret.secret.value
}
}
Com os arquivos prontos, podemos inicializar o projeto Terraform por meio do comando init.
terraform init
Vamos executar o comando plan, com a intenção de mapear todas as modificações que serão feitas no Azure. No nosso caso, como não temos nada previamente criado, serão provisionados os 5 recursos definidos anteriormente.
terraform plan -out main.tfplan
Vamos criar nossa infraestrutura por meio do comando apply.
terraform apply "main.tfplan"
Após a execução, podemos ver que tudo foi criado de forma correta!
É fechamos aqui o post! Só não vamos esquecer de deletar tudo o que foi criado.
terraform apply -destroy
Você já pode baixar o projeto por esse link, e não esquece de me seguir no LinkedIn!
Até a próxima, abraços!