Commit 09a30ec5 authored by Alexis Deruelle's avatar Alexis Deruelle Committed by Cédric OLIVIER
Browse files

doc: add OIDC setup instructions for azurerm provider [skip-ci]

parent 3c1e9416
Loading
Loading
Loading
Loading
+192 −0
Original line number Diff line number Diff line
@@ -888,3 +888,195 @@ include:
      # specific OIDC role ARN for prod
      aws-prod-oidc-role-arn: "arn:aws:iam::222222222222:role/cicd-role"
```

## Azure authentication with OIDC

The Terraform template supports authenticating to Azure using OpenID Connect (OIDC)
without requiring a dedicated variant.
This approach leverages [GitLab's ID tokens](https://docs.gitlab.com/ci/secrets/id_token_authentication/)
and the [Azure Provider's OIDC support](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/guides/service_principal_oidc).

### Prerequisites

Before using OIDC authentication with Azure, you must:

1. Configure [Workload Identity Federation between GitLab and Azure](https://docs.gitlab.com/ci/cloud_services/azure/)
   (following the GitLab guide)
2. Create a Service Principal in Azure with appropriate permissions
3. Configure the federated credential on your Service Principal to trust your GitLab instance

### Configuration

#### Step 1: Configure GitLab to generate the ID token

Add the following to your `.gitlab-ci.yml` to generate an ID token for Azure authentication:

```yaml
.tf-base:
  id_tokens:
    ARM_OIDC_TOKEN:
      aud: api://AzureADTokenExchange  # Prefered over GitLab instance URL[2]
```

The `.tf-base` job is the base job that all Terraform jobs inherit from,
so this configuration will apply to all Terraform operations.

:bulb: Audience `api://AzureADTokenExchange` is the [recommended value][2]
that tells the Microsoft API to accept the aud claim in the incoming token.

[2]: https://learn.microsoft.com/en-us/entra/workload-id/workload-identity-federation-create-trust?pivots=identity-wif-apps-methods-azcli#:~:text=600%20characters.%20The-,recommended%20value,-is%20%22api%3A//AzureADTokenExchange

#### Step 2: Configure the Azure Provider in your Terraform code

In your Terraform configuration files,
configure the `azurerm` provider to use OIDC authentication:

```terraform
provider "azurerm" {
  features {}

  # OIDC authentication settings - use_oidc MUST be set to true
  use_oidc        = true                # Required for OIDC authentication
  client_id       = var.client_id       # Your Service Principal's Application (client) ID
  tenant_id       = var.tenant_id       # Your Azure AD tenant ID
  subscription_id = var.subscription_id # Your Azure subscription ID

  # Optional: only required when your Service Principal lacks permissions to register Resource Providers
  resource_provider_registrations = "none"
}
```

:warning: **Important**: The `use_oidc = true` parameter is **required** for OIDC authentication to work.
Without it, the provider will not attempt to authenticate using the OIDC token.
See the [Azure Provider OIDC documentation](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/guides/service_principal_oidc)
for more details.

#### Step 3: Set the required Terraform variables

Define the required variables as GitLab CI/CD variables:

* `TF_VAR_client_id`: Your Azure Service Principal's Application (client) ID
* `TF_VAR_tenant_id`: Your Azure AD tenant ID
* `TF_VAR_subscription_id`: Your Azure subscription ID

:bulb: **Tip**: Use [GitLab CI/CD variables](https://docs.gitlab.com/ci/variables/#for-a-project) to manage these values.
Mark them as **masked** to prevent them from appearing in logs.

### Multiple environments with different credentials

If you need to use different Service Principals for different environments
(e.g., separate credentials for production),
use environment-specific `.tfvars` files.

The template will automatically apply the appropriate `.tfvars` file based on the deployment environment.
In your `.gitlab-ci.yml`, you only need to configure the ID token (see example in the next section).

### Complete example

Here's a complete example combining all the pieces:

**`.gitlab-ci.yml`:**
```yaml
include:
  - component: $CI_SERVER_FQDN/to-be-continuous/terraform/gitlab-ci-terraform@8.1.2
    inputs:
      image: docker.io/hashicorp/terraform:latest
      staging-enabled: true
      prod-enabled: true

.tf-base:
  id_tokens:
    ARM_OIDC_TOKEN:
      aud: api://AzureADTokenExchange
```

**`production.env.tfvars`:**
```hcl
client_id       = "44444444-4444-4444-4444-444444444444"
tenant_id       = "55555555-5555-5555-5555-555555555555"
subscription_id = "66666666-6666-6666-6666-666666666666"
```

**`staging.env.tfvars`:**
```hcl
client_id       = "11111111-1111-1111-1111-111111111111"
tenant_id       = "22222222-2222-2222-2222-222222222222"
subscription_id = "33333333-3333-3333-3333-333333333333"
```

**`main.tf`:**
```terraform
terraform {
  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "~> 3.0"
    }
  }
}

provider "azurerm" {
  features {}

  use_oidc        = true  # Required for OIDC authentication
  client_id       = var.client_id
  tenant_id       = var.tenant_id
  subscription_id = var.subscription_id
  
  # Only set this if your Service Principal cannot register Resource Providers
  resource_provider_registrations = "none"
}
```

**`variables.tf`:**
```terraform
variable "client_id" {
  description = "Azure Service Principal client ID"
  type        = string
}

variable "tenant_id" {
  description = "Azure AD tenant ID"
  type        = string
}

variable "subscription_id" {
  description = "Azure subscription ID"
  type        = string
}
```

### Troubleshooting

#### Authentication fails with `AADSTS700016: Application not found`

This indicate that de Service Principal for the registered Application
is not properly configured.

Verify that:
- Your Service Principal's Application ID (`client_id`) is correct
- The federated credential is properly configured on the Service Principal
- The `aud` claim in your ID token configuration matches what's configured in Azure

#### Error `The client '...' with object id '...' does not have authorization to perform action`

Ensure your Service Principal has been granted the appropriate Azure RBAC roles
on the target subscription or resource groups.

#### Authentication fails with `AADSTS7002131: No matching federated identity record found`

This error indicates that the federated identity credential configured in Azure
doesn't match the JWT token claims that GitLab is presenting.

Verify that:
- The federated credential's **Subject** field matches your GitLab project path pattern
  (e.g., `project_path:mygroup/myproject:ref_type:branch:ref:main` for the main branch,
  or use a wildcard like `project_path:mygroup/myproject:ref_type:branch:ref:*`
  to match all branches)
- The **Audience** configured in Azure matches the `aud` value
  in your `.gitlab-ci.yml` ID token configuration

#### Provider initialization is slow or fails with resource provider errors

Try adding `resource_provider_registrations = "none"` to your provider configuration
if your Service Principal doesn't have permissions to register Resource Providers.
 No newline at end of file