Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

nginx authorization based on client certificates

I have SSL enabled in nginx with the client certificate enabled in my browser. With this I'm able to hit my site via HTTPS through port 443.

What I'm looking for now is to use this information about the client to allow access to different parts of the API (URLs) but deny access to other parts. I can do this using IP address and the ngx_http_access_module with something like the following:

location /allowed/loc {
    allow 192.168.1.0/24;
}

location /protected/loc {
    allow 192.168.1.10;
    deny all;
}

What I'm looking for is some way to allow/deny based on the certificate of the client instead of on the IP address, ie something akin to this:

location /authorize/by/cert {
    allow client-cert-serial;
    deny all;
}

Is there a way to do this in nginx, or do I need to use something else? Or am I thinking about this all wrong?

Thanks for the help.

like image 688
jayemar Avatar asked Mar 10 '23 05:03

jayemar


1 Answers

For access check you can use if directive and ssl module variables: $ssl_client_s_dn, $ssl_client_serial. Example

location /not/for/jhon/ {
   if ($ssl_client_s_dn ~ Jhon) {
      return 403;
   }
}

Good way to maintain list of allowed certificated the map directive. Example

map $ssl_client_s_dn $ssl_access {
default 0;
01 1;
02 1;
}

server {
  ...
  location /authorize/by/cert {
     if ($ssl_access = 0) {
        return 403;
     }
  }
}

or, rules can be more complicated

map $ssl_client_s_dn $ssl_access {
default "";
01 -a-b-c-;
02 -b-e-;
}

server {
  ...
  location /authorize/by/cert/a {
     if ($ssl_access !~ -a-) {
        return 403;
     }
  }

  location /authorize/by/cert/b {
     if ($ssl_access !~ -b-) {
        return 403;
     }
  }
}

But read this article before https://www.nginx.com/resources/wiki/start/topics/depth/ifisevil/. Use if only with return or rewrite ... last; directives.

like image 199
Dmitry MiksIr Avatar answered Apr 05 '23 16:04

Dmitry MiksIr