In this blog post, we’ll explore how to generate secure user passwords for Azure VMs using Terraform during the VM creation step and output it.
Ensuring the security of your virtual machines (VMs) is critical in today’s dynamic digital landscape. One way to achieve this is by using strong and unique user passwords. By the end of this guide, you’ll know how to automate the creation of random passwords for your Azure VM, enhancing security and streamlining your workflow.
Generate a random password using Terraform
We’ll start with using the random_password
resource to generate a random, secure password for the VM. Add the following block to your main.tf
file. This configuration generates a 20-character password containing alphanumeric characters and special characters from the specified set.
resource "random_password" "set_password" {
length = 20
min_lower = 1
min_upper = 1
min_numeric = 1
min_special = 1
special = true
}
Define the Azure VM resource
Now, we’ll define an azurerm_virtual_machine
resource, which represents your Azure VM. Replace the placeholders with the appropriate values for your environment. Notice the password configuration line admin_password = random_password.set_password.result
resource "azurerm_windows_virtual_machine" "winosvm" {
name = "${var.winosprefix}-vm"
resource_group_name = azurerm_resource_group.rg.name
location = azurerm_resource_group.rg.location
size = "Standard_F2s_v2"
admin_username = "vmadmin"
admin_password = random_password.set_password.result
network_interface_ids = [
azurerm_network_interface.winosnic.id,
]
source_image_reference {
publisher = "MicrosoftWindowsServer"
offer = "WindowsServer"
sku = "2022-datacenter-azure-edition"
version = "latest"
}
os_disk {
storage_account_type = "Standard_LRS"
caching = "ReadWrite"
}
}
Variables
If you would like to use our variables.tf
copy it to your code.
variable "rg_name" {
type = string
default = "Server2022"
description = "The prefix used for all resources in this example"
}
variable "location" {
type = string
default = "southeastasia"
description = "The Azure location where all resources in this example should be created"
}
variable "vm_username" {
type = string
default = "vmadmin"
}
variable "winosprefix" {
type = string
default = "Win2022"
description = "The prefix which should be used for all resources in this example"
}
variable "vnet_name" {
type = string
default = "win_vnet"
}
variable "subnet_name" {
type = string
default = "win_vms"
}
variable "nic_name" {
type = string
default = "winnic"
}
variable "vm_nsg" {
type = string
default = "win_nsg"
}
Output
To output the VM public IP address and password, we use the following output.tf file. Notice that the password section is set not to output the password to the terminal (sensitive set to true). You can change that to false however, we don’t recommend you do that.
The admin password will be available inside terraform.tfstate
output "public_ip_address" {
value = azurerm_windows_virtual_machine.winosvm.public_ip_address
}
output "admin_password" {
sensitive = true
value = azurerm_windows_virtual_machine.winosvm.admin_password
}
The admin_password
value inside the terraform.tfstate
looks like:
"outputs": {
"admin_password": {
"value": "random_password_value",
"type": "string",
"sensitive": true
},
Full code
The full code to create a Windows Server 2022 VM and generate a random password is below.
resource "azurerm_resource_group" "rg" {
name = var.rg_name
location = var.location
}
resource "azurerm_virtual_network" "vnet" {
name = var.vnet_name
address_space = ["10.0.0.0/16"]
location = azurerm_resource_group.rg.location
resource_group_name = azurerm_resource_group.rg.name
}
resource "azurerm_subnet" "subnet" {
name = var.subnet_name
resource_group_name = azurerm_resource_group.rg.name
virtual_network_name = azurerm_virtual_network.vnet.name
address_prefixes = ["10.0.2.0/24"]
}
resource "azurerm_network_interface" "winosnic" {
name = "${var.winosprefix}-nic"
resource_group_name = azurerm_resource_group.rg.name
location = azurerm_resource_group.rg.location
ip_configuration {
name = "internal"
subnet_id = azurerm_subnet.subnet.id
private_ip_address_allocation = "Dynamic"
public_ip_address_id = azurerm_public_ip.winospublicip.id
}
}
resource "azurerm_network_security_group" "nsg" {
name = var.vm_nsg
location = azurerm_resource_group.rg.location
resource_group_name = azurerm_resource_group.rg.name
security_rule {
name = "RDP"
priority = 101
direction = "Inbound"
access = "Allow"
protocol = "Tcp"
source_port_range = "*"
destination_port_range = "3389"
source_address_prefix = "*"
destination_address_prefix = "*"
}
}
resource "azurerm_windows_virtual_machine" "winosvm" {
name = "${var.winosprefix}-vm"
resource_group_name = azurerm_resource_group.rg.name
location = azurerm_resource_group.rg.location
size = "Standard_F2s_v2"
admin_username = "vmadmin"
admin_password = random_password.set_password.result
network_interface_ids = [
azurerm_network_interface.winosnic.id,
]
source_image_reference {
publisher = "MicrosoftWindowsServer"
offer = "WindowsServer"
sku = "2022-datacenter-azure-edition"
version = "latest"
}
os_disk {
storage_account_type = "Standard_LRS"
caching = "ReadWrite"
}
}
resource "azurerm_public_ip" "winospublicip" {
name = "${var.winosprefix}-pubip"
resource_group_name = azurerm_resource_group.rg.name
location = azurerm_resource_group.rg.location
allocation_method = "Dynamic"
}
resource "azurerm_network_interface_security_group_association" "securitygroup" {
network_interface_id = azurerm_network_interface.winosnic.id
network_security_group_id = azurerm_network_security_group.nsg.id
}
resource "random_password" "set_password" {
length = 20
min_lower = 1
min_upper = 1
min_numeric = 1
min_special = 1
special = true
}
Leave a Reply