.netregexiisarr

How to match on all combinations except one?


I have a set of ARR redirect/rewrite rules that do this:

  1. Redirect to HTTPS whenever the subdomain tfs is in the URL
  2. Pull the content from a different server on the network.

Here's my config:

<rule name="TFS Redirect" enabled="true" stopProcessing="true">
    <match url="^((?!tfs).)*$" />
    <conditions logicalGrouping="MatchAll" trackAllCaptures="false">
        <add input="{HTTP_HOST}" pattern="tfs.domain.com" />
    </conditions>
    <action type="Redirect" url="https://tfs.domain.com/tfs" appendQueryString="false" />
</rule>
<rule name="TFS Rewrite" enabled="true" stopProcessing="true">
    <match url="^tfs(.*)" />
    <conditions logicalGrouping="MatchAll" trackAllCaptures="false" />
    <action type="Rewrite" url="http://server3:8080/{R:0}" />
</rule>

The trouble is that this setup is conflicting with my Let's Encrypt configuration. Somehow I need to enforce the above rules for everything except this URL:

http://tfs.domain.com/.well-known/acme-challenge/*

This is the answer to the incoming remote challenge that drives the automated certificate renewal process. Because of the rules, though, the ACME server can't reach the local IIS for validation and the certificate isn't being renewed.

How can I allow this one URL through, while catching everything else? Is there a way to add an exception to a condition? Or should I remove that condition altogether and rely solely on the RegEx expression for all of this?


Solution

  • After a couple hours of RegEx fiddling, I came up with the fix.

    Here's the new rule:

    <rule name="TFS Redirect" enabled="true" stopProcessing="true">
        <match url="^(.*)" />
        <conditions logicalGrouping="MatchAll" trackAllCaptures="false">
            <add input="{HTTPS}" pattern="^OFF$" />
            <add input="{HTTP_HOST}" pattern="^tfs\.domain\.com$" />
            <add input="{URL}" pattern="^/\.well-known*" negate="true" />
        </conditions>
        <action type="Redirect" url="https://tfs.domain.com/tfs" appendQueryString="false" redirectType="Found" />
    </rule>
    

    I hate to admit that I don't know where I got that earlier expression, but it was WAY off. All I had to do was back it down, tune up the conditions a bit and everything sailed right through.

    This rule catches and redirects these requests:

    1. Non-HTTPS URLs for all requests to tfs.domain.com
    2. All of the above, except those that don't start with /.well-known in the {URL} server variable

    FYI I opted for the 302 redirect after finding this.