Basic authentication in API Management using Key Vault.

 

This post will provide an example of how to integrate Azure API ManagementKey Vault and Managed Identities to securely retrieve and use a secret within an API.



Enable Managed Identity

Before we jump into the policy itself, we first need to do some groundwork. As we are going to retrieve the secret from Key Vault, we will assign a managed identity to API Management, which we then give permission to get the secrets. First, enable managed identity on your API Management.




Assign permissions

Once enabled, the next step is to assign the required permissions to this new identity in Key Vault, which has the name of our resource. We do this in the Access policies blade, where we provide Get permissions for the secrets. Important to note, this does give the identity access to all the secrets in this Key Vault. As such, it is important to have a good Key Vault policy around separation of secrets.




Next Add access policy with the below of below screen shot.




Once done above steps we can see in access policy api management will added, refer below screen shot.





Next Generating secrets Value in azure key vault refer below screen shots.










Create policy

Now that we have everything in place, we are going to create the policy. In this scenario, we will send the secret as part of our basic authentication header. The endpoint we are using is on Request Bin, which allows us to easily inspect the call. Refer below screen shot.







Add below xml in policy.

 

<!--

    IMPORTANT:

    - Policy elements can appear only within the <inbound>, <outbound>, <backend> section elements.

    - To apply a policy to the incoming request (before it is forwarded to the backend service), place a corresponding policy element within the <inbound> section element.

    - To apply a policy to the outgoing response (before it is sent back to the caller), place a corresponding policy element within the <outbound> section element.

    - To add a policy, place the cursor at the desired insertion point and select a policy from the sidebar.

    - To remove a policy, delete the corresponding policy statement from the policy document.

    - Position the <base> element within a section element to inherit all policies from the corresponding section element in the enclosing scope.

    - Remove the <base> element to prevent inheriting policies from the corresponding section element in the enclosing scope.

    - Policies are applied in the order of their appearance, from the top down.

    - Comments within policy elements are not supported and may disappear. Place your comments between policy elements or at a higher level scope.

-->

<policies>

    <inbound>

        <choose>

            <when condition="@(!context.Request.Headers.ContainsKey("Authorization"))">

                <return-response>

                    <set-status code="401" reason="Unauthorized" />

                </return-response>

            </when>

        </choose>

        <!-- check the cache for secret first -->

        <cache-lookup-value key="@(context.Request.Headers.GetValueOrDefault("Authorization").AsBasic().UserId)" variable-name="keyvaultsecretResponse" />

        <!-- call Key Vault if not found in cache -->

        <choose>

            <when condition="@(!context.Variables.ContainsKey("keyvaultsecretResponse"))">

                <send-request mode="new" response-variable-name="keyvaultsecret" timeout="20" ignore-error="false">

                    <set-url>@{

                 return "https://*******.vault.azure.net/secrets/" + context.Request.Headers.GetValueOrDefault("Authorization").AsBasic().UserId + "/?api-version=7.0";

             }</set-url>

                    <set-method>GET</set-method>

                    <authentication-managed-identity resource="https://vault.azure.net" />

                </send-request>

                <!-- transform response to string and store in cache -->

                <set-variable name="keyvaultsecretResponse" value="@((string)((IResponse)context.Variables["keyvaultsecret"]).Body.As<JObject>()["value"])" />

                <cache-store-value key="@(context.Request.Headers.GetValueOrDefault("Authorization").AsBasic().UserId)" value="@((string)context.Variables["keyvaultsecretResponse"])" duration="3600" />

            </when>

        </choose>

        <!--Check if password from the Authorization header matches the secret value from the Key Vault -->

        <choose>

            <when condition="@(context.Request.Headers.GetValueOrDefault("Authorization").AsBasic().Password!= (string)context.Variables["keyvaultsecretResponse"])">

                <return-response>

                    <set-status code="401" reason="Not authorized" />

                </return-response>

            </when>

        </choose>

        <!--Delete the Authorization header, because it can cause problems at the backend-->

        <set-header name="Authorization" exists-action="delete" />

        <base />

    </inbound>

    <backend>

        <base />

    </backend>

    <outbound>

        <base />

    </outbound>

    <on-error>

        <base />

    </on-error>

</policies>

 

Reference Link:

 

https://aztoso.com/posts/apim-basic-auth-keyvault/

https://blog.eldert.net/retrieve-azure-key-vault-secrets-from-api-management-policies/

https://madeofstrings.com/2019/06/13/azure-api-management-key-vault-and-managed-identities/

https://vincentlauzon.com/2019/11/19/accessing-azure-key-vault-from-within-azure-api-management/



















Comments

Popular posts from this blog

Create Data Package file to Import Or Export CRM records.

Receive Incoming Message in Twilio using Power Automate

Azure Function to Read Incoming Message in Twilio

Open canvas app with Customize the command bar using command designer

Execute CRUD operations within the Power Platform using a Canvas App