Search code examples
azure-keyvaultazure-api-managementhmac

Read a secret key from azure key vault in apim


i need to validate a hmac in my apim policy. For which the hmac secret will be stored in azure key vault. Below are the steps that i will be following in my policy

  • Read the secret key from the key vault
  • Validate the hmac

Below is the apim policy that i tried

<policies>
    <inbound>
        <base />

        <!-- Fetch HMAC key from Key Vault -->
        <set-variable name="keyVaultSecretUri" value="KV_URL/secrets/SECRET_NAME" />
        <set-variable name="keyVaultClientId" value="KV_CLIENT />
        <set-variable name="keyVaultClientSecret" value="KV_SECRET" />

        <set-variable name="request" value="@{
            var keyVaultSecretUri = context.Variables["keyVaultSecretUri"];
            var keyVaultClientId = context.Variables["keyVaultClientId"];
            var keyVaultClientSecret = context.Variables["keyVaultClientSecret"];

            return new {
                method = "GET",
                url = keyVaultSecretUri,
                headers = new {
                    Authorization = "Bearer " + FetchAccessToken(keyVaultClientId, keyVaultClientSecret)
                }
            };
        }" />

        <send-request mode="new" response-variable-name="keyVaultResponse" timeout="20" ignore-error="false">
            <set-url>@(context.Variables["request"].url)</set-url>
            <set-method>@(context.Variables["request"].method)</set-method>
            <set-header name="Authorization" exists-action="override">
                <value>@(context.Variables["request"].headers.Authorization)</value>
            </set-header>
        </send-request>

        <!-- Log Key Vault Response -->
        <trace source="keyVault" severity="information">
            <message>@(context.Variables["keyVaultResponse"].Body?.ToString())</message>
        </trace>
    </inbound>
</policies>

Below is the error i got

 One or more fields contain incorrect values:
Error in element 'set-variable' on line 22, column 10: The name 'FetchAccessToken' does not exist in the current context
Error in element 'send-request' on line 36, column 10: 'object' does not contain a definition for 'url' and no extension method 'url' accepting a first argument of type 'object' could be found (are you missing a using directive or an assembly reference?)
Error in element 'trace' on line 45, column 10: 'object' does not contain a definition for 'Body' and no extension method 'Body' accepting a first argument of type 'object' could be found (are you missing a using directive or an assembly reference?)

in the above policy i am just trying to read the secret and display. I am unable to achieve that. I followed this link as a reference


Solution

  • I am just trying to read the secret and display

    To fetch the secret value from Key Vault, you need to do the following setup.

    1. Enable the Managed Identities like below in Azure APIM.

    enter image description here

    1. Grant Get Secret access to APIM in Key vault using Access Policies as shown below.

    enter image description here enter image description here enter image description here enter image description here

    1. Create a Named value in APIM.

    enter image description here enter image description here

    Once the named value is created, then you can use the below policy to fetch the secret and display the value too.

    <policies>
        <inbound>
            <base  />
            <set-variable  name="KeyVaultSecret"  value="{{Named value name}}"  />
            <return-response>
                <set-body>@("Key Vault Secret is: "+(context.Variables["KeyVaultSecret"])+"")</set-body>
            </return-response>
        </inbound>
    </policy>
    

    I am able to get the Key Vault secret value.

    enter image description here

    You need to use the <send-request> policy like below-

    <send-request mode="new" response-variable-name="keyVaultResponse" timeout="60" ignore-error="true">
        <set-url>@("pass_the_url")</set-url>
        <set-method>GET</set-method>
        <set-header name="Authorization" exists-action="override">
            <value>@(context.Request.Headers.GetValueOrDefault("Authorization", ""))</value>
        </set-header>
    </send-request>
    

    You can also refer to my answer in this SO-Thread.