4
votes

I've picked up something that someone else has set up. We have an API Management instance, siting behind an Application Gateway, which has a policy on an API:

<inbound>
        <choose>
            <when condition="@(context.Request.Certificate == null)">
                <return-response>
                    <set-status code="403" reason="Client certificate required..d1PD" />
                </return-response>
            </when>
        </choose>
        <choose>
            <when condition="@(!context.Request.Certificate.Verify())">
                <return-response>
                    <set-status code="403" reason="Client certificate cannot be verified..d2PD " />
                </return-response>
            </when>
        </choose>
        <choose>
            <when condition="@(!context.Deployment.Certificates.Any(c => c.Value.Thumbprint == context.Request.Certificate.Thumbprint))">
                <return-response>
                    <set-status code="403" reason="Client certificate is untrusted or invalid..d3PD" />
                </return-response>
            </when>
        </choose>
        <base />
    </inbound>

In Postman I am passing a cert and key. The Postman Console shows

Client Certificate:
keyPath:"C:\selfsigned\internalscm.X.com.key"
pemPath:"C:\selfsigned\internalscm.X.com.crt"
pfxPath:""

I'm passing Ocp-Apim-Trace in the header of the request so am getting a trace back which contains:

traceEntries        {2}
  inbound       [10]
..
    6       {4}
        source  :   authentication-certificate
        timestamp   :   2019-08-06T08:55:31.3435485Z
        elapsed :   00:00:00.0006857
            data        {2}
                message :   Certificate was attached to request per configuration.
                certificate     {...}
    7       {4}
        source  :   choose
        timestamp   :   2019-08-06T08:55:31.3435485Z
        elapsed :   00:00:00.0007011
            data        {3}
                message :   Expression was successfully evaluated.
                expression  :   context.Request.Certificate == null
                value   :   true

UPDATE:

The authentication-certificate assessment is of the backend's certificate and is nothing to do with the client certificate (.key and .crt) that Postman claims to be including in the request (the same result is returned if I pass a pfx and password instead of .key and .crt).

When I hit the API that the Gateway is protecting, I can see in the trace that it is processing the client certificate (and returning a 200):

     {
        "source": "client-certificate-handler",
        "timestamp": "2019-08-09T15:47:46.3825928Z",
        "elapsed": "00:00:00.0005974",
        "data": "Requesting client certificate because next handler requires access to it."
      },
      {
        "source": "client-certificate-handler",
        "timestamp": "2019-08-09T15:47:46.6950495Z",
        "elapsed": "00:00:00.3225172",
        "data": "Client certificate thumbprint '6C03F4E7999999999999999999999999'  received."
      },
      {
        "source": "choose",
        "timestamp": "2019-08-09T15:47:46.6950495Z",
        "elapsed": "00:00:00.3225288",
        "data": {
          "message": "Expression was successfully evaluated.",
          "expression": "context.Request.Certificate == null",
          "value": false
        }
      },
      {
        "source": "choose",
        "timestamp": "2019-08-09T15:47:46.9606395Z",
        "elapsed": "00:00:00.5849700",
        "data": {
          "message": "Expression was successfully evaluated.",
          "expression": "!context.Request.Certificate.Verify()",
          "value": false
        }
      },
      {
        "source": "choose",
        "timestamp": "2019-08-09T15:47:46.9606395Z",
        "elapsed": "00:00:00.5850060",
        "data": {
          "message": "Expression was successfully evaluated.",
          "expression": "!context.Deployment.Certificates.Any(c => c.Value.Thumbprint == context.Request.Certificate.Thumbprint)",
          "value": false
        }
      }

So it looks like AppGateway is dropping the client certificate.

The trace doesn't give me enough to start deducing why the client certificate (assuming that Postman is transmitting it to the Gateway as it does the API) is being dropped. Where should I start?

For ref, when I remove the policy the request is processed as expected.

1
Hi, did you manage do solve this problem ?Tyrannas
Hi @Tyrannas. As Vitaliy suggested it is not possible. We had to remove that requirement from our project.Badgerspot

1 Answers

1
votes

I'm not sure if you can make AppGateway pass the certificate - you need to check their docs. The reason I'm skeptical is bacuse the whole idea of AppGateway is to look into traffic and provide protection by doing that. And the only way to d othat is to terminate SSL connection at AppGateway level. See here for more information: https://docs.microsoft.com/en-us/azure/application-gateway/ssl-overview there are two modes for AppGateway: SSL temination when AppGAteway makes HTTP (not HTTPS) calls to backend, and SSL end-to-end when AppGateway uses own SSL certificate to connect to bakend.