wip: some progress on markdown; cleaning up code using html-react-parser and its dependencies

This commit is contained in:
2024-05-11 21:54:16 +10:00
parent a828c62e71
commit 49e9fa8bc6
11 changed files with 251 additions and 635 deletions

View File

@@ -1,15 +1,201 @@
# Post Title
# Nginx + SSL Client Certificate Verification: Manage access to a site
## Introduction
Access control is a fundamental part of security. Most entities rely on
the combination of username and password, sometimes with additional multi-factor authentication
to improve security. Some entities also use the SSL client certificate verification to manage access
to specific resources. One of the use cases where SSL client certificate verification fits perfectly is
managing access to internet-facing development or staging servers. In this post, I'll share how
to set up the certificates and configure nginx to verify users based on their certificates.
Hi there! Do you see me?
## Preparing the certificates
```go
import "fmt"
There are two certificates we are going to create. The first one is the root
certificate. It will be placed in the Nginx server. The second one is the client certificate. It will
be installed in the client machine/browsers.
func main() {
fmt.Println("hello world")
### Root CA
For generating a root CA, execute these two steps:
#### Generate RSA Key
```sh
openssl genrsa -aes256 -out ca.key 4096
```
#### Create Root CA file
```sh
openssl req -new -x509 -days 3650 -key ca.key -out ca.crt
```
### Setup CA configuration
This is an optional step, but if you want to be able to revoke access you previously granted, you need to do this step.
Create a file named ca.cnf in the same directory as the ca.key and ca.crt.
```ini
[ ca ]
default_ca = gca
[ crl_ext ]
authorityKeyIdentifier=keyid:always
[ gca ]
dir = ./
new_certs_dir = $dir
unique_subject = no
certificate = $dir/ca.crt
database = $dir/certindex
private_key = $dir/ca.key
serial = $dir/certserial
default_days = 365
default_md = sha256
policy = gca_policy
x509_extensions = gca_extensions
crlnumber = $dir/crlnumber
default_crl_days = 365
[ gca_policy ]
commonName = supplied
stateOrProvinceName = supplied
countryName = optional
emailAddress = optional
organizationName = supplied
organizationUnitName = optional
[ gca_extensions ]
basicConstraints = CA:false
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always
keyUsage = digitalSignature,keyEncipherment
extendedKeyUsage = serverAuth
crlDistributionPoints = URI:http://example.com/root.crl
subjectAltName = @alt_names
[ alt_names ]
DNS.1 = example.com
DNS.2 = *.example.com
```
Initialize an empty file for the CA database.
```sh
touch certindex
```
Initialize value for certserial and crlnumber
```sh
echo 01 > certserial
echo 01 > crlnumber
```
### User Certificates
#### Generate the user RSA key
```sh
openssl genrsa -aes256 -out client01/user.key 4096
```
#### Create Certificate-Signing Request (CSR)
```sh
openssl req -new -key client01/user.key -out client01/user.csr
```
#### Sign the CSR
If you did the setup CA configuration step, sign the CSR file by running this command.
```sh
openssl ca -config ca.cnf -in client01/user.csr -out client01/user.crt
```
If you skipped the setup CA configuration step, sign the CSR file by running this command.
```sh
openssl x509 -req -days 365 -in client01/user.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out client01/user.crt
```
#### Convert the crt file to pfx/p12 file
Most of the time, browsers/client machines only accept a certificate in the pfx format. Run this
command to convert the crt file to the pfx/p12 format
```sh
openssl pkcs12 -export -out client01/user.pfx -inkey client01/user.key -in client01/user.crt -certfile ca.crt
```
You'll be prompted to enter an export password. You must input the exact password when adding
the certificate to a browser.
---
## Setting up nginx with client certificates verification
Add these lines to a server block in your nginx configuration
```nginx
ssl_client_certificate /path/to/client/verfication/ca.crt;
ssl_verify_client optional;
ssl_verify_depth 2;
```
You can do location-based access control. Location-based here refers to a location block in your
nginx configuration, for example:
```nginx
location /private {
if ($ssl_client_verify != SUCCESS) { # add this condition
return 403; # to make nginx return 403
} # when the client has no valid certificate
....
}
```
Here is a complete example of a server block in the nginx configuration
```nginx
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name www.example.com;
ssl_certificate /path/to/your/https/certificate.pem;
ssl_certificate_key /path/to/your/https/private-key.pem;
include snippets/ssl-params.conf;
# the folowing three lines make nginx verify client certificate
ssl_client_certificate /path/to/client/verification/ca.crt;
ssl_verify_client optional;
ssl_verify_depth 2;
root /usr/share/nginx/html;
index index.html index.htm;
location / {
if ($ssl_client_verify != SUCCESS) { # add this condition
return 403; # to make nginx return 403
} # when the client has no valid certificate
}
}
```
That's the `hello world` code!
---
## Adding the User Certificates to the client machine/browsers
Most browsers have a search feature on their setting page. Just search for certificates. It will show you the setting
for certificate management.
### Google Chrome (and Chromium-based browsers)
Google Chrome and most Chromium-based (e.g., Vivaldi, Microsoft Edge) browsers installed on Windows or Mac rely on
the operating system key management. So when you open the setting for certificate management, an external window
will open.