cryptutil: add automatic certificate management (#644)

Signed-off-by: Bobby DeSimone <bobbydesimone@gmail.com>
This commit is contained in:
Bobby DeSimone 2020-05-05 12:50:19 -07:00 committed by GitHub
parent 1dc1c870c3
commit bf9a6f5e97
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
29 changed files with 696 additions and 253 deletions

View file

@ -5,7 +5,6 @@ sidebarDepth: 0
meta:
- name: keywords
content: pomerium community contributing pr code
description: >-
This document describes how you can find issues to work on, fix/add
documentation, and how setup Pomerium for local development.
@ -93,4 +92,4 @@ We use [Netlify](https://www.netlify.com) to build and host our docs. One of nic
[httpbin]: https://httpbin.org/
[identity provider]: ../identity-providers/readme.md
[make]: https://en.wikipedia.org/wiki/Make_(software)
[wild-card tls certificate]: ../reference/certificates.md
[tls certificates]: ../reference/certificates.md

View file

@ -13,7 +13,7 @@ The following quick-start guide covers how to configure and run Pomerium using t
## Prerequisites
- A configured [identity provider]
- A [wild-card TLS certificate]
- [TLS certificates]
## Download
@ -54,4 +54,4 @@ Browse to `external-httpbin.your.domain.example`. Connections between you and [h
[httpbin]: https://httpbin.org/
[identity provider]: ../docs/identity-providers/
[make]: https://en.wikipedia.org/wiki/Make_(software)
[wild-card tls certificate]: ../reference/certificates.md
[tls certificates]: ../reference/certificates.md

View file

@ -75,4 +75,4 @@ Browse to `httpbin.localhost.pomerium.io`. Connections between you and [httpbin]
[httpbin]: https://httpbin.org/
[identity provider]: ../docs/identity-providers/
[make]: https://en.wikipedia.org/wiki/Make_(software)
[wild-card tls certificate]: ../reference/certificates.md
[tls certificates]: ../reference/certificates.md

View file

@ -17,7 +17,7 @@ This quick-start will show you how to deploy Pomerium with [Helm](https://helm.s
- Install [kubectl](https://kubernetes.io/docs/tasks/tools/install-kubectl/)
- Install the [Google Cloud SDK](https://cloud.google.com/kubernetes-engine/docs/quickstart)
- Install [helm](https://helm.sh/docs/using_helm/)
- A [wild-card TLS certificate]
- [TLS certificates]
Though there are [many ways](https://kubernetes.io/docs/setup/pick-right-solution/) to work with Kubernetes, for the purpose of this guide, we will be using Google's [Kubernetes Engine](https://cloud.google.com/kubernetes-engine/). That said, most of the following steps should be very similar using any other provider.
@ -25,7 +25,7 @@ In addition to sharing many of the same features as the Kubernetes quickstart gu
## Configure
Download and modify the following [helm_gke.sh script][./scripts/helm_gke.sh] to match your [identity provider] and [wild-card tls certificate] settings.
Download and modify the following [helm_gke.sh script][./scripts/helm_gke.sh] to match your [identity provider] and [TLS certificates] settings.
<<<@/scripts/helm_gke.sh
@ -56,4 +56,4 @@ You can also navigate to the special pomerium endpoint `httpbin.your.domain.exam
[identity provider]: ../identity-providers/readme.md
[letsencrypt]: https://letsencrypt.org/
[script]: https://github.com/pomerium/pomerium/blob/master/scripts/generate_wildcard_cert.sh
[wild-card tls certificate]: ../reference/certificates.md
[tls certificates]: ../reference/certificates.md

View file

@ -13,7 +13,7 @@ This quickstart will cover how to deploy Pomerium with Kubernetes.
## Prerequisites
- A configured [identity provider]
- A [wild-card TLS certificate]
- [TLS certificates]
- A [Google Cloud Account](https://console.cloud.google.com/)
- [kubectl](https://kubernetes.io/docs/tasks/tools/install-kubectl/)
- [Google Cloud SDK](https://cloud.google.com/kubernetes-engine/docs/quickstart)
@ -29,7 +29,7 @@ cd $HOME/pomerium/docs/configuration/examples/kubernetes
## Configure
Edit [./kubernetes_gke.sh] making sure to change the identity provider secret value to match your [identity provider] and [wild-card tls certificate] settings.
Edit [./kubernetes_gke.sh] making sure to change the identity provider secret value to match your [identity provider] and [TLS certificates] settings.
<<<@/docs/configuration/examples/kubernetes/kubernetes_gke.sh
@ -68,4 +68,4 @@ You can also navigate to the special pomerium endpoint `httpbin.your.domain.exam
[identity provider]: ../identity-providers/readme.md
[letsencrypt]: https://letsencrypt.org/
[script]: https://github.com/pomerium/pomerium/blob/master/scripts/generate_wildcard_cert.sh
[wild-card tls certificate]: ../reference/certificates.md
[tls certificates]: ../reference/certificates.md

View file

@ -14,7 +14,7 @@ In the following quick-start, we'll create a minimal but complete environment fo
- A configured [identity provider]
- [Docker] and [docker-compose]
- A [wild-card TLS certificate]
- [TLS certificates]
## Configure
@ -31,7 +31,7 @@ Ensure the `docker-compose.yml` contains the correct path to your `config.yaml`.
Download the following `docker-compose.yml` file and modify it to:
- generate new secrets
- mount your [wild-card TLS certificate]
- mount your [TLS certificates]
- mount your `config.yaml` [configuration file]
<<< @/docs/configuration/examples/docker/basic.docker-compose.yml
@ -58,4 +58,4 @@ You can also navigate to the special pomerium endpoint `httpbin.corp.yourdomain.
[docker-compose]: https://docs.docker.com/compose/install/
[httpbin]: https://httpbin.org/
[identity provider]: ../identity-providers/readme.md
[wild-card tls certificate]: ../reference/certificates.md
[tls certificates]: ../reference/certificates.md

View file

@ -24,7 +24,7 @@ Pomerium is lightweight, can easily handle hundreds of concurrent requests, and
- A [docker-capable] synology product
- A [Google Cloud Account](https://console.cloud.google.com/)
- A configured Google OAuth2 [identity provider]
- A [wild-card TLS certificate][certificate documentation]
- [TLS certificates][certificate documentation]
Though any supported [identity provider] would work, this guide uses google.
@ -46,17 +46,17 @@ Click **Create**.
Set the following **Reverse Proxy Rules**.
| Field | Description |
| -------------------- | ----------- |
| Description | pomerium |
| Source Protocol | HTTPS |
| Source Hostname | \* |
| Destination Port | 8443 |
| HTTP/2 | Enabled |
| HSTS | Enabled |
| Destination Protocol | HTTP |
| Destination Hostname | localhost |
| Destination Port | 32443 |
Field | Description
-------------------- | -----------
Description | pomerium
Source Protocol | HTTPS
Source Hostname | *
Destination Port | 8443
HTTP/2 | Enabled
HSTS | Enabled
Destination Protocol | HTTP
Destination Hostname | localhost
Destination Port | 32443
![Synology setup nginx reverse proxy](./img/synology-reverse-proxy.png)
@ -76,9 +76,9 @@ Once the certificate is showing on the list of certificates screen we need to te
**Click configure**
| Services | Certificate |
| -------- | ------------------- |
| \*:8443 | `*.int.nas.example` |
Services | Certificate
-------- | -------------------
*:8443 | `*.int.nas.example`
![Synology assign wildcard certificate](./img/synology-certifciate-assignment.png)
@ -170,15 +170,15 @@ These are the minimum set of configuration settings to get Pomerium running in t
Go to **Environment** tab.
| Field | Value |
| ------------------------ | --------------------------------------------------------------- |
| POLICY | output of `base64 -i policy.yaml` |
| INSECURE_SERVER | `TRUE`, internal routing within docker will not be encrypted. |
| IDP_CLIENT_SECRET | Values from setting up your [identity provider] |
| IDP_CLIENT_ID | Values from setting up your [identity provider] |
| IDP_PROVIDER | Values from setting up your [identity provider] (e.g. `google`) |
| COOKIE_SECRET | output of `head -c32 /dev/urandom | base64` |
| AUTHENTICATE_SERVICE_URL | `https://authenticate.int.nas.example` |
Field | Value
------------------------ | ---------------------------------------------------------------
POLICY | output of `base64 -i policy.yaml`
INSECURE_SERVER | `TRUE`, internal routing within docker will not be encrypted.
IDP_CLIENT_SECRET | Values from setting up your [identity provider]
IDP_CLIENT_ID | Values from setting up your [identity provider]
IDP_PROVIDER | Values from setting up your [identity provider] (e.g. `google`)
COOKIE_SECRET | output of `head -c32 /dev/urandom | base64`
AUTHENTICATE_SERVICE_URL | `https://authenticate.int.nas.example`
For a detailed explanation, and additional options, please refer to the [configuration variable docs]. Also note, though not covered in this guide, settings can be made via a mounted configuration file.

View file

@ -8,7 +8,9 @@ meta:
# Certificates
[Certificates](https://en.wikipedia.org/wiki/X.509) and [TLS](https://en.wikipedia.org/wiki/Transport_Layer_Security) play a vital role in [zero-trust][principles] networks, and in Pomerium. This document covers how to generate and set up wild-card certificates suitable for working with pomerium.
[Certificates](https://en.wikipedia.org/wiki/X.509) and [TLS](https://en.wikipedia.org/wiki/Transport_Layer_Security) play a vital role in [zero-trust][principles] networks, and in Pomerium.
This document covers a few options in how to generate and set up TLS certificates suitable for working with pomerium.
This guide uses the following tools and resources:
@ -16,13 +18,7 @@ This guide uses the following tools and resources:
- [Google Domains](https://domains.google.com/) registrar will be used to set up our wildcard domain and certificate validation. But any registrar would do and some providers support [automatic renewal](https://github.com/Neilpang/acme.sh/wiki/dnsapi).
- [acme.sh](https://github.com/Neilpang/acme.sh) will be used to retrieve the wild-card domain certificate. Any [LetsEncrypt client](https://letsencrypt.org/docs/client-options/) that supports wildcard domains would work.
It should be noted that there are countless ways of building and managing [public-key infrastructure](https://en.wikipedia.org/wiki/Public_key_infrastructure). And although we hope this guide serves as a helpful baseline for generating and securing pomerium with certificates, these instructions should be modified to meet your own organization's tools, needs, and constraints.
::: warning
LetsEncrypt certificates must be renewed [every 90 days](https://letsencrypt.org/2015/11/09/why-90-days.html).
:::
It should be noted that there are countless ways of building and managing [public-key infrastructure](https://en.wikipedia.org/wiki/Public_key_infrastructure). And although we hope this guide serves as a helpful baseline for generating and securing pomerium with certificates, these instructions should be modified to meet your own organization's tools, needs, and constraints. In a production environment you will likely be using your corporate load balancer, or a key management system to manage your certificate authority infrastructure.
## Why
@ -32,81 +28,54 @@ Since one of Pomerium's core [principles] is to treat internal and external traf
- Pomerium's services **regardless** of if the network is "trusted"
- Pomerium and the destination application
## How
## Setting up DNS
First, you'll want to set a [CNAME](https://en.wikipedia.org/wiki/CNAME_record) record for wild-card domain name you will be using with Pomerium.
![pomerium add a text entry to your dns records](./img/certificate-wildcard-domain.png)
Once you've setup your wildcard domain, we can use acme.sh to create a certificate-signing request with LetsEncrypt.
## Certificates
### Per-route automatic certificates
Pomerium itself can be used to retrieve, manage, and renew certificates certificates for free using Let's Encrypt, the only requirement is that Pomerium is able to receive public traffic on ports `80`/`443`. This is probably the easiest option.
```yaml
autocert: true
```
### Self-signed wildcard certificate
In production, we'd use a public certificate authority such as LetsEncrypt. But for a local proof of concept or for development, we can use [mkcert](https://mkcert.dev/) to make locally trusted development certificates with any names you'd like. The easiest, is probably to use `*.localhost.pomerium.io` which we've already pre-configured to point back to localhost.
```bash
# Requires acme.sh @ https://github.com/Neilpang/acme.sh
# Install (after reviewing, obviously) by running :
# $ curl https://get.acme.sh | sh
$HOME/.acme.sh/acme.sh \
--issue \
-k ec-256 \
-d '*.corp.example.com' \
--dns \
--yes-I-know-dns-manual-mode-enough-go-ahead-please
Creating domain key
The domain key is here: $HOME/.acme.sh/*.corp.example.com_ecc/*.corp.example.com.key
Single domain='*.corp.example.com'
Getting domain auth token for each domain
Getting webroot for domain='*.corp.example.com'
Add the following TXT record:
Domain: '_acme-challenge.corp.example.com'
TXT value: 'Yz0B1Uf2xjyUI7Cr9-k96P2PQnw3RIK32dMViuvT58s'
Please be aware that you prepend _acme-challenge. before your domain
so the resulting subdomain will be: _acme-challenge.corp.example.com
Please add the TXT records to the domains, and re-run with --renew.
Please check log file for more details: $HOME/.acme.sh/acme.sh.log
Removing DNS records.
Not Found domain api file:
# Install mkcert.
go get -u github.com/FiloSottile/mkcert
# Bootstrap mkcert's root certificate into your operating system's trust store.
mkcert -install
# Create your wildcard domain.
# *.localhost.pomerium.io is helper domain we've hard-coded to route to localhost
mkcert "*.localhost.pomerium.io"
```
### Manual DNS Let's Encrypt wildcard certificate
Once you've setup your wildcard domain, we can use acme.sh to create a certificate-signing request with LetsEncrypt.
<<< @/docs/docs/reference/sh/generate_wildcard_cert.sh
LetsEncrypt will respond with the corresponding `TXT` record needed to verify our domain.
![pomerium add a text entry to your dns records](./img/certificate-domain-challenge.png)
It may take a few minutes for the DNS records to propagate. Once it does, you can run the following command to complete the certificate request process.
```bash
# Complete the certificate request now that we have validated our domain
$HOME/.acme.sh/acme.sh \
--renew \
--ecc \
-k ec-256 \
-d '*.corp.example.com' \
--dns \
--yes-I-know-dns-manual-mode-enough-go-ahead-please
Renew: '*.corp.example.com'
Single domain='*.corp.example.com'
Getting domain auth token for each domain
Verifying: *.corp.example.com
Success
Verify finished, start to sign.
Cert success.
-----BEGIN CERTIFICATE-----
.... snip...
-----END CERTIFICATE-----
Your cert is in $HOME/.acme.sh/*.corp.example.com_ecc/*.corp.example.com.cer
Your cert key is in $HOME/.acme.sh/*.corp.example.com_ecc/*.corp.example.com.key
The intermediate CA cert is in $HOME/.acme.sh/*.corp.example.com_ecc/ca.cer
And the full chain certs is there: $HOME/.acme.sh/*.corp.example.com_ecc/fullchain.cer
```
Here's how the above certificates signed by LetsEncrypt correspond to their respective Pomerium configuration settings:
| Pomerium Config | Certificate file |
| --------------------------- | -------------------------------------------------------------- |
| [CERTIFICATE] | `$HOME/.acme.sh/*.corp.example.com_ecc/fullchain.cer` |
| [CERTIFICATE_KEY] | `$HOME/.acme.sh/*.corp.example.com_ecc/*.corp.example.com.key` |
| [CERTIFICATE_AUTHORITY] | `$HOME/.acme.sh/*.corp.example.com_ecc/ca.cer` |
| [OVERRIDE_CERTIFICATE_NAME] | `*.corp.example.com` |
Pomerium Config | Certificate file
------------------------------ | --------------------------------------------------------------
[CERTIFICATE] | `$HOME/.acme.sh/*.corp.example.com_ecc/fullchain.cer`
[CERTIFICATE_KEY][certificate] | `$HOME/.acme.sh/*.corp.example.com_ecc/*.corp.example.com.key`
Your end users will see a valid certificate for all domains delegated by Pomerium.
@ -114,6 +83,12 @@ Your end users will see a valid certificate for all domains delegated by Pomeriu
![pomerium certificates A+ ssl labs rating](./img/certificates-ssl-report.png)
::: warning
LetsEncrypt certificates must be renewed [every 90 days](https://letsencrypt.org/2015/11/09/why-90-days.html).
:::
## Resources
Certificates, TLS, and Public Key Cryptography is a vast subject we cannot adequately cover here so if you are new to or just need a brush up, the following resources may be helpful:
@ -123,9 +98,9 @@ Certificates, TLS, and Public Key Cryptography is a vast subject we cannot adequ
- [Use TLS](https://smallstep.com/blog/use-tls.html) covers why TLS should be used everywhere; not just for securing typical internet traffic but for securing service communication in both "trusted" and adversarial situations.
- [Everything you should know about certificates and PKI but are too afraid to ask](https://smallstep.com/blog/everything-pki.html)
[certificate]: ../../configuration/readme.md#certificate
[certificate]: ../../configuration/readme.md#certificates
[certificate_authority]: ../../configuration/readme.md#certificate-authority
[certificate_key]: ../../configuration/readme.md#certificate-key
[certificate_key]: ../../configuration/readme.md#certificates
[override_certificate_name]: ../../configuration/readme.md#override-certificate-name
[principles]: ../docs/#why
[zero-trust]: ../docs/#why

View file

@ -0,0 +1,24 @@
#!/bin/bash
# acme.sh : https://github.com/Neilpang/acme.sh
# curl https://get.acme.sh | sh
# NOTA BENE:
# if you use a DNS service that supports API access, you may be able to automate
# this process. See https://github.com/Neilpang/acme.sh/wiki/dnsapi
echo "=> first generate a certificate signing request!"
$HOME/.acme.sh/acme.sh \
--issue \
-k ec-256 \
-d '*.corp.example.com' \
--dns \
--yes-I-know-dns-manual-mode-enough-go-ahead-please
read -p "press anykey once you've updated your TXT entries"
$HOME/.acme.sh/acme.sh \
--renew \
--ecc \
-k ec-256 \
-d '*.corp.example.com' \
--dns \
--yes-I-know-dns-manual-mode-enough-go-ahead-please