Azure Linux VM使用Managed Identity获取Key-vault的Secret
在程序开发中,如何管理密码或Key,是一个开发人员都会碰到的问题。Azure的Managed Identity为基于Azure的开发提供了一种安全方便的方法。
Azure的Managed Identity为应用程序提供一个标识,可以在连接到支持 Azure Active Directory (Azure AD) 身份验证的资源时使用。应用程序可以使用托管标识来获取 Azure AD 令牌,而开发人员无需管理凭据。
前面几篇blog中介绍了如何获取Azure的Access Token,这里介绍通过Managed Identity,在Azure VM内方便获取Access Token的方法。这为基于Azure的一些应用提供了一个新的获取token的思路。
1 创建managed identity
az group create -n idtest -l westus2 az identity create -g idtest -n vhid01 |
2 创建基于managed identity的VM
subnet_id=$(az network vnet subnet list \ --vnet-name default-uswest2-vnet \ -g networkwatcherrg | jq -r .[0].id) nsg_id=$(az network nsg show -g networkwatcherrg \ -n default-uswest2-vnet-vlan11-nsg-westus2 | jq -r .id) az vm create -n idtest01 -g idtest -l westus2 \ --accelerated-networking true \ --image OpenLogic:CentOS:7_9:latest \ --os-disk-size-gb 128 \ --priority spot \ --size Standard_D2s_v5 \ --assign-identity vhid01 \ --subnet $subnet_id \ --nsg $nsg_id \ --authentication-type ssh \ --admin-username hengwei \ --public-ip-sku Standard \ --ssh-key-values ~/.ssh/id_rsa.pub --no-wait |
查看VM的identity属性:
$ az vm show -n idtest01 -g idtest | jq .identity { "principalId": null, "tenantId": null, "type": "UserAssigned", "userAssignedIdentities": { "/subscriptions/xxxx/resourceGroups/idtest/providers/Microsoft.ManagedIdentity/userAssignedIdentities/vhid01": { "clientId": "xxxxxxx-8af6-4dde-97fc-xxxxxxx", "principalId": "xxxxxxx-b2fc-4c12-984c-xxxxxxx" } } } |
3 对已有VM添加managed identity
创建无User identity的VM
az vm create -n idtest02 -g idtest -l westus2 \ --accelerated-networking true \ --image OpenLogic:CentOS:7_9:latest \ --os-disk-size-gb 128 \ --priority spot \ --size Standard_D2s_v5 \ --subnet $subnet_id \ --nsg $nsg_id \ --authentication-type ssh \ --admin-username hengwei \ --public-ip-sku Standard \ --ssh-key-values ~/.ssh/id_rsa.pub --no-wait |
对于创建的VM idtest02不包含identity的属性。
$ az vm show -n idtest02 -g idtest | jq .identity null |
对于已经创建的VM,可以通过update VM的方法,添加managed identity:
$ az vm identity assign -g idtest -n idtest02 --identities vhid01 |
查看Identity属性:
$ az vm show -n idtest02 -g idtest | jq .identity { "principalId": null, "tenantId": null, "type": "UserAssigned", "userAssignedIdentities": { "/subscriptions/xxxx/resourceGroups/idtest/providers/Microsoft.ManagedIdentity/userAssignedIdentities/vhid01": { "clientId": "xxxx-8af6-4dde-97fc-xxxx", "principalId": "xxxx-b2fc-4c12-984c-xxxx" } } } |
4 在VM内获取Access Token
在VM中可以获取这个id各个scope的access Token。创建如下的脚本,并且将clientId更换成对于managed Identity的clientId,这个脚本可以获得KeyVault的AccessToken:
az identity show -n vhid01 -g idtest | jq .clientId "xxxx-8af6-4dde-97fc-xxxx" |
#!/bin/bash
curl 'http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https%3A%2F%2Fvault.azure.net&client_id= xxxx-8af6-4dde-97fc-xxxx -H Metadata:true -s | jq -r .access_token |
5 创建KeyVault的secret
用下面的cli创建keyvault的securet:
kvname="vhkvtest01" rg="idtest"
az keyvault create -n $kvname -g $rg -l westus2 \ --no-self-perms --enable-soft-delete false
pid=$(az identity show -g idtest -n vhid01 \ | jq -r .principalId) az_user=$(az account show -n dn-china-ats-weiheng \ | jq -r .user.name) az_user_id=$(az ad user list --upn $az_user \ | jq -r .[].objectId)
az keyvault set-policy -n $kvname -g $rg \ --secret-permissions all --object-id $pid az keyvault set-policy -n $kvname -g $rg \ --secret-permissions all --object-id $az_user_id
s_name='whkey' s_value='aaaaaa' az keyvault secret set -n $s_name \ --vault-name $kvname --value $s_value |
6 在VM中通过managed Identity访问KeyVault的Securet
#!/bin/bash
token=$(./getKeyVaultToken.sh) curl -s "https://vhkvtest01.vault.azure.net/secrets/whkey?api-version=2016-10-01" -H "Authorization: Bearer $token" |
7 通过manage identity查看相关资源
类似的,下面这个脚本可以获得Azure management的AccessToken:
#!/bin/bash
curl 'http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://management.azure.com/' -H Metadata:true -s | jq -r .access_token |
subId="xxxx-xxxx-xxxx" token=$(./getKeyManageToken.sh)
curl -s -H "Authorization: Bearer $token" \ "https://management.azure.com/subscriptions?api-version=2020-01-01" | jq . curl -s -H "Authorization: Bearer $token" \ "https://management.azure.com/subscriptions/$subId/resourcegroups?api-version=2021-04-01" \ | jq .value[].name curl -s -H "Authorization: Bearer $token" \ "https://management.azure.com/subscriptions/$subId/providers/Microsoft.Storage/storageAccounts?api-version=2021-09-01" | jq .value |