I am currently working on deploying a VM on Azure using Terraform. The VM deployed correctly when using client_id, subscription_id, client_secret and tenant_id in the AzureRM provider block. However, I want to make use of managed identities so I don't have to expose the client_secret.
Things I tried: For this, I followed this guide
I included the azuread provider block, used the "use_msi = true" to indicate that managed identities should be used. Also included the azurerm_subscription block,azurerm_Client_config, as well as a resource definition. Then added the role assignment to the VM.
Code:
terraform {
required_providers {
azuread = {
source = "hashicorp/azuread"
}
}
}
provider "azurerm" {
features {}
//client_id = "XXXXXXXXXXXXXX"
//client_secret = "XXXXXXXXXXXXXX"
//subscription_id = "XXXXXXXXXXXXXX"
tenant_id = "TENANT_ID"
//use_msi = true
}
provider "azuread" {
use_msi = true
tenant_id = "TENANT_ID"
}
#Resource group definition
resource "azurerm_resource_group" "myVMachineRG" {
name = "testnew-resources"
location = "westus2"
}
resource "azurerm_virtual_network" "myVNet" {
name = "testnew-network"
address_space = ["10.0.0.0/16"]
location = azurerm_resource_group.myVMachineRG.location
resource_group_name = azurerm_resource_group.myVMachineRG.name
}
resource "azurerm_subnet" "mySubnet" {
name = "testnew-internal-subnet"
resource_group_name = azurerm_resource_group.myVMachineRG.name
virtual_network_name = azurerm_virtual_network.myVNet.name
#256 total IPs
address_prefixes = ["10.0.2.0/24"]
}
resource "azurerm_network_interface" "myNIC" {
name = "testnew-nic"
location = azurerm_resource_group.myVMachineRG.location
resource_group_name = azurerm_resource_group.myVMachineRG.name
ip_configuration {
name = "testconfiguration1"
subnet_id = azurerm_subnet.mySubnet.id
private_ip_address_allocation = "Dynamic"
}
}
#ADDED HERE:
data "azurerm_subscription" "current" {}
data "azurerm_client_config" "example" {
}
resource "azurerm_virtual_machine" "example" {
name = "testnew-vm"
location = azurerm_resource_group.myVMachineRG.location
resource_group_name = azurerm_resource_group.myVMachineRG.name
network_interface_ids = ["${azurerm_network_interface.myNIC.id}"]
vm_size = "Standard_F2"
#Option to delete disks when Terraform destroy is performed.
#This is to ensure that we don't keep wasting balance
delete_os_disk_on_termination = true
delete_data_disks_on_termination = true
storage_image_reference {
publisher = "Canonical"
offer = "UbuntuServer"
sku = "16.04-LTS"
version = "latest"
}
storage_os_disk {
name = "OSDISK"
caching = "Readwrite"
create_option = "FromImage"
managed_disk_type = "Standard_LRS"
}
#Just for testing purposes, would be better to use a KeyVault reference here instead.
os_profile {
computer_name = "XXXXXXXXXXXXXX"
admin_username = "XXXXXXXXXXXXXX"
admin_password = "XXXXXXXXXXXXXX"
}
#Force password to authenticate
os_profile_linux_config {
disable_password_authentication = false
}
identity {
type = "SystemAssigned"
}
}
data "azurerm_role_definition" "contributor" {
name = "Contributor"
}
resource "azurerm_role_assignment" "example" {
//name = azurerm_virtual_machine.example.name
scope = data.azurerm_subscription.current.id
role_definition_name = "Contributor"
//role_definition_id = "${data.azurerm_subscription.current.id}${data.azurerm_role_definition.contributor.id}"
//principal_id = azurerm_virtual_machine.example.identity[0].principal_id
principal_id = data.azurerm_client_config.example.object_id
}
Error:
Error: building AzureRM Client: obtain subscription() from Azure CLI: parsing json result from the Azure CLI: waiting for the Azure CLI: exit status 1: ERROR: Please run 'az login' to setup account.
│
│ with provider["registry.terraform.io/hashicorp/azurerm"],
│ on main.tf line 9, in provider "azurerm":
│ 9: provider "azurerm" {
I dont understand why it's still asking to use az login when I am trying to use Managed Identity for log-in.
Redacted the tenantID for security purposes.
Any help would be greatly appreciated :)
CodePudding user response:
your provider block has usemsi commented out for azurerm (the one that's failing.) Is that just a code transfer mistake to this question? Would have put this in comments but my reputation is not high enough.
Looks like azurerm might also need the subscription id (unlike azuread) https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/guides/managed_service_identity
The use_msi property should be in azurerm as well. From the above link: enter image description here
Also, just ot be sure, you've already configured the managed identity to use for this purpose, right?
CodePudding user response:
I tried to reproduce the same requirement in my environment and was able to deploy it successfully.
Need to provide name of the managed identity if you are authenticating via managed identities in terraform.
Add msi_name
under azuread
provider.
Note: As you have given, make sure that managed identities should have enough permissions (contributor role) to authenticate and create resources otherwise deployment will fail.
main.tf
data "azurerm_subscription" "current" {}
variable "subscription_id" {
default = "xxxxxxxxxxxx"
}
provider "azurerm"{
features{}
subscription_id = var.subscription_id
}
provider "azuread"{
features{}
use_msi = true
msi-name = "jahnaviidentity" //Give Name of the Managed identity
}
resource "azurerm_resource_group" "example" {
name = "example-resources"
location = "West Europe"
}
resource "azurerm_virtual_network" "main" {
name = "main-network"
address_space = ["10.0.0.0/16"]
location = azurerm_resource_group.example.location
resource_group_name = azurerm_resource_group.example.name
}
resource "azurerm_subnet" "internal" {
name = "internal"
resource_group_name = azurerm_resource_group.example.name
virtual_network_name = azurerm_virtual_network.main.name
address_prefixes = ["10.0.2.0/24"]
}
resource "azurerm_network_interface" "main" {
name = "main-nic"
location = azurerm_resource_group.example.location
resource_group_name = azurerm_resource_group.example.name
ip_configuration {
name = "<configurationname>"
subnet_id = azurerm_subnet.internal.id
private_ip_address_allocation = "Dynamic"
}
}
resource "azurerm_virtual_machine" "main" {
name = "main-vm"
location = azurerm_resource_group.example.location
resource_group_name = azurerm_resource_group.example.name
network_interface_ids = [azurerm_network_interface.main.id]
vm_size = "Standard_DS1_v2"
storage_image_reference {
publisher = "Canonical"
offer = "UbuntuServer"
sku = "16.04-LTS"
version = "latest"
}
storage_os_disk {
name = "osdisk"
caching = "ReadWrite"
create_option = "FromImage"
managed_disk_type = "Standard_LRS"
}
os_profile {
computer_name = "<computername>"
admin_username = "<admin/username>"
admin_password = "xxxxxx"
}
os_profile_linux_config {
disable_password_authentication = false
}
identity {
type = "SystemAssigned"
}
}
Output:
terraform init
:
terraform plan
:
terraform apply
:
Deployed successfully in Azure Portal: