Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 72 additions & 0 deletions docs/handson_client_certs.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
---
id: handson_client_certs
title: "Hands-on: Client Certificate Authentication"
sidebar_label: Client Certificate Auth
---

In this lab, we'll learn how to configure a web server to require a client certificate for authentication. This is also known as mutual TLS (mTLS) because both the server and the client are presenting certificates to each other to prove their identity.

We will use Nginx as our web server and `mkcert` to create the necessary certificates.

## Prerequisites

* You have `mkcert` installed. If not, please follow the instructions in the "Hands-on with mkcert" lab.
* You have `nginx` installed.

## Step 1: Create a Certificate Authority (CA)

First, we need our own private CA. We can use `mkcert` for this. If you've run this before, you don't need to do it again.

```bash
mkcert -install
```

This creates a local CA and installs it in your system's trust stores.

## Step 2: Create a Server Certificate

Next, let's create a certificate for our server. We'll use `localhost` as the domain.

```bash
mkcert localhost
```

This will create `localhost.pem` (the certificate) and `localhost-key.pem` (the private key) in the current directory.

## Step 3: Create a Client Certificate

Now, let's create a certificate for our client. We'll identify the client by the name "my-client".

```bash
mkcert -client my-client
```

This will create `my-client.pem` and `my-client-key.pem` in the current directory.

## Step 4: Configure Nginx for mTLS

Now we need to configure Nginx to use these certificates. We will provide an example Nginx configuration file that you can adapt.

We will need to know where your CA certificate is stored. You can find the location of your local CA files by running:
```bash
mkcert -CAROOT
```
This will output a path. Inside that directory, you will find `rootCA.pem`. This is the file we need to reference in our Nginx config.

We will be creating the Nginx configuration file in the `examples/client-cert-nginx/` directory.

## Step 5: Test the configuration

Once we have the Nginx configuration in place, we will test it.

You can try to access `https://localhost:8443` in your browser. You should see an error because the browser is not presenting a client certificate.

To test it correctly, you can use `curl`:

```bash
curl --cacert $(mkcert -CAROOT)/rootCA.pem \
--cert my-client.pem --key my-client-key.pem \
https://localhost:8443
```

If everything is configured correctly, you should get the default Nginx welcome page. If you remove the `--cert` and `--key` flags, the request should fail.
68 changes: 68 additions & 0 deletions docs/handson_lets_encrypt.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
---
id: handson_lets_encrypt
title: "Hands-on: Automating Certificates with Let's Encrypt"
sidebar_label: Automating with Let's Encrypt
---

In this lab, we'll learn how to use Let's Encrypt to get a free, trusted TLS certificate for a real, public website. We'll also see how to automatically renew the certificate so it never expires.

Let's Encrypt is a free, automated, and open certificate authority (CA), run for the public's benefit. It's a service provided by the Internet Security Research Group (ISRG).

## Prerequisites

* A publicly accessible web server. This could be a server from any cloud provider (AWS, GCP, Azure, DigitalOcean, etc.).
* A registered domain name that you can point to your server's public IP address.
* Shell access to your server.

## Step 1: Install Certbot

The easiest way to use Let's Encrypt is with the `certbot` client. It's a tool that automates the process of getting a certificate and configuring your web server to use it.

Installation instructions vary depending on your operating system and web server. The official Certbot website has excellent instructions for all major platforms.

**[Go to the Certbot Instructions Generator](https://certbot.eff.org/)**

Select your web server software (e.g., Nginx, Apache) and your server's operating system (e.g., Ubuntu, CentOS) and follow the instructions to install `certbot`.

## Step 2: Obtain your first certificate

Once `certbot` is installed, you can run it to get your certificate.

For example, if you are using Nginx on Ubuntu, the command is typically:

```bash
sudo certbot --nginx
```

This command will:
1. Automatically detect the domain names your Nginx server is configured for.
2. Ask you which domain(s) you want to get a certificate for.
3. Obtain the certificate from Let's Encrypt.
4. Automatically update your Nginx configuration to use the new certificate.
5. Set up a cron job or systemd timer to automatically renew the certificate before it expires.

Follow the on-screen prompts to complete the process.

## Step 3: Verify automatic renewal

Let's Encrypt certificates are valid for 90 days. `certbot` automatically sets up a task to renew them for you. You can test that the renewal process works by doing a "dry run":

```bash
sudo certbot renew --dry-run
```

If the dry run is successful, you're all set! Your certificates will be renewed automatically.

## How does it work?

The process `certbot` uses to prove you control the domain is called the "ACME protocol" (Automated Certificate Management Environment).

When you run `certbot`, it communicates with the Let's Encrypt servers. Let's Encrypt will give `certbot` a challenge, which is usually to place a specific file with specific content on your web server at a specific URL.

For example: `http://yourdomain.com/.well-known/acme-challenge/some-random-string`

`certbot` places the file there, and then tells Let's Encrypt to go check for it. If Let's Encrypt can download the file and the content is correct, it proves you control the server for that domain, and it will issue the certificate.

This is a simplified explanation of the "HTTP-01" challenge, which is the most common one. There are other challenge types as well, like the "DNS-01" challenge.

That's it! You now have a free, trusted, and automatically renewing TLS certificate for your website.
23 changes: 23 additions & 0 deletions examples/client-cert-nginx/default.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
server {
listen 8443 ssl;
server_name localhost;

# Server certificate and key
# Replace these paths with the actual paths to your server certificate and key
# e.g. /Users/jules/learn-mtls/localhost.pem
ssl_certificate /path/to/your/localhost.pem;
ssl_certificate_key /path/to/your/localhost-key.pem;

# Client certificate settings
# The 'ssl_client_certificate' should point to the CA that signed the client certs.
# You can find your CA path by running `mkcert -CAROOT`
# e.g. /Users/jules/Library/Application Support/mkcert/rootCA.pem
ssl_client_certificate /path/to/your/rootCA.pem;
ssl_verify_client on; # 'on' means the client MUST present a valid certificate

location / {
# A simple default page
root /usr/share/nginx/html;
index index.html index.htm;
}
}
7 changes: 4 additions & 3 deletions sidebars.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@

module.exports = {
someSidebar: {
"First Principles": ['certificates', 'principles_cryptographic_protocols', 'principles_macos_ios_gotchyas'],
"Hands-on Practice": ['handson_mkcert', 'handson_ssh', 'handson_consul', 'handson_zookeeper'],
"Learn the Code": ['ltc_consul', 'ltc_nomad', 'ltc_zookeeper'],
"Part 1: Certificate Fundamentals": ['certificates', 'principles_cryptographic_protocols', 'principles_macos_ios_gotchyas'],
"Part 2: Hands-on Certificate Creation & Usage": ['handson_mkcert', 'handson_ssh', 'handson_consul', 'handson_zookeeper'],
"Part 3: Advanced Scenarios & Automation": ['handson_client_certs', 'handson_lets_encrypt'],
"Part 4: Under the Hood": ['ltc_consul', 'ltc_nomad', 'ltc_zookeeper'],
},
};