2

In addition to usual CA chain validation, I would like Nginx server section to permit specific client certificate thumbprints only.

I could find how to check for single fingerprint, but I'm not sure how to combine multiple fingerprints because Nginx does not support or, and map is not allowed inside server sections.

So, now I have an ugly workaround like this:

    ssl_client_certificate /usr/local/share/ca-certificates/trusted_chain.pem;
    ssl_verify_client on;
    ssl_verify_depth 3;

    if ( $ssl_client_fingerprint = "12a4f0abc935cc0dd0f6fdcc0d56682d7f5c15a1" ) {
        set $whiteclient 1;
    }
    if ( $ssl_client_fingerprint = "12a4f0abc935cc0dd0f6fdcc0d56682d7f5c15a2" ) {
        set $whiteclient 1;
    }
    if ( $ssl_client_fingerprint = "12a4f0abc935cc0dd0f6fdcc0d56682d7f5c15a3" ) {
        set $whiteclient 1;
    }
    if ( $whiteclient != 1 ) {
         return 403;
    }

Is there any nicer way to do this?

JustAMartin
  • 231
  • 1
  • 17
  • How is `map` being unavailable in `server` sections a problem here? You are checking SHA1 hashes of certs signed by a known entity, would be quite odd to encounter collisions there.. – anx Sep 23 '19 at 17:11
  • @anx if `map` was available, I could avoid those ugly `if`s. Also, I hoped that some better, built-in way to create a fingerprint whitelist exists. – JustAMartin Sep 23 '19 at 19:35
  • This is something you should use a `map` for. They don't go in `server` blocks. They go outside `server` blocks. – Michael Hampton Sep 23 '19 at 20:01
  • But if `ssl_client_certificate` and `ssl_verify_client` are both defined inside only one `server` block (because I have multiple server sections), will a `map` outside still work correctly with the `$ssl_client_fingerprint` variable? Will Nginx process this variable when it haven't yet routed the request to the `server` section that enables client certificate processing? – JustAMartin Sep 23 '19 at 20:15

1 Answers1

0

NGINX supports regex matching within if conditions so you can do the following:

if ($ssl_client_fingerprint !~ "12a4f0abc935cc0dd0f6fdcc0d56682d7f5c15a1|12a4f0abc935cc0dd0f6fdcc0d56682d7f5c15a2|12a4f0abc935cc0dd0f6fdcc0d56682d7f5c15a3") {
  return 403
}

Obviously this line could get rather long but dependant on taste/use case it may be preferable.

dav_i
  • 101
  • 3