In the rapidly evolving world of cloud computing, maintaining secure access to cloud resources is crucial. One area that often poses significant security risks is the storage of long-lived credentials. These credentials, if compromised, can lead to unauthorized access and severe data breaches. This issue is particularly relevant in the context of Azure, Microsoft’s cloud platform. While tools like HashiCorp’s Terraform can secure sensitive credentials as write-only variables, the use of long-lived credentials still necessitates regular audits to ensure they haven’t been compromised. Many organizations have policies in place to block such credentials due to the associated security risks.
A more secure alternative exists in the form of dynamic provider credentials offered by HashiCorp’s Cloud Platform (HCP) Terraform. This feature provides a robust method for authenticating to Azure by leveraging a native integration with OpenID Connect (OIDC). With dynamic provider credentials, Terraform can authenticate as a service principal and obtain temporary credentials for each run. Once the operation is completed, these credentials are discarded. This approach significantly reduces the risk of credential compromise since the credentials are short-lived and thus less useful to potential attackers.
Understanding Dynamic Credentials for Azure
Dynamic provider credentials represent a paradigm shift in how cloud authentication is managed. Rather than relying on static credentials that remain valid indefinitely, dynamic credentials are generated for each operation, ensuring that they are only valid for a limited time. This setup enhances security by narrowing the window of opportunity for unauthorized access.
In this article, we will delve into the concept of dynamic credentials for Azure and provide a step-by-step guide to setting them up using HCP Terraform. This tutorial will cover the essential steps needed to configure dynamic provider credentials, including establishing a trust relationship between HCP Terraform and Azure, configuring Azure platform access, and setting up resources on HCP Terraform to utilize these dynamic credentials.
Setting Up Dynamic Credentials for Azure
To start using dynamic credentials with Azure, you must follow three primary steps:
- Establish a trust relationship between HCP Terraform and Azure.
- Configure access to the Azure platform.
- Set up resources on HCP Terraform to use dynamic credentials.
Step 1: Establish a Trust Relationship
The first step involves setting up a trust relationship between HCP Terraform and Azure. This is crucial for enabling Terraform to authenticate with Azure and obtain temporary credentials necessary for provisioning resources. This process requires the use of several Terraform providers, including
azurerm
,azuread
, andtfe
.The configuration begins by creating an application in Azure Entra ID and a corresponding service principal:
hcl<br /> resource "azuread_application" "hcp_terraform" {<br /> display_name = "hcp-terraform-azure-oidc"<br /> }<br /> <br /> resource "azuread_service_principal" "hcp_terraform" {<br /> client_id = azuread_application.hcp_terraform.client_id<br /> }<br />
Next, you establish an OIDC trust relationship using federated identity credentials. This setup involves specifying an audience, issuer, and subject as follows:
- Audience:
api://AzureADTokenExchange
- Issuer:
https://app.terraform.io
- Subject: This includes details from your HCP Terraform environment, such as organization, project, workspace, and run phase.
It’s recommended to use federated credentials for specific purposes, allowing the use of different service principals for distinct Terraform operations, such as plan and apply.
Step 2: Configure Azure Platform Access
Once the trust relationship is set up, the next step is configuring Azure platform access. This involves assigning roles to the service principal, allowing it to perform necessary actions on Azure. In this tutorial, the Storage Account Contributor role is assigned to enable management of storage accounts. Additionally, a custom role is defined for creating resource groups:
hcl<br /> resource "azurerm_role_definition" "resource_group_creator" {<br /> name = "Resource Group Creator"<br /> scope = data.azurerm_subscription.current.id<br /> <br /> permissions {<br /> actions = [<br /> "*/read",<br /> "Microsoft.Resources/subscriptions/resourceGroups/write",<br /> ]<br /> }<br /> <br /> assignable_scopes = [<br /> data.azurerm_subscription.current.id,<br /> ]<br /> }<br /> <br /> resource "azurerm_role_assignment" "resource_group_creator" {<br /> scope = data.azurerm_subscription.current.id<br /> principal_id = azuread_service_principal.hcp_terraform.object_id<br /> role_definition_id = azurerm_role_definition.resource_group_creator.role_definition_resource_id<br /> }<br />
Step 3: Configure Resources on HCP Terraform
The final step is to configure resources on HCP Terraform to use dynamic credentials. This involves creating a project and a workspace within HCP Terraform and setting the necessary environment variables for dynamic authentication:
hcl<br /> resource "tfe_project" "default" {<br /> name = "demo-project"<br /> }<br /> <br /> resource "tfe_workspace" "default" {<br /> name = "demo-workspace"<br /> project_id = tfe_project.default.id<br /> }<br /> <br /> resource "tfe_variable" "tfc_azure_provider_auth" {<br /> key = "TFC_AZURE_PROVIDER_AUTH"<br /> value = "true"<br /> category = "env"<br /> workspace_id = tfe_workspace.default.id<br /> }<br /> <br /> resource "tfe_variable" "tfc_azure_run_client_id" {<br /> sensitive = true<br /> key = "TFC_AZURE_RUN_CLIENT_ID"<br /> value = azuread_service_principal.hcp_terraform.client_id<br /> category = "env"<br /> workspace_id = tfe_workspace.default.id<br /> }<br />
Utilizing Dynamic Provider Credentials
Once the dynamic provider credentials are configured, you can leverage them to provision resources on Azure. Importantly, you do not need to define authentication details within the provider block of your Terraform configuration. Instead, you share the variable set containing the Azure service principal details with an HCP Terraform workspace, which automatically provides access to Azure.
HCP Terraform accomplishes this by interacting with Azure at runtime to obtain temporary credentials based on the environment variables from the shared variable set. This secure approach allows for scalable access management within HCP Terraform, where access can be delegated from one workspace to another while ensuring precise restrictions on Azure access.
The service principal, equipped with roles such as Storage Account Contributor and Resource Group Creator, can now be used to create infrastructure on Azure. Below is a sample Terraform configuration that can be deployed using the established trust relationship:
hcl<br /> provider "azurerm" {<br /> features {}<br /> use_cli = false<br /> subscription_id = "xxxxxxx"<br /> tenant_id = "xxxxxxx"<br /> }<br /> <br /> resource "random_string" "suffix" {<br /> length = 10<br /> upper = false<br /> special = false<br /> }<br /> <br /> resource "azurerm_resource_group" "default" {<br /> name = "rg-demo-${random_string.suffix.result}"<br /> location = "westeurope"<br /> }<br /> <br /> resource "azurerm_storage_account" "test" {<br /> name = "st${random_string.suffix.result}"<br /> resource_group_name = azurerm_resource_group.default.name<br /> location = azurerm_resource_group.default.location<br /> account_tier = "Standard"<br /> account_replication_type = "LRS"<br /> }<br />
Scaling Dynamic Credentials
To scale this approach, you can establish a pattern where multiple HCP Terraform workspaces configure dynamic provider credentials for other workspaces. This allows platform teams to create workspaces with pre-configured Azure authentication, scoped to specific service principals for each team.
For each workspace, an HCP Terraform variable set is created containing environment variables like
TFC_AZURE_PROVIDER_AUTH
andTFC_AZURE_RUN_CLIENT_ID
. These credentials are injected into the provider to grant access to Azure APIs as permitted by the service principal’s permissions.Here’s how you can set up a variable set for a team (e.g., "Team A"):
hcl<br /> resource "tfe_variable_set" "oidc_team_a_dev" {<br /> name = "oidc-team-a-dev"<br /> description = "OIDC federation configuration for team A (dev)"<br /> organization = "XXXXXXXXXXXXXXX"<br /> }<br /> <br /> resource "tfe_variable" "tfc_azure_provider_auth" {<br /> key = "TFC_AZURE_PROVIDER_AUTH"<br /> value = "true"<br /> category = "env"<br /> variable_set_id = tfe_variable_set.oidc_team_a_dev.id<br /> }<br /> <br /> resource "tfe_variable" "tfc_azure_run_client_id" {<br /> sensitive = true<br /> key = "TFC_AZURE_RUN_CLIENT_ID"<br /> value = azuread_service_principal.team_a_dev.client_id<br /> category = "env"<br /> variable_set_id = tfe_variable_set.oidc_team_a_dev.id<br /> }<br />
Finally, share the variable set with Team A by connecting it to their development workspace. This ensures that the targeted workspace receives and uses the environment variables, allowing HCP Terraform to automatically obtain and inject the temporary credentials:
hcl<br /> resource "tfe_workspace_variable_set" "oidc_team_a_dev" {<br /> variable_set_id = tfe_variable_set.oidc_team_a_dev.id<br /> workspace_id = "ws-XXXXXXXXXXXXXXX"<br /> }<br />
For each team requiring Azure access, similar resources should be set up, along with configuring Azure RBAC permissions for each service principal.
Further Learning
To deepen your understanding of using OIDC federation with Microsoft Entra ID and secure access to Azure from HCP Terraform, consider exploring resources such as Use dynamic credentials with the Azure provider and the OIDC federation documentation. For a comprehensive example of configuring the Azure OIDC identity provider, visit this GitHub repository.
- Audience:
For more Information, Refer to this article.