DEV Community

Cover image for HCP Terraform to Azure Cloud using OIDC
Roman Kiprin
Roman Kiprin

Posted on

HCP Terraform to Azure Cloud using OIDC

The usecase

The usecase

We need our HCP Terraform Workspace to deploy resources to Microsoft Azure without using secrets, tokens, passwords, or anything similar.

Challenging? Not really. We just need to configure OpenID Connect. Continue reading if you need details.

Prerequisites

Obviously, we need to obtain:

  • the Azure subscription (with the Owner role access),
  • the HCP Terraform Workspace,
  • a GitLab (or any other supported by HCP Terraform VCS) project with the Terraform code. (However, the GitLab integration is slightly outside of the scope of this post.)

Let's pretend we have HCP Terraform workspace

HCP Terraform Workspace

It is crucial to know

  • the name of the organization: rokicool-tf
  • the project: dev-to
  • the name of the workspace: azure-automation-account-dev

We will use these identifiers later.

And imagine we have a new shiny Azure subscription:

Azure subscription

We need to know the Azure subscription ID and the Tenant ID. If you are not sure if your subscription is located in the root management group or not, just open the Entra ID interface in the Azure Portal. The first thing you'll see will be the Tenant ID.

Tenant

  • Subscription ID 971307eb-329d-47a2-b3f2-d424f4da5461
  • Tenant ID 86abb60f-b63e-475e-85dd-9fa6e1d9f754

Service Principal to represent HCP Terraform Workspace

Our HCP Terraform Workspace should have identity to access the Azure subscription to deploy/destroy resources.

Let's create one.

Azure portal, Entra ID, App Registrations, + New Registration...

New Registration

Entering it's name... sp-azure-automation-account-deployer-tfc

Add the name

And here it is:

Service Principal is ready

The only significant part is...

  • The Client ID 348c0fdc-b20f-4fe7-a79a-872068ff22fd

Give it a role!

The identity cannot do much (access Entra ID with read permissions) by default. You need to assign it a role on the necessary scope.

The details about the possible role and the correct scope are far beyond this post. So, let's say we want to give it Contributor on the scope of subscription.

Create service principal

Federated Credentials for the Service Principal

Everything before this point was a preparation. Now the magic comes!

HashiCorp provides a very comprehensive document Use dynamic credentials with the Azure provider which explains a lot. Especially Configure Microsoft Entra ID Application to Trust a Generic Issuer section.

However, it's outdated a little! We are going to use one flexible federated credential instead of two static ones (as the official document suggests).

First, we need to build a string that is called Subject identifier. The template is

organization:<my-org-name>:project:<my-project-name>:workspace:<my-workspace-name>:run_phase:plan
Enter fullscreen mode Exit fullscreen mode

In our example, the string will look like this:

organization:rokicool-tf:project:dev-to:workspace:azure-automation-account-dev:run_phase:plan
Enter fullscreen mode Exit fullscreen mode

and...

organization:rokicool-tf:project:dev-to:workspace:azure-automation-account-dev:run_phase:apply
Enter fullscreen mode Exit fullscreen mode

... for the second federated identity credentials.

But!

We are going to use Claims matching expression instead of the Explicit subject identifier!

Therefore, our string will look like this:

claims['sub'] matches 'organization:rokicool-tf:project:dev-to:workspace:azure-automation-account-dev:run_phase:*'
Enter fullscreen mode Exit fullscreen mode

Do you see? It is an expression, and the "*" symbol matches both plan and apply phases!

The rest of the fields are described in the mentioned document:

  • Federated credential scenario: Must be set to Other issuer
  • Issuer: The address of HCP Terraform (e.g., https://app.terraform.io)
  • Name: A name for the federated credential, such as `tfc-azure-automation-account-dev'
  • Audience: api://AzureADTokenExchange by default.

Let's put them in the correct place.

Portal - Entra ID - App registrations - search for you sp - Manage/Certificates & secrets - Federated credentials - +Add credential

Add federated credentials

Here is what you should see:

Federated Credentials details

Believe me, I am tired too! But bear with me for one more step!

HCP Terraform Workspace Variables

The Azure and Entra ID sides are ready. The next thing is to define several variables for your HCP Terraform workspace to inform Terraform Cloud that you want it using OIDC.

But before doing this, I need to mention another caveat that HashiCorp mentions in their documentation.

Here is the quote:

Make sure that you’re passing values for the subscription_id and tenant_id arguments into the provider configuration block or setting the ARM_SUBSCRIPTION_ID and ARM_TENANT_ID variables in your workspace.

Make sure that you’re not setting values for client_id, use_oidc, or oidc_token in the provider or setting any of ARM_CLIENT_ID, ARM_USE_OIDC, ARM_OIDC_TOKEN.

So, simply speaking, your provider block should look like this:

provider "azurerm" {
features {}

tenant_id = var.tenant_id
subscription_id = var.subscription_id
}

(Unfortunately, dev.to stopped supporting my code block, so I had to use quotes above.)

If it is, we are ready to set up the variables!

Name Type Value Meaning
TFC_AZURE_PROVIDER_AUTH env true Enable OIDC authentication
TFC_AZURE_RUN_CLIENT_ID env 348c0fdc-b20f-4fe7-a79a-872068ff22fd The Client ID of the Service Principal you created earlier
tenant_id terraform 86abb60f-b63e-475e-85dd-9fa6e1d9f754 Entra ID Tenant ID, which you use
subscription_id terraform 971307eb-329d-47a2-b3f2-d424f4da5461 ID of the Azure subscription you use

Here is how it looks within HCP Terraform Workspace interface:

Workspace variables

And... Congrats! You have done it!

Now every push to your GitLab dev-tfc branch will initiate an HCP Terraform Workspace pipeline run, which will definitely deploy your resources.

And an unexpectedly nice thing... you will see an additional stage in your GitLab pipeline that will show the status of the HCP Terraform pipeline run.

GitLab pipeline run

What? You did not set up the VCS GitLab integration? Sorry, bro. Next time!

Results

That is how success looks on the HCP Terraform side:

HCP Terraform after success

And here is the resource in Azure:

Azure deployment success

Useful documents

Use dynamic credentials with the Azure provider
Flexible federated identity credentials (preview)


About identities and the services. For those with harmful intentions.

I am absolutely sure that knowledge of the IDs of Tenant, Subscription, and even Service Principal will not help to get access to this infrastructure.

Despite that, I usually delete the identities before publishing my post. So, don't bother.

Top comments (0)