393 lines
13 KiB
Plaintext
393 lines
13 KiB
Plaintext
---
|
|
layout: docs
|
|
page_title: Azure - Auth Methods
|
|
description: |-
|
|
The azure auth method plugin allows automated authentication of Azure Active
|
|
Directory.
|
|
---
|
|
|
|
# Azure Auth Method
|
|
|
|
The `azure` auth method allows authentication against Vault using
|
|
Azure Active Directory credentials. It treats Azure as a Trusted Third Party
|
|
and expects a [JSON Web Token (JWT)](https://tools.ietf.org/html/rfc7519)
|
|
signed by Azure Active Directory for the configured tenant.
|
|
|
|
This method supports authentication for system-assigned and user-assigned
|
|
managed identities. See [Azure Managed Service Identity (MSI)](https://docs.microsoft.com/en-us/azure/active-directory/managed-service-identity/overview) for more information about these resources.
|
|
|
|
~> System-assigned identities are unique to every virtual machine in Azure. If the
|
|
virtual machines using Azure auth are recreated frequently, using system-assigned
|
|
identities could result in a lot of Vault entities. For environments with high ephemeral
|
|
workloads, user-assigned identities are recommended.
|
|
|
|
## Prerequisites:
|
|
|
|
The following documentation assumes that the method has been
|
|
[mounted](/docs/plugin) at `auth/azure`.
|
|
|
|
- A configured [Azure AD application](https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-integrating-applications) which is used as the resource for generating MSI access tokens.
|
|
- Client credentials (shared secret) for accessing the Azure Resource Manager with read access to compute endpoints. See [Azure AD Service to Service Client Credentials](https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-protocols-oauth-service-to-service)
|
|
|
|
Required Azure API permissions to be granted to Vault user:
|
|
|
|
- `Microsoft.Compute/virtualMachines/*/read`
|
|
- `Microsoft.Compute/virtualMachineScaleSets/*/read`
|
|
|
|
_NOTE:_ The above permissions are only required when the associated vm\* parameters are used on login. Please see the [API doc](https://www.vaultproject.io/api-docs/auth/azure#login) for more details.
|
|
|
|
If Vault is hosted on Azure, Vault can use MSI to access Azure instead of a shared secret. MSI must be [enabled](https://docs.microsoft.com/en-us/azure/active-directory/managed-service-identity/qs-configure-portal-windows-vm) on the VMs hosting Vault.
|
|
|
|
The next sections review how the authN/Z workflows work. If you
|
|
have already reviewed these sections, here are some quick links to:
|
|
|
|
- [Usage](/docs/secrets/azure#usage)
|
|
- [API documentation](/api/auth/azure) docs.
|
|
|
|
## Authentication
|
|
|
|
### Via the CLI
|
|
|
|
The default path is `/auth/azure`. If this auth method was enabled at a different
|
|
path, specify `auth/my-path/login` instead.
|
|
|
|
```shell-session
|
|
$ vault write auth/azure/login \
|
|
role="dev-role" \
|
|
jwt="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." \
|
|
subscription_id="12345-..." \
|
|
resource_group_name="test-group" \
|
|
vm_name="test-vm"
|
|
```
|
|
|
|
The `role` and `jwt` parameters are required. When using `bound_service_principal_ids` and `bound_group_ids` in the token roles, all the information is required in the JWT (except for _vm_name_ and _vmss_name_). When using other `bound_*` parameters, calls to Azure APIs will be made and subscription id, resource group name, and vm name/vmss_name are all required and can be obtained through instance metadata.
|
|
|
|
For example:
|
|
|
|
```shell-session
|
|
$ vault write auth/azure/login role="dev-role" \
|
|
jwt="$(curl -s 'http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https%3A%2F%2Fmanagement.azure.com%2F' -H Metadata:true | jq -r '.access_token')" \
|
|
subscription_id=$(curl -s -H Metadata:true "http://169.254.169.254/metadata/instance?api-version=2017-08-01" | jq -r '.compute | .subscriptionId') \
|
|
resource_group_name=$(curl -s -H Metadata:true "http://169.254.169.254/metadata/instance?api-version=2017-08-01" | jq -r '.compute | .resourceGroupName') \
|
|
vm_name=$(curl -s -H Metadata:true "http://169.254.169.254/metadata/instance?api-version=2017-08-01" | jq -r '.compute | .name')
|
|
```
|
|
|
|
### Via the API
|
|
|
|
The default endpoint is `auth/azure/login`. If this auth method was enabled
|
|
at a different path, use that value instead of `azure`.
|
|
|
|
```shell-session
|
|
$ curl \
|
|
--request POST \
|
|
--data '{"role": "dev-role", "jwt": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."}' \
|
|
https://127.0.0.1:8200/v1/auth/azure/login
|
|
```
|
|
|
|
The response will contain the token at `auth.client_token`:
|
|
|
|
```json
|
|
{
|
|
"auth": {
|
|
"client_token": "f33f8c72-924e-11f8-cb43-ac59d697597c",
|
|
"accessor": "0e9e354a-520f-df04-6867-ee81cae3d42d",
|
|
"policies": ["default", "dev", "prod"],
|
|
"lease_duration": 2764800,
|
|
"renewable": true
|
|
}
|
|
}
|
|
```
|
|
|
|
## Configuration
|
|
|
|
Auth methods must be configured in advance before machines can authenticate.
|
|
These steps are usually completed by an operator or configuration management
|
|
tool.
|
|
|
|
### Via the CLI
|
|
|
|
1. Enable Azure authentication in Vault:
|
|
|
|
```text
|
|
$ vault auth enable azure
|
|
```
|
|
|
|
1. Configure the Azure auth method:
|
|
|
|
```text
|
|
$ vault write auth/azure/config \
|
|
tenant_id=7cd1f227-ca67-4fc6-a1a4-9888ea7f388c \
|
|
resource=https://management.azure.com/ \
|
|
client_id=dd794de4-4c6c-40b3-a930-d84cd32e9699 \
|
|
client_secret=IT3B2XfZvWnfB98s1cie8EMe7zWg483Xy8zY004=
|
|
```
|
|
|
|
For the complete list of configuration options, please see the API
|
|
documentation.
|
|
|
|
1. Create a role:
|
|
|
|
```text
|
|
$ vault write auth/azure/role/dev-role \
|
|
policies="prod,dev" \
|
|
bound_subscription_ids=6a1d5988-5917-4221-b224-904cd7e24a25 \
|
|
bound_resource_groups=vault
|
|
```
|
|
|
|
Roles are associated with an authentication type/entity and a set of Vault
|
|
policies. Roles are configured with constraints specific to the
|
|
authentication type, as well as overall constraints and configuration for
|
|
the generated auth tokens.
|
|
|
|
For the complete list of role options, please see the [API documentation](/api/auth/azure).
|
|
|
|
### Via the API
|
|
|
|
1. Enable Azure authentication in Vault:
|
|
|
|
```sh
|
|
$ curl \
|
|
--header "X-Vault-Token: ..." \
|
|
--request POST \
|
|
--data '{"type": "azure"}' \
|
|
https://127.0.0.1:8200/v1/sys/auth/azure
|
|
```
|
|
|
|
1. Configure the Azure auth method:
|
|
|
|
```sh
|
|
$ curl \
|
|
--header "X-Vault-Token: ..." \
|
|
--request POST \
|
|
--data '{"tenant_id": "...", "resource": "..."}' \
|
|
https://127.0.0.1:8200/v1/auth/azure/config
|
|
```
|
|
|
|
1. Create a role:
|
|
|
|
```sh
|
|
$ curl \
|
|
--header "X-Vault-Token: ..." \
|
|
--request POST \
|
|
--data '{"policies": ["dev", "prod"], ...}' \
|
|
https://127.0.0.1:8200/v1/auth/azure/role/dev-role
|
|
```
|
|
|
|
### Plugin Setup
|
|
|
|
~> The following section is only relevant if you decide to enable the azure auth
|
|
method as an external plugin. The azure plugin method is integrated into Vault as
|
|
a builtin method by default.
|
|
|
|
Assuming you have saved the binary `vault-plugin-auth-azure` to some folder and
|
|
configured the [plugin directory](/docs/internals/plugins#plugin-directory)
|
|
for your server at `path/to/plugins`:
|
|
|
|
1. Enable the plugin in the catalog:
|
|
|
|
```text
|
|
$ vault write sys/plugins/catalog/auth/azure-auth \
|
|
command="vault-plugin-auth-azure" \
|
|
sha256="..."
|
|
```
|
|
|
|
1. Enable the azure auth method as a plugin:
|
|
|
|
```text
|
|
$ vault auth enable -path=azure azure-auth
|
|
```
|
|
|
|
## Azure Debug Logs
|
|
|
|
The Azure auth plugin supports debug logging which includes additional information
|
|
about requests and responses from the Azure API.
|
|
|
|
To enable the Azure debug logs, set the following environment variable on the Vault
|
|
server:
|
|
|
|
```shell
|
|
AZURE_GO_SDK_LOG_LEVEL=DEBUG
|
|
```
|
|
|
|
## API
|
|
|
|
The Azure Auth Plugin has a full HTTP API. Please see the [API documentation](/api/auth/azure) for more details.
|
|
|
|
## Code Example
|
|
|
|
The following code snippet demonstrates the Azure auth method to authenticate
|
|
with Vault.
|
|
|
|
<CodeTabs heading="azure auth example">
|
|
|
|
<CodeBlockConfig lineNumbers>
|
|
|
|
```go
|
|
package main
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
vault "github.com/hashicorp/vault/api"
|
|
auth "github.com/hashicorp/vault/api/auth/azure"
|
|
)
|
|
|
|
// Fetches a key-value secret (kv-v2) after authenticating to Vault via Azure authentication.
|
|
// This example assumes you have a configured Azure AD Application.
|
|
func getSecretWithAzureAuth() (string, error) {
|
|
config := vault.DefaultConfig() // modify for more granular configuration
|
|
|
|
client, err := vault.NewClient(config)
|
|
if err != nil {
|
|
return "", fmt.Errorf("unable to initialize Vault client: %w", err)
|
|
}
|
|
|
|
azureAuth, err := auth.NewAzureAuth(
|
|
"dev-role-azure",
|
|
)
|
|
if err != nil {
|
|
return "", fmt.Errorf("unable to initialize Azure auth method: %w", err)
|
|
}
|
|
|
|
authInfo, err := client.Auth().Login(context.TODO(), azureAuth)
|
|
if err != nil {
|
|
return "", fmt.Errorf("unable to login to Azure auth method: %w", err)
|
|
}
|
|
if authInfo == nil {
|
|
return "", fmt.Errorf("no auth info was returned after login")
|
|
}
|
|
|
|
// get secret
|
|
secret, err := client.Logical().Read("kv-v2/data/creds")
|
|
if err != nil {
|
|
return "", fmt.Errorf("unable to read secret: %w", err)
|
|
}
|
|
|
|
data, ok := secret.Data["data"].(map[string]interface{})
|
|
if !ok {
|
|
return "", fmt.Errorf("data type assertion failed: %T %#v", secret.Data["data"], secret.Data["data"])
|
|
}
|
|
|
|
// data map can contain more than one key-value pair,
|
|
// in this case we're just grabbing one of them
|
|
key := "password"
|
|
value, ok := data[key].(string)
|
|
if !ok {
|
|
return "", fmt.Errorf("value type assertion failed: %T %#v", data[key], data[key])
|
|
}
|
|
|
|
return value, nil
|
|
}
|
|
|
|
```
|
|
</CodeBlockConfig>
|
|
|
|
<CodeBlockConfig lineNumbers>
|
|
|
|
```cs
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Net;
|
|
using System.Net.Http;
|
|
using System.Text;
|
|
using Newtonsoft.Json;
|
|
using VaultSharp;
|
|
using VaultSharp.V1.AuthMethods;
|
|
using VaultSharp.V1.AuthMethods.Azure;
|
|
using VaultSharp.V1.Commons;
|
|
|
|
namespace Examples
|
|
{
|
|
public class AzureAuthExample
|
|
{
|
|
public class InstanceMetadata
|
|
{
|
|
public string name { get; set; }
|
|
public string resourceGroupName { get; set; }
|
|
public string subscriptionId { get; set; }
|
|
}
|
|
|
|
const string MetadataEndPoint = "http://169.254.169.254/metadata/instance?api-version=2017-08-01";
|
|
const string AccessTokenEndPoint = "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://management.azure.com/";
|
|
|
|
/// <summary>
|
|
/// Fetches a key-value secret (kv-v2) after authenticating to Vault via Azure authentication.
|
|
/// This example assumes you have a configured Azure AD Application.
|
|
/// </summary>
|
|
public string GetSecretWithAzureAuth()
|
|
{
|
|
string vaultAddr = Environment.GetEnvironmentVariable("VAULT_ADDR");
|
|
if(String.IsNullOrEmpty(vaultAddr))
|
|
{
|
|
throw new System.ArgumentNullException("Vault Address");
|
|
}
|
|
|
|
string roleName = Environment.GetEnvironmentVariable("VAULT_ROLE");
|
|
if(String.IsNullOrEmpty(roleName))
|
|
{
|
|
throw new System.ArgumentNullException("Vault Role Name");
|
|
}
|
|
|
|
string jwt = GetJWT();
|
|
InstanceMetadata metadata = GetMetadata();
|
|
|
|
IAuthMethodInfo authMethod = new AzureAuthMethodInfo(roleName: roleName, jwt: jwt, subscriptionId: metadata.subscriptionId, resourceGroupName: metadata.resourceGroupName, virtualMachineName: metadata.name);
|
|
var vaultClientSettings = new VaultClientSettings(vaultAddr, authMethod);
|
|
|
|
IVaultClient vaultClient = new VaultClient(vaultClientSettings);
|
|
|
|
// We can retrieve the secret from the VaultClient object
|
|
Secret<SecretData> kv2Secret = null;
|
|
kv2Secret = vaultClient.V1.Secrets.KeyValue.V2.ReadSecretAsync(path: "/creds").Result;
|
|
|
|
var password = kv2Secret.Data.Data["password"];
|
|
|
|
return password.ToString();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Query Azure Resource Manage for metadata about the Azure instance
|
|
/// </summary>
|
|
private InstanceMetadata GetMetadata()
|
|
{
|
|
HttpWebRequest metadataRequest = (HttpWebRequest)WebRequest.Create(MetadataEndPoint);
|
|
metadataRequest.Headers["Metadata"] = "true";
|
|
metadataRequest.Method = "GET";
|
|
|
|
HttpWebResponse metadataResponse = (HttpWebResponse)metadataRequest.GetResponse();
|
|
|
|
StreamReader streamResponse = new StreamReader(metadataResponse.GetResponseStream());
|
|
string stringResponse = streamResponse.ReadToEnd();
|
|
var resultsDict = JsonConvert.DeserializeObject<Dictionary<string, InstanceMetadata>>(stringResponse);
|
|
|
|
return resultsDict["compute"];
|
|
}
|
|
|
|
/// <summary>
|
|
/// Query Azure Resource Manager (ARM) for an access token
|
|
/// </summary>
|
|
private string GetJWT()
|
|
{
|
|
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(AccessTokenEndPoint);
|
|
request.Headers["Metadata"] = "true";
|
|
request.Method = "GET";
|
|
|
|
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
|
|
|
|
// Pipe response Stream to a StreamReader and extract access token
|
|
StreamReader streamResponse = new StreamReader(response.GetResponseStream());
|
|
string stringResponse = streamResponse.ReadToEnd();
|
|
var resultsDict = JsonConvert.DeserializeObject<Dictionary<string, string>>(stringResponse);
|
|
|
|
return resultsDict["access_token"];
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
</CodeBlockConfig>
|
|
|
|
</CodeTabs>
|