Terraform Template to deploy Windows VM with Bastion Host on Azure
- Active Azure subscription
- Azure AD service principal with permission to modify the target resource group
- Azure CLI v2.46.0 or above
- Terraform CLI v1.3.7 or above
-
In Terraform Cloud, create a new workspace.
-
Chooose
Version Control Workflow
. -
Click
GitHub App
and select this repository. -
Once workspace is created, input
resource_group_name
andsuffix
variable. -
Configure the following environment variables accordingly:
ARM_CLIENT_ID
ARM_CLIENT_SECRET
- don't forget to mark as 'sensitive'ARM_TENANT_ID
ARM_SUBSCRIPTION_ID
-
Click
+ New run
and thenStart run
. -
The plan should run successfully. Review the plan then click
Confirm & apply
and thenConfirm plan
. -
All resources should be created successfully
- Log in to Azure and switch to your target subscription.
az login --service-principal \
--tenant "00000000-0000-0000-0000-000000000000" \
--username "00000000-0000-0000-0000-000000000000" \
--password "ThisIsYourSecret"
az account set --subscription "YOUR_SUBSCRIPTION_NAME"
- Init and apply.
terraform init
terraform apply -var "resource_group_name=rg-your-resource-group" -var "suffix=vmtest"
-
Go to States and open the latest one.
-
Input the following into the filter to get username and password resoectively:
.outputs.windows_virtual_machine_admin_username.value
.outputs.windows_virtual_machine_admin_password.value
echo "USERNAME: $(terraform output -raw windows_virtual_machine_admin_username)"
echo "PASSWORD: $(terraform output -raw windows_virtual_machine_admin_password)"
- Open Azure Portal. Go to your virtual machine and connect to the VM using Bastion.
- Update Windows.
- Create another local admin account and log in using the new account next time. Do not use sysadmin account.
Use these commands to turn off virtual machine and delete Bastion host to save cost.
RESOURCE_GROUP_NAME="$(terraform output -raw resource_group_name)"
VM_NAME="$(terraform output -raw windows_virtual_machine_name)"
az vm stop --resource-group "${RESOURCE_GROUP_NAME}" --name "${VM_NAME}" --no-wait
terraform apply -var "resource_group_name=rg-your-resource-group" -var "suffix=vmtest" -var "bastion=false"
Use these commands to turn on virtual machine and create Bastion host.
RESOURCE_GROUP_NAME="$(terraform output -raw resource_group_name)"
VM_NAME="$(terraform output -raw windows_virtual_machine_name)"
az vm start --resource-group "${RESOURCE_GROUP_NAME}" --name "${VM_NAME}" --no-wait
terraform apply -var "resource_group_name=rg-your-resource-group" -var "suffix=vmtest" -var "bastion=true"
To use GitHub Actions to turn on or off the virtual machine, follow this instruction.
- Go to your service principal and configure a new OIDC federated crendential with the scope to your repository's environment named
azure
. - Retrieve variables from CLI or from Azure portal:
echo "RESOURCE_GROUP_NAME : $(terraform output -raw resource_group_name)"
echo "VM_NAME : $(terraform output -raw windows_virtual_machine_name)"
echo "BASTION_NAME : $(terraform output -raw azurerm_bastion_host_name)"
echo "PUBLIC_IP_NAME : $(terraform output -raw public_ip_name)"
echo "VNET_NAME : $(terraform output -raw virtual_network_name)"
echo "AZURE_CLIENT_ID : $(terraform output -raw azurerm_client_id)"
echo "AZURE_TENANT_ID : $(terraform output -raw azurerm_tenant_id)"
echo "AZURE_SUBSCRIPTION_ID: $(terraform output -raw azurerm_subscription_id)"
- Go to your repository settings and create environment
azure
, if not existed. - Add all variables from 2 as environment secrets.
- Run the workflow
Start VM
orStop VM
as you wish.
You can customize using the the following variables:
Variable | Description |
---|---|
location | Location name where all resources will be created. Default to resource group's location. Use command az account list-locations --output table to list all avaialble locations. |
bastion | Whether to create bastion host. Default to true . To save cost, set to false to delete bastion host and set back to true when needed. It takes ~6-8 minutes to create or delete. |
If you get the error 'Microsoft.Compute/EncryptionAtHost' feature is not enabled for this subscription
when apply.
- Execute the following command to enable this feature in your subscription:
az feature register --namespace Microsoft.Compute --name EncryptionAtHost
- Wait until the feature is registered (state =
Registered
). This might take around 20 minutes. You may use this command to monitor:
watch az feature show --namespace Microsoft.Compute --name EncryptionAtHost
- Execute this command to ensure the change is propagated:
az provider register -n Microsoft.Compute