azureazure-active-directoryterraformacrazure-aks

Azure Role Assignment - AKS to ACR - Terraform


I am using the Terraform code below, to create a resource group, create an AKS cluster and i am trying to allow the AKS cluster to use an existing ACR in the same subscription, using the data {} reference. It works fine without the role assignment block, but when i use that i keep getting the below error

Error: Invalid index

  on main.tf line 40, in resource "azurerm_role_assignment" "aks_to_acr_role":
  40:   principal_id         = azurerm_kubernetes_cluster.aks.kubelet_identity[0].object_id
    |----------------
    | azurerm_kubernetes_cluster.aks.kubelet_identity is empty list of object

The given key does not identify an element in this collection value.

I have looked all over stack exchange, microsoft azure docs and Terraform issues and lots of blog posts, i honestly have no idea what is wrong at this point. Any suggestions would be greatly appreciated.

resource "azurerm_resource_group" "rg" {
      name     = var.resource_group_name
      location = var.location
    }

    resource "azurerm_kubernetes_cluster" "aks" {
      name                = var.cluster_name
      kubernetes_version  = var.kubernetes_version
      location            = var.location
      resource_group_name = azurerm_resource_group.rg.name
      dns_prefix          = var.cluster_name

      default_node_pool {
        name                = "system"
        node_count          = var.system_node_count
        vm_size             = "Standard_B2ms"
        type                = "VirtualMachineScaleSets"
        availability_zones  = [1, 2, 3]
        enable_auto_scaling = false
      }

      service_principal {
        client_id     = var.appId
        client_secret = var.password
      }

    }
    data "azurerm_container_registry" "acr_name" {
      name = "xxxxx"
      resource_group_name = "xxxxx"
    }
    resource "azurerm_role_assignment" "aks_to_acr_role" {
      scope                = data.azurerm_container_registry.acr_name.id
      role_definition_name = "AcrPull"
      principal_id         = azurerm_kubernetes_cluster.aks.kubelet_identity[0].object_id
      skip_service_principal_aad_check = true
    }

ACR name and RG name are xxxxx out of the code just for privacy


Solution

  • While Using the Service Principal as a identity for Kubernetes cluster the kubelet_identity will be empty as you have not defined identity block while creating the AKS Cluster . The Identity block conflicts with Service Principal Block so, they can't be used together .

    Solutions:

    1. You can use Identity as SystemAssigned instead of Service Principal then you don't have to configure the kubelet_identity block ,it will automatically get preconfigured and you can use azurerm_kubernetes_cluster.aks.kubelet_identity[0].object_id successfully. So, your code will be like below:

      provider"azurerm"{
          features{}
      }
      data "azurerm_resource_group" "rg" {
            name     = "ansumantest"
      }
      
          resource "azurerm_kubernetes_cluster" "aks" {
            name                = "ansumantestaks"
            location            = data.azurerm_resource_group.rg.location
            resource_group_name = data.azurerm_resource_group.rg.name
            dns_prefix          = "ansumantestaks-dns"
      
            default_node_pool {
              name                = "system"
              node_count          = 1
              vm_size             = "Standard_B2ms"
              type                = "VirtualMachineScaleSets"
              availability_zones  = [1, 2, 3]
              enable_auto_scaling = false
            }
             identity{
                 type = "SystemAssigned"
             }
          }
          data "azurerm_container_registry" "acr_name" {
            name = "ansumantestacr"
            resource_group_name = data.azurerm_resource_group.rg.name
          }
          resource "azurerm_role_assignment" "aks_to_acr_role" {
            scope                = data.azurerm_container_registry.acr_name.id
            role_definition_name = "AcrPull"
            principal_id         = azurerm_kubernetes_cluster.aks.kubelet_identity[0].object_id
            skip_service_principal_aad_check = true
          }
      

      Output:

      enter image description here

      enter image description here

      enter image description here


    1. If you want to use Service Principal only instead of Identity , then you have to use Service Principal Object Id in the role assignment as the aks is also using the same Service Principal.The Code with Service Principal Block will be like below :

      provider"azurerm"{
          features{}
      }
      provider"azuread"{}
      # Service Principal Which is being used by AKS.
      data "azuread_service_principal" "akssp"{
          display_name = "aksspansuman"
      }
      data "azurerm_resource_group" "rg" {
            name     = "ansumantest"
      }
      
          resource "azurerm_kubernetes_cluster" "aks" {
            name                = "ansumantestaks"
            location            = data.azurerm_resource_group.rg.location
            resource_group_name = data.azurerm_resource_group.rg.name
            dns_prefix          = "ansumantestaks-dns"
      
            default_node_pool {
              name                = "system"
              node_count          = 1
              vm_size             = "Standard_B2ms"
              type                = "VirtualMachineScaleSets"
              availability_zones  = [1, 2, 3]
              enable_auto_scaling = false
            }
      
            service_principal {
            client_id = data.azuread_service_principal.akssp.application_id
            client_secret = "e997Q~xxxxxxxx"
            }
      
          }
          data "azurerm_container_registry" "acr_name" {
            name = "ansumantestacr"
            resource_group_name = data.azurerm_resource_group.rg.name
          }
          resource "azurerm_role_assignment" "aks_to_acr_role" {
            scope                = data.azurerm_container_registry.acr_name.id
            role_definition_name = "AcrPull"
            principal_id         = data.azuread_service_principal.akssp.object_id
            skip_service_principal_aad_check = true
          }
      

      Outputs:

      enter image description here

      enter image description here