azure-api-management

APIM - Validating a thumbprint against certificates uploaded to API Management


I currently have the below policy which validates the certificate thumbprint against "any" certificate uploaded to API Management:

<choose>
    <when condition="@(context.Request.Certificate == null || !context.Deployment.Certificates.Any(c => c.Value.Thumbprint == context.Request.Certificate.Thumbprint))">
        <return-response>
            <set-status code="403" reason="Invalid client certificate"/>
        </return-response>
    </when>
</choose>

But I want to validate a thumbprint against a "specific" certificate uploaded to API Management, not "any".

I have tried the below policy:

<choose>
    <when condition="@(context.Request.Certificate == null || context.Deployment.Certificates["MyCert"].Thumbprint == context.Request.Certificate.Thumbprint)">
        <return-response>
            <set-status code="403" reason="Invalid client certificate"/>
        </return-response>
    </when>
</choose>

"MyCert" is the "Id" of the "Client Certificate" in API which refers to the certificate uploaded in Key Vault.

enter image description here

But when I call the API, it throws this error: Expression evaluation failed. The given key 'MyCert' was not present in the dictionary. at System.Collections.Immutable.ImmutableDictionary`2.get_Item(TKey key)

Can someone please help me with this issue?


Solution

  • context.Deployment.Certificates.Values doesn't contain Certificate Id parameter to filter. You can validate it by using <set-variable name="Values" value="@((string)string.Join(", ", context.Deployment.Certificates.Values))" /> expression.

    You can use the below given policy to pass the Thumbprint of a specific certificate uploaded in APIM to verify against the incoming certificate.

    <policies>
        <inbound>
            <base />
            <choose>
                <when condition="@(context.Request.Certificate != null || (string)context.Deployment.Certificates.Values.FirstOrDefault(cert => cert.Thumbprint == "<APIMCertThumbprint>")?.Thumbprint == context.Request.Certificate.Thumbprint)">
                    <return-response>
                        <set-status code="200" reason="OK" />
                        <set-body>Valid certificate</set-body>
                    </return-response>
                </when>
                <otherwise>
                    <return-response>
                        <set-status code="403" reason="Invalid client certificate" />
                        <set-body>Invalid or missing client certificate</set-body>
                    </return-response>
                </otherwise>
            </choose>
        </inbound>
    </policies>
    

    Due to some limitations I can't pass the certificate information in request body, so I am testing by storing the value of thumbprint in set-variable against the uploaded certificate in APIM.

    enter image description here enter image description here

    enter image description here