Featured image of post Microsoft Fabric & Terraform - Authentication

Microsoft Fabric & Terraform - Authentication

Recommended authentication configuration for Microsoft Fabric using Terraform

Ways to authenticate

There are several ways to set up authentication for Terraform when using the provider for Microsoft Fabric and on the top level can be divided into 2 main categories:

  • User authentication
  • Service Principal

User authentication is interactive and depends on using the Azure CLI and as such is not suitable for automating provisioning through CI/CD pipelines.
A Service Principal (SP) on the other hand is non-interactive in nature and is what you want to use for your automation. Service Principal comes in a few flavors and my favorite and recommendation is to use a SP with OpenID Connect (OIDC). With this option you no longer have to worry about either expiring certificates or client secrets as it uses something called workload identity federation.

Limitations

To put it simply, the Terraform provider is a wrapper around the Microsoft Fabric REST API, meaning the authentication options are limited to whatever each API supports. I am regularly updating the table in this blog post on which Microsoft Fabric items which support service principal authentication. The table also includes which of those items again which has a Terraform resource published.

Creating a service principal as a federated identity credential

Since it is likely that there is a different team that manage your Azure estate than your Microsoft Fabric environment(s) I have made in this example the presumption that the Azure-team will implement the code below for you to have a dedicated service principal for your Microsoft Fabric automation tasks.

resource "azuread_application_registration" "iac_msfabric" {
  display_name = "tf-app-iac-msfabric"
}

resource "azuread_application_federated_identity_credential" "iac_msfabric" {
  application_id = azuread_application_registration.iac_msfabric.id
  display_name   = "tf-iac-msfabric-wif"
  description    = "Deployments for iac-msfabric repository"
  audiences      = ["api://AzureADTokenExchange"]
  issuer         = "https://token.actions.githubusercontent.com"
  subject        = "repo:MyGitHubAcctountOrOrganization/MyMsFabricTerraformCodeRepo:ref:refs/heads/main"
}

Configuring your Terraform environment for federated identity credential

In setting up your Terraform environment you want to make your configuration details as secure as possible. You can set it up in a way that the configuration details are stored as masked environment variables and that way if a bad actor (internal or external) gets read-access to your code repository the details are inaccessible.

Initializing Terraform

Before processing the Terraform code the working directory needs to be initialized using the terraform init command. Specifically, it:

  1. Installs provider plugins: Terraform downloads and installs the providers referenced in your configuration (for example, Fabric, Azure, etc.) into a local directory (often called a plugin directory).
  2. Prepares the backend: If you use a remote or local backend for storing Terraform state, terraform init configures and initializes it.
  3. Validates required modules: Any referenced Terraform modules are located, downloaded, or otherwise prepared for use.

terraform init is the very first command you should run in a new or cloned Terraform configuration folder, because it sets up everything Terraform needs for subsequent commands like terraform plan or terraform apply.

Executing the init-command like in this example you do not need reference the location of your remote state file in the terraform code block (see next paragraph).

terraform init \
  -backend-config="resource_group_name=my-sa-rg" \
  -backend-config="storage_account_name=mytfstatesa001" \
  -backend-config="container_name=mytfstates" \
  -backend-config="key=my-tf-env-state.tfstate"

In a future blog post I will go more in detail on how to configure the different Terraform task, including intitialization, for GitHub Action workflows and Azure DevOps pipelines.

Terraform configuration values

In your Terraform files folder you are required to have a terraform code block and provider code blocks. This blocks configures the Terraform behavior.
For readability always have the terraform block and provider block(s) in separate files:

tf / (working directory)
└── terraform.tf
└── provider.tf

In the code example below, when setting up the minimum (and recommended) required for service principal with workload identity federation this is what you need

terraform {
  required_version = ">= 1.8, < 2.0"
  backend "azurerm" {
    use_oidc = true
  }
  required_providers {
    # Microsoft Fabric    
    fabric = {
      source  = "microsoft/fabric"
    }    
  }
}

#############################################
#         Microsoft Fabric provider         #
#############################################
provider "fabric" {
  use_oidc = true
}

Environment variables

This configuration relies on environment varibles to be set. For local testing to make this work you need to set the following environment variables:

export FABRIC_TENANT_ID="00000000-0000-0000-0000-000000000000"
export FABRIC_CLIENT_ID="00000000-0000-0000-0000-000000000000"
The TENANT_ID is the GUID for your Entra ID tenant | The GUID for your Entra ID tenant.
The CLIENT_ID is the Application ID GUID for your application registration

Resources

Fabric Terraform provider - Authentication using a Service Principal and OpenID Connect (OIDC) Terraform init command - Offical docs
Terraform block reference - Official docs

Notes from the field...my internet-stored long term memory
Built with Hugo
Theme Stack designed by Jimmy