Search code examples
certificateazure-api-management

Azure API Management - Validate incoming client certificate and Send cert to backend


In Azure API management I am trying to be able to validate an incoming cert from the calling application as well as send a cert to the backend. I am also trying to use Azure Keyvault Certs to do this. I am able to do either of these independently but am having trouble to get them working together.

Basically I would like to GET a certificate from the Keyvault, make sure the incoming cert matches, then also send that same cert to the backed end for end to end cert validation. By using the inbound policy below I am able to get the cert from keyvault and use it to send to my back end. I am also able to get the thumbrpint of the incoming cert.

Where I am having issues is getting the thumbprint from the base64 string of the certificate I get from the keyvault. I there anyway to can conver the certificate string to a certificate object?

<inbound>
        <base />
        <send-request mode="new" response-variable-name="keyVaultCertResponse" timeout="20" ignore-error="false">
            <set-url>https://MYKEYVAULTNAME.vault.azure.net/secrets/CLIENTCERTTEST/?api-version=2016-10-01</set-url>
            <set-method>GET</set-method>
            <authentication-managed-identity resource="https://vault.azure.net" />
        </send-request>
        <set-variable name="keyVaultCertBase64" value="@(((IResponse)context.Variables["keyVaultCertResponse"]).Body.As<JObject>()["value"].ToString())" />
        <choose>
            <when condition="@(context.Request.Certificate == null)">
                <return-response>
                    <set-status code="403" reason="No Client Certificate Provided to APIM" />
                </return-response>
            </when>
            <when condition="@(context.Variables["keyVaultCertResponse"] != context.Request.Certificate.Thumbprint)">
                <return-response>
                    <set-status code="403" reason="Client Certificate Presented to APIM is incorrect" />
                </return-response>
            </when>
        </choose>
        <authentication-certificate body="@(Convert.FromBase64String((string)context.Variables["keyVaultCertBase64"]))" />
    </inbound>

Solution

  • In your second when you're comparing keyVaultCertResponse which is IResponse object with a thumbprint of client certificate. If you're fine with comparing them by thumbprint, try instantiating X509Certificate2 object and get thumbprint from it. Like so:

    new X509Certificate2(Convert.FromBase64String((string)context.Variables["keyVaultBase64"])). Thumbprint == context.Request.Certiricate.Thumbprint