Rotate Azure auth method root credentials with Vault CLI
Challenge
Operators with a need to rotate client secrets in the Azure Auth Engine mounts and Secrets Engine on a routine basis are currently limited to the Vault API. Until recently this was not available as a dedicated CLI command.
Solution
Vault 1.13 adds a rotate-root
command to the Vault CLI. Now the Vault CLI has a dedicated command to generate a new client secret for the root account defined in the configuration for Azure Auth Engine mounts and Secrets Engine. The generated value will be known only by Vault.
Prerequisites
- Azure Subscription.
- Vault version 1.13 binary.
- Terraform CLI to provision Vault server.
- Azure CLI.
- jq - used by Terraform.
- ssh or PUTTY installed.
- You should generate a new RSA key for this tutorial and delete as you clean up.
Set up environment
Open a new window and start up Vault as a local server.
$ vault server -dev -dev-root-token-id root==> Vault server configuration:...
Open a second window and add a
VAULT_ADDR
andVAULT_TOKEN
environment variable.$ export VAULT_ADDR='http://127.0.0.1:8200';export VAULT_TOKEN=root
To use the Terraform configuration in this lab you need to set up authentication to Azure.
CLI is easiest method, but feel free to use other methods as detailed for the Azure provider.
$ az loginA web browser has been opened at https://login.microsoftonline.com/organizations/oauth2/v2.0/authorize. Please continue the login in the web browser. If no web browser is available or if the web browser fails to open, use device code flow with `az login --use-device-code`.
Follow the directions as given by the CLI.
Open a second window and clone the
learn-vault-azure-rotate-root-creds
repository.$ git clone https://github.com/hashicorp-education/learn-azure-rotate-root-creds.git
Go into the directory you just created.
$ cd learn-azure-rotate-root-creds
Initialize the terraform in that directory.
$ terraform init
Create a new RSA key-pair
$ ssh-keygen -f $HOME/.ssh/myAzureVM_rsa -t rsa -b 4096
You will need a environment variables for the path of these public and private keys.
$ export TF_VAR_ssh_public_key_path=$HOME/.ssh/myAzureVM_rsa.pub; export TF_VAR_ssh_private_key_path=$HOME/.ssh/myAzureVM_rsa
Terraform configuration
Create the VM and supporting infrastructure.
$ terraform apply -auto-approve ... Apply complete! Resources: 18 added, 0 changed, 0 destroyed. Outputs: access_token_jwt = <sensitive>client_id = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXX"client_secret = <sensitive>resource_group_name = "vault_azure_tests_XXXXXXXX"resource_id = "/subscriptions/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXX/resourceGroups/vault_azure_tests_XXXXXXXX/providers/Microsoft.Compute/virtualMachines/vault-azure-tests-vm"subscription_id = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXX"tenant_id = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXX"vm_ip_address = "NN.NN.NNN.NNNN"vm_name = "vault-azure-tests-vm"
Vault configuration
The Terraform configuration in the earlier section also created a file called
local_environment_setup.sh
. Source this file and set up the environment variables needed to configure the Azure plugin for Vault.$ source local_environment_setup.sh
Enable Azure plugin.
$ vault auth enable azureSuccess! Enabled azure auth method at: azure/
Write the azure auth configuration.
$ vault write auth/azure/config \ tenant_id="${TENANT_ID}" \ client_id="${CLIENT_ID}" \ client_secret="${CLIENT_SECRET}" \ resource="https://management.azure.com/"
Write the role.
$ vault write auth/azure/role/rotation-role \ bound_subscription_ids="${SUBSCRIPTION_ID}" \ bound_resource_groups="${RESOURCE_GROUP_NAME}"
Login using the access token and VM name.
$ vault write auth/azure/login \ role="rotation-role" \ jwt="${ACCESS_TOKEN_JWT}" \ subscription_id="${SUBSCRIPTION_ID}" \ resource_group_name="${RESOURCE_GROUP_NAME}" \ vm_name="${VM_NAME}"
The output should resemble the following:
Key Value--- -----token hvs.XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXtoken_accessor XXXXXXXXXXXXXXXXXXXXXXtoken_duration 768htoken_renewable truetoken_policies ["default"]identity_policies []policies ["default"]token_meta_vm_name vault-azure-tests-vmtoken_meta_resource_group_name vault_azure_tests_XXXXXXXXtoken_meta_role rotation-roletoken_meta_subscription_id XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXX
Azure UI
Now that you have created application and configured Vault, take a look at the secret in the Azure UI.
Open Microsoft Azure and sign in.
Go to the Search field and type in
Azure Active Directory
, then click on the same after it appears.On the left nav choose App Registrations.
In the section that opens to right, choose All Applications tab. There will be a vault_azure_tests displayed.
Click on the vault_azure_tests link and open the Overview. On the left navigation bar, click on Certificates and Secrets.
Look at the secret listed on that page, and for future reference note down the unmasked portion of the secret.
Compare it to the
CLIENT_SECRET
environment variable that was set earlier. The first three characters should be the same.$ echo $CLIENT_SECRETrSuXX&LyBVLF%DGML$$@CnXXXXXEEEESFYVItCDdLp
Keeping the Credentials and Secrets Window open, go back to your terminal and rotate the credentials.
$ vault write -force auth/azure/rotate-root
Return to the Credentials and Secrets Window and reload the screen.
It takes a while to sync, but after a reload or two you will to see two secrets. This is because it takes a few minutes for all the Azure regions to sync.
Wait a few minutes and reload the page again, notice the original secret has disappeared. Only the new secrets is listed.
Next steps
You have created simple Azure infrastructure with a client secret. Then you started Vault, configured the Azure secrets engine and finally learned how to use the Azure Vault plugin to rotate the client credentials of an Azure Active Directory Application.
Clean up
Remove the infrastructure you created.
$ terraform apply -destroy -auto-approve...Apply complete! Resources: 0 added, 0 changed, 17 destroyed.
Unset the environment variables.
$ unset TF_VAR_ssh_public_key_path; unset TF_VAR_ssh_private_key_path;unset CLIENT_SECRET; unset ACCESS_TOKEN_JWT;unset VM_NAME; unset VM_IP_ADDRESS; unset RESOURCE_ID; unset RESOURCE_GROUP_NAME; unset SUBSCRIPTION_ID; unset TENANT_ID; unset CLIENT_ID;
Go to window with dev Vault server running and type in control-c (
^C
). You should notice the following:$ ^C==> Vault shutdown triggered2023-03-09T12:30:17.758-0600 [INFO] core: marked as sealed2023-03-09T12:30:17.759-0600 [INFO] core: pre-seal teardown starting2023-03-09T12:30:17.761-0600 [INFO] rollback: stopping rollback manager2023-03-09T12:30:17.765-0600 [INFO] core: pre-seal teardown complete2023-03-09T12:30:17.767-0600 [INFO] core: stopping cluster listeners2023-03-09T12:30:17.767-0600 [INFO] core.cluster-listener: forwarding rpc listeners stopped2023-03-09T12:30:17.920-0600 [INFO] core.cluster-listener: rpc listeners successfully shut down2023-03-09T12:30:17.920-0600 [INFO] core: cluster listeners successfully shut down2023-03-09T12:30:17.922-0600 [INFO] core: vault is sealed
Find the RSA Key Pair generated for this lab and delete it.
$ rm $HOME/.ssh/myAzureVM_rsa;rm $HOME/.ssh/myAzureVM_rsa.pub
References
- Azure Secrets Engine - Rotate Root API Call
- Azure Secret Engine
- Secure Access Azure SQL Database
- Key Management Secrets Engine with Azure Key Vault
- Azure Active Directory with OIDC Auth Method and External Groups
- Auto-unseal using Azure Key Vault
- Peering an Azure Virtual Network with HashiCorp Cloud Platform (HCP)