0
votes

I have the following syntax for policy which works for only one certificate when passed with the GET Request.

<choose>
    <when condition="@(context.Request.Certificate != null && !context.Request.Certificate.Issuer.Contains("CN=itv.mit-xperts.com"))">
        <return-response>
            <set-status code="403" reason="Invalid client certificate Issuer" />
        </return-response>
    </when>
</choose>

If I use the policy to validate between two certificates, then it will always go to 403 because the OR statement always returns true:

<choose>
    <when condition="@((context.Request.Certificate != null) && (!context.Request.Certificate.Issuer.Contains("CN=itv.mit-xperts.com") || !context.Request.Certificate.Issuer.Contains("CN=DigiCert Test SHA2 Intermediate CA-1")))">
        <return-response>
            <set-status code="403" reason="Invalid client certificate Issuer" />
        </return-response>
    </when>
</choose>

The API works without certificate, but if a Certificate is passed, then "when" tag may or may not take action. I want the condition to go to 403 only when a certificate with any other Issuer is used. The Issuer Information contains many different attributes according to the certificate but CN=some-text remains common.

I have no knowledge regarding XML and its syntax or functions.

The following Microsoft Docs may help, but I did not find any syntax that may help:

https://docs.microsoft.com/en-us/azure/api-management/api-management-howto-mutual-certificates-for-clients#checking-the-issuer-and-subject

https://docs.microsoft.com/en-us/azure/api-management/api-management-policy-expressions

https://docs.microsoft.com/en-us/azure/api-management/api-management-transformation-policies

1

1 Answers

0
votes

It seems like your issue is not with the syntax but rather with boolean logic:

(context.Request.Certificate != null) && 
(
 !context.Request.Certificate.Issuer.Contains("CN=itv.mit-xperts.com") ||
 !context.Request.Certificate.Issuer.Contains("CN=DigiCert Test SHA2 Intermediate CA-1")
)

This will evaluate to true any time the issuer does not contain CN=itv.mit-xperts.com and any time it does not contain CN=itv.mit-xperts.com

It seems like what you actually want here is an AND condition:

(context.Request.Certificate != null) && 
(
 !context.Request.Certificate.Issuer.Contains("CN=itv.mit-xperts.com") &&
 !context.Request.Certificate.Issuer.Contains("CN=DigiCert Test SHA2 Intermediate CA-1")
)

This will only be true when the issuer does not contain CN=itv.mit-xperts.com AND IT ALSO does not contain CN=DigiCert Test SHA2 Intermediate CA-1

Alternatively, it seems you could move the NOT outside of the parentheses and change the AND to an OR, which might be a little easier to follow:

(context.Request.Certificate != null) && 
!(
 context.Request.Certificate.Issuer.Contains("CN=itv.mit-xperts.com") ||
 context.Request.Certificate.Issuer.Contains("CN=DigiCert Test SHA2 Intermediate CA-1")
)

This will be true when the issuer does not contain either CN=itv.mit-xperts.com or CN=DigiCert Test SHA2 Intermediate CA-1

It looks like you could also use LINQ for this:

var validIssuers = new [] 
{
    "CN=itv.mit-xperts.com",
    "CN=DigiCert Test SHA2 Intermediate CA-1",
};
var issuer = context.Request?.Certificate.Issuer;

return issuer != null && !validIssuers.Any(i => issuer.Contains(i));