vault

Integrating Azure AD Identity with HashiCorp Vault — Part 1: Azure Application Auth via OIDC

Learn how to achieve user authentication to HashiCorp Vault with OIDC using Microsoft Azure AD as a central identity provider.

When applying a zero trust security mindset to applications and infrastructure, identity is the foundational component that the zero trust pillars are built on. Centrally managing secrets and identity are fundamental to the success of zero trust because managing secrets in multiple places with IP addresses quickly becomes cumbersome and error-prone. A single source of truth means a single control plane can be used to verify everything.

Using HashiCorp Vault's many secrets engines, short-lived credentials can be provisioned for most application and infrastructure components. As Vault manages and issues credentials, it brokers identity for almost everything from databases and message queues to public cloud platforms, including Microsoft Azure. Vault manages the entire lifecycle of the credential, acting as the centralized identity broker for these third-party platforms.

However, users and applications will still need to authenticate with Vault before they can request platform credentials. This first authentication is often called “secret zero”. Securely introducing secret zero to applications is one of the biggest challenges facing developers. There needs to be a way of providing this to the application without leaking it. This blog post will show you how Azure users with existing Azure Active Directory setups can configure an Azure application to facilitate authentication with Vault using OIDC. Part 2 of this series explains how to configure HashiCorp Vault’s OIDC auth method to use Azure as an identity provider. The third and final installment will demonstrate how Azure workloads can use their cloud-native identities to authenticate with Vault.

»Azure AD as an Identity Provider

While user and application identity can be provisioned and managed in Vault, many organizations operating in Azure will already have this in place using Azure Active Directory (AAD). With this context we can think of AAD as the identity provider (IdP).

Vault has the concept of auth methods, which is a plugin-based component allowing organizations to bring their own IdP to Vault.

The common way to achieve this for users is using OpenID Connect (OIDC), which allows clients to verify the identity of the end-user based on the authentication performed by an authorization server. In this case, once a user has authenticated to AAD, AAD will act as the authorization server. AAD will sign a JSON web token (JWT) and pass this JWT to Vault to authenticate there. This is made possible thanks to the JWT/OIDC auth method in Vault.

For virtual machines (VMs) and Azure-based applications, it works similarly using JWT under the hood. Identities provisioned by Azure, whether system-assigned or user-assigned, can use their JWTs signed by Azure to authenticate with Vault. These identities are attached to workloads in Azure. These workloads can then authenticate with Vault using the Azure auth method.

»Azure AD Application for OIDC

In order to configure Vault's OIDC auth method to use AAD as an OIDC provider, Vault needs to be registered as an application in AAD. This application identity is what Vault will use to authenticate with Azure to verify the signed JWTs and read any group claims within the token.

The application can be registered in the Azure portal or by using the Azure CLI. This registered application does not require any Microsoft Graph API permissions to work with Vault’s OIDC auth method.

To ease the process of registering the application in AAD, I have built a Terraform module that registers the application in AAD with the correct configuration. The module will also create a client_secret that Vault can use in combination with the client_id to authenticate with Azure.

This module was built using the recently released Terraform AzureAD provider 2.0.

provider "azuread" {}

module "application" {
  source  = "devops-rob/app-vault/azuread"
  version = "0.1.0"
}

output "display_name" {
  value = module.application.application_name
}

output "password" {
  value     = module.application.client_secret
  sensitive = true
}
provider "azuread" {}
 
module "application" {
  source  = "devops-rob/app-vault/azuread"
  version = "0.1.0"
}
 
output "display_name" {
  value = module.application.application_name
}
 
output "password" {
  value     = module.application.client_secret
  sensitive = true
}

For more information about how this workflow operates under the hood and some of the code behind the Terraform modules, check out The DevOps Lab where I met with Cloud Advocate, April Edwards from Microsoft for a deep dive on this topic.

»Summary

In this blog post, I illustrated how user and machine authentication can be achieved using AAD as a central IdP. I also explored how to use AAD to enable users and applications to authenticate with Vault using OIDC. Finally I looked at how to provision an application in AAD for Vault use as the first step of implementing OIDC authentication.

In part 2 of this blog series, I address how to configure Vault to use Azure as an OIDC provider.

Sign up for the latest HashiCorp news