Hello,
I want to create a Caddyfile with mTLS. The difficulty is that I need mTLS for every path, expect /test. This path should be the only path not protected by mTLS. All sites should use my own tls certs in /example/site.cer /example/site.key.
2. Error messages and/or full log output:
I cannot find any documentation to accomplish this.
This should be doable, but you should note that TLS is negotiated before path comes into play. It’s not really possible for Caddy to change its mTLS behaviour based on what URI the client wants.
So, you’ll need to use a mode that allows for mTLS and non-mTLS clients to connect, and then handle requests based on which URI they want and whether they did authenticate themselves.
verify_if_given is the mode that allows clients to optionally authenticate, but requires a valid client certificate if they do authenticate themselves. When you set that mode, you can trust that Caddy has discarded inauthentic mTLS requests before they reach your HTTP handling logic and the only clients left are valid-mTLS and non-mTLS.
Then you can handle non-mTLS requests to non-/test endpoints by issuing a 403 response (or any alternative rejection handling at your preference).
Ahh, whoops. Can’t invert with !type(), what I wanted was to invert type() == string (i.e. it isn’t a string). But we can do that instead with != like so:
Use the literal word string there. It’s not an actual string, it’s a type.
What we’re doing is checking if http.request.tls.client.issuer is a string or not. If it’s a string, it means it was replaced with a value. If it’s not a string, we know it hasn’t actually been set. It’s basically checking “does this placeholder exist”.
Hmm. It’s not grouping the path and type checks (which are boolean) into one boolean and then comparing its type to not a string (which would always be true), is it?
Maybe `!path('/test') && (type({tls_client_issuer}) != string)` (adding the parentheses around the type comparison) might work better?