Pular para o conteúdo principal

Criando uma Máquina Virtual no Azure com Senha no Key Vault usando Terraform

Introdução​

Este laboratório mostra como criar uma máquina virtual Linux no Azure utilizando Terraform, mas com um diferencial de segurança: a senha da VM será armazenada de forma segura no Azure Key Vault, e recuperada dinamicamente no momento da execução. Isso evita que senhas sensíveis fiquem expostas em arquivos .tf ou .tfvars no repositório. Este tipo de prática é fundamental quando falamos de segurança em ambientes de infraestrutura como código.


Estrutura de diretórios​

mkdir vm-keyvault && cd vm-keyvault

touch main.tf variables.tf outputs.tf terraform.tfvars

Comandos: Preparação com Azure CLI​

Antes de rodar o Terraform, precisamos preparar o ambiente no Azure:

az group create --name rg-tf-vm-keyvault --location eastus

az keyvault create \
--name kv-devopsautomation-lab \
--resource-group rg-tf-vm-keyvault \
--location eastus

az keyvault secret set \
--vault-name kv-devopsautomation-lab \
--name vmPassword \
--value "SenhaSuperSegura123"

⚠️ Atenção: O segredo precisa ser criado manualmente. O Terraform vai apenas ler esse valor e aplicar na criação da VM.


Arquivo main.tf​

terraform {
required_version = ">= 1.12.2"
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = ">= 2.0"
}
}
}

provider "azurerm" {
features {}
}

data "azurerm_resource_group" "rg" {
name = var.resource_group_name
}

data "azurerm_key_vault" "kv" {
name = var.key_vault_name
resource_group_name = var.resource_group_name
}

data "azurerm_key_vault_secret" "vm_password" {
name = var.secret_name
key_vault_id = data.azurerm_key_vault.kv.id
}

resource "azurerm_virtual_network" "vnet" {
name = "vnet"
address_space = ["10.0.0.0/16"]
location = var.location
resource_group_name = data.azurerm_resource_group.rg.name
}

resource "azurerm_subnet" "subnet" {
name = "subnet"
resource_group_name = data.azurerm_resource_group.rg.name
virtual_network_name = azurerm_virtual_network.vnet.name
address_prefixes = ["10.0.1.0/24"]
}

resource "azurerm_network_security_group" "nsg" {
name = "nsg"
location = var.location
resource_group_name = data.azurerm_resource_group.rg.name

security_rule {
name = "SSH"
priority = 1001
direction = "Inbound"
access = "Allow"
protocol = "Tcp"
source_port_range = "*"
destination_port_range = "22"
source_address_prefix = "*"
destination_address_prefix = "*"
}
}

resource "azurerm_subnet_network_security_group_association" "nsg_assoc" {
subnet_id = azurerm_subnet.subnet.id
network_security_group_id = azurerm_network_security_group.nsg.id
}

resource "azurerm_public_ip" "public_ip" {
name = "public-ip"
location = var.location
resource_group_name = data.azurerm_resource_group.rg.name
allocation_method = "Static"
sku = "Standard"
}

resource "azurerm_network_interface" "nic" {
name = "nic"
location = var.location
resource_group_name = data.azurerm_resource_group.rg.name

ip_configuration {
name = "internal"
subnet_id = azurerm_subnet.subnet.id
private_ip_address_allocation = "Dynamic"
public_ip_address_id = azurerm_public_ip.public_ip.id
}
}

resource "azurerm_linux_virtual_machine" "vm" {
name = var.vm_name
location = var.location
resource_group_name = data.azurerm_resource_group.rg.name
size = "Standard_B1s"
admin_username = var.admin_username
admin_password = data.azurerm_key_vault_secret.vm_password.value
disable_password_authentication = false
network_interface_ids = [azurerm_network_interface.nic.id]

os_disk {
caching = "ReadWrite"
storage_account_type = "Standard_LRS"
name = "osdisk"
}

source_image_reference {
publisher = "Canonical"
offer = "UbuntuServer"
sku = "18.04-LTS"
version = "latest"
}
}

Arquivo variables.tf​

variable "resource_group_name" { type = string }
variable "location" { type = string }
variable "key_vault_name" { type = string }
variable "secret_name" { type = string }
variable "vm_name" { type = string }
variable "admin_username" { type = string }

Arquivo outputs.tf​

output "public_ip" {
value = azurerm_public_ip.public_ip.ip_address
description = "IP público da VM"
}

Arquivo terraform.tfvars​

resource_group_name = "rg-tf-vm-keyvault"
location = "eastus"
key_vault_name = "kv-devopsautomation-lab"
secret_name = "vmPassword"
vm_name = "vm-keyvault-demo"
admin_username = "azureuser"

Comandos Terraform​

terraform init
terraform plan -var-file="terraform.tfvars"
terraform apply -var-file="terraform.tfvars"

Output esperado​

Apply complete! Resources: 6 added, 0 changed, 0 destroyed.

Outputs:
public_ip = "52.170.12.34"

Conclusão​

Esse laboratório demonstrou como criar uma VM segura no Azure utilizando Terraform e integrando o Azure Key Vault para armazenar a senha da VM. Essa abordagem reduz riscos de exposição de dados sensíveis e representa uma prática recomendada para ambientes profissionais. Além disso, reforça o conceito de separação de responsabilidades: a infraestrutura é declarada com Terraform, e os segredos são gerenciados de forma segura pelo Key Vault.

Na próxima aula, você poderá experimentar acessar essa VM usando SSH com a senha segura ou ajustar o provisionamento para usar chaves públicas e privadas.