Search code examples
azurehttp-headersazure-keyvaultazure-webappsazure-managed-identity

How to get Key Vault Secret under Web App's (with a user-assigned managed identity) Kudu powershell environment?


If I have a web app which has a system-assigned managed identity and the web app has been added to a Key Vault's Access Policies, I can use the following code the get secret value from the Key Vault under Kudu powershell Environment:

function GetSecret {
    param (
                [parameter(Mandatory=$True, Position=1)] [String] $keyVaultSecretUri
            )
    $apiVersion="2017-09-01"
    $resourceURI = "https://vault.azure.net"
    $tokenResponse = Invoke-RestMethod `
                    -Method Get `
                    -Headers @{"Secret"="$env:MSI_SECRET";"Content-Type"="application/json"} `
                    -Uri "${env:MSI_ENDPOINT}?resource=${resourceURI}&api-version=${apiVersion}"
    $accessToken = $tokenResponse.access_token
    $headers = @{'Authorization'="Bearer $accessToken"}

    $keyVaultApiVersion="7.1"
    $secret=Invoke-RestMethod -Method Get -Headers $headers -Uri "${keyVaultSecretUri}?api-version=${keyVaultApiVersion}"
    return $secret
}
GetSecret -keyVaultSecretUri $SecreteUri

But if I give the web app a user-assigned managed identity (without system-assigned managed identity) and add that managed identity to the Key Vault's Access Policies (with enough permissions), the above code doesn't work.

Actually even the following three lines gets a runtime exception:

$apiVersion="2017-09-01"
$resourceURI = "https://vault.azure.net"
$tokenResponse = Invoke-RestMethod `
                    -Method Get `
                    -Headers @{"Secret"="$env:MSI_SECRET";"Content-Type"="application/json"} `
                    -Uri "${env:MSI_ENDPOINT}?resource=${resourceURI}&api-version=${apiVersion}"

The exception is (CorrelationId is hidden):

Invoke-RestMethod : {"StatusCode":400,"Message":"No MSI found for specified 
ClientId/ResourceId.","CorrelationId":"0000000-0000-0000-0000-000000000000"}
At line:1 char:18
+ $tokenResponse = Invoke-RestMethod `
+                  ~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (System.Net.HttpWebRequest:Htt 
   pWebRequest) [Invoke-RestMethod], WebException
    + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShe 
   ll.Commands.InvokeRestMethodCommand

So how to get Key Vault Secret under Web App's (with a user-assigned managed identity) Kudu powershell environment??

(Probably the Headers for user-assigned identity web app is wrong)

PS: This answer How can I give access to key vault to a user assigned identity? doesn't resolve my question.


Solution

  • I actually wrote an article on this topic just a while ago: https://joonasw.net/view/get-managed-identity-access-token-in-azure-app-service-through-kudu. There I link to the docs for the REST protocol that Managed Identity uses: https://learn.microsoft.com/en-us/azure/app-service/overview-managed-identity?tabs=dotnet#using-the-rest-protocol.

    If you use a user-assigned identity, you must identify which identity you want to use. Since an App Service etc. can have multiple user-assigned identities. In the docs they give the following options:

    Three query parameters that can be specified

    You only need to specify one of these if I recall correctly.

    Tested this script and got a token for the user-assigned identity:

    $resource = "https://vault.azure.net"
    
    $clientId = "00000000-0000-0000-0000-000000000000"
    
    $endpoint = $env:IDENTITY_ENDPOINT
    $header = $env:IDENTITY_HEADER
    $apiVersion = "2019-08-01"
    
    $headers = @{ 'X-Identity-Header' = $header }
    
    $url = "$($endpoint)?api-version=$apiVersion&resource=$resource&client_id=$clientId"
    
    $response = Invoke-RestMethod -Method Get -Uri $url -Headers $headers
    $response.access_token