docs: add certificate section (#96)

Closes #88
This commit is contained in:
Bobby DeSimone 2019-04-27 20:21:43 -07:00 committed by GitHub
parent 857b9e5773
commit ce7a8b1f2d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 217 additions and 51 deletions

131
docs/docs/certificates.md Normal file
View file

@ -0,0 +1,131 @@
---
title: Certificates
lang: en-US
meta:
- name: keywords
content: x509 certificates tls mtls letsencrypt lets encrypt
---
# 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.
This guide uses the following tools and resources:
- [LetsEncrypt](https://letsencrypt.org/about/) is a _public_ certificate authority that issues free certificates trusted by the major browsers. Other [private](https://blog.cloudflare.com/how-to-build-your-own-public-key-infrastructure/) or [public](https://scotthelme.co.uk/are-ev-certificates-worth-the-paper-theyre-written-on/) CAs would also be fine.
- [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 certificates must be renewed [every 90 days](https://letsencrypt.org/2015/11/09/why-90-days.html).
:::
## Why
Since one of Pomerium's core [principles] is to treat internal and external traffic impartially, Pomerium uses [mutually authenticated TLS](https://en.wikipedia.org/wiki/Mutual_authentication) ubiquitously. For example, Pomerium uses mTLS between:
- end-user and Pomerium
- Pomerium's services **regardless** of if the network is "trusted"
- Pomerium and the destination application
## How
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](./certificates/certificate-wildcard-domain.png)
Once you've setup your wildcard domain, we can use acme.sh to create a certificate-signing request with LetsEncrypt.
```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:
```
LetsEncrypt will respond with the corresponding `TXT` record needed to verify our domain.
![pomerium add a text entry to your dns records](./certificates/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`
Your end users will see a valid certificate for all domains delegated by Pomerium.
![pomerium valid certificate](./certificates/certificates-valid-secure-certificate.png)
![pomerium certificates A+ ssl labs rating](./certificates/certificates-ssl-report.png)
## 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:
- [Why HTTPS for Everything?](https://https.cio.gov/everything/) The US government's CIO office has an excellent guide covering HTTPS and why future government sites will all be HTTPS.
- [Is TLS Fast](https://istlsfastyet.com/) debunks the performance myth associated with HTTPS.
- [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]: ../reference/#certificate
[certificate_authority]: ../reference/#certificate-authority
[certificate_key]: ../reference/#certificate-key
[override_certificate_name]: ../reference/#override-certificate-name
[principles]: ../docs/#why
[zero-trust]: ../docs/#why

Binary file not shown.

After

Width:  |  Height:  |  Size: 181 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 179 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 226 KiB

View file

@ -1,232 +0,0 @@
---
sidebar: auto
---
# Configuration Variables
Pomerium uses [environmental variables] to set configuration settings. If you are coming from a kubernetes or docker background this should feel familiar. If not, check out the following primers.
- [Store config in the environment](https://12factor.net/config)
- [Kubernetes: Environment variables](https://kubernetes.io/docs/tasks/inject-data-application/define-environment-variable-container/)
- [Docker: Environment variables](https://docs.docker.com/compose/environment-variables/)
## Global settings
These are configuration variables shared by all services, in all service modes.
### Service Mode
- Environmental Variable: `SERVICES`
- Type: `string`
- Default: `all`
- Options: `all` `authenticate` `authorize` or `proxy`
Service mode sets the pomerium service(s) to run. If testing, you may want to set to `all` and run pomerium in "all-in-one mode." In production, you'll likely want to spin up several instances of each service mode for high availability.
### Address
- Environmental Variable: `ADDRESS`
- Type: `string`
- Default: `:https`
Address specifies the host and port to serve HTTPS and gRPC requests from. If empty, `:https`/`:443` is used.
### Shared Secret
- Environmental Variable: `SHARED_SECRET`
- Type: [base64 encoded] `string`
- Required
Shared Secret is the base64 encoded 256-bit key used to mutually authenticate requests between services. It's critical that secret keys are random, and store safely. Use a key management system or `/dev/urandom/` to generate a key. For example:
```
head -c32 /dev/urandom | base64
```
### Policy
- Environmental Variable: either `POLICY` or `POLICY_FILE`
- Type: [base64 encoded] `string` or relative file location
- Filetype: `json` or `yaml`
- Required
Policy contains the routes, and their access policies. For example,
<<< @/policy.example.yaml
### Debug
- Environmental Variable: `POMERIUM_DEBUG`
- Type: `bool`
- Default: `false`
By default, JSON encoded logs are produced. Debug enables colored, human-readable logs to be streamed to [standard out](https://en.wikipedia.org/wiki/Standard_streams#Standard_output_(stdout)). In production, it's recommended to be set to `false`.
For example, if `true`
```
10:37AM INF cmd/pomerium version=v0.0.1-dirty+ede4124
10:37AM INF proxy: new route from=httpbin.corp.beyondperimeter.com to=https://httpbin.org
10:37AM INF proxy: new route from=ssl.corp.beyondperimeter.com to=http://neverssl.com
10:37AM INF proxy/authenticator: grpc connection OverrideCertificateName= addr=auth.corp.beyondperimeter.com:443
```
If `false`
```
{"level":"info","version":"v0.0.1-dirty+ede4124","time":"2019-02-18T10:41:03-08:00","message":"cmd/pomerium"}
{"level":"info","from":"httpbin.corp.beyondperimeter.com","to":"https://httpbin.org","time":"2019-02-18T10:41:03-08:00","message":"proxy: new route"}
{"level":"info","from":"ssl.corp.beyondperimeter.com","to":"http://neverssl.com","time":"2019-02-18T10:41:03-08:00","message":"proxy: new route"}
{"level":"info","OverrideCertificateName":"","addr":"auth.corp.beyondperimeter.com:443","time":"2019-02-18T10:41:03-08:00","message":"proxy/authenticator: grpc connection"}
```
### Log Level
- Environmental Variable: `LOG_LEVEL`
- Type: `string`
- Options: `debug` `info` `warn` `error`
- Default: `debug`
Log level sets the global logging level for pomerium. Only logs of the desired level and above will be logged.
### Certificate
- Environmental Variable: either `CERTIFICATE` or `CERTIFICATE_FILE`
- Type: [base64 encoded] `string` or relative file location
- Required
Certificate is the x509 _public-key_ used to establish secure HTTP and gRPC connections. If unset, pomerium will attempt to find and use `./cert.pem`.
### Certificate Key
- Environmental Variable: either `CERTIFICATE_KEY` or `CERTIFICATE_KEY_FILE`
- Type: [base64 encoded] `string`
- Required
Certificate key is the x509 _private-key_ used to establish secure HTTP and gRPC connections. If unset, pomerium will attempt to find and use `./privkey.pem`.
## Authenticate Service
### Authenticate Service URL
- Environmental Variable: `AUTHENTICATE_SERVICE_URL`
- Type: `URL`
- Required
- Example: `https://authenticate.corp.example.com`
Authenticate Service URL is the externally accessible URL for the authenticate service.
### Identity Provider Name
- Environmental Variable: `IDP_PROVIDER`
- Type: `string`
- Required
- Options: `azure` `google` `okta` `gitlab` `onelogin` or `oidc`
Provider is the short-hand name of a built-in OpenID Connect (oidc) identity provider to be used for authentication. To use a generic provider,set to `oidc`.
See [identity provider] for details.
### Identity Provider Client ID
- Environmental Variable: `IDP_CLIENT_ID`
- Type: `string`
- Required
Client ID is the OAuth 2.0 Client Identifier retrieved from your identity provider. See your identity provider's documentation, and our [identity provider] docs for details.
### Identity Provider Client Secret
- Environmental Variable: `IDP_CLIENT_SECRET`
- Type: `string`
- Required
Client Secret is the OAuth 2.0 Secret Identifier retrieved from your identity provider. See your identity provider's documentation, and our [identity provider] docs for details.
### Identity Provider URL
- Environmental Variable: `IDP_PROVIDER_URL`
- Type: `string`
- Required, depending on provider
Provider URL is the base path to an identity provider's [OpenID connect discovery document](https://openid.net/specs/openid-connect-discovery-1_0.html). For example, google's URL would be `https://accounts.google.com` for [their discover document](https://accounts.google.com/.well-known/openid-configuration).
### Identity Provider Scopes
- Environmental Variable: `IDP_SCOPES`
- Type: `[]string` comma separated list of oauth scopes.
- Default: `oidc`,`profile`, `email`, `offline_access` (typically)
- Optional for built-in identity providers.
Identity provider scopes correspond to access privilege scopes as defined in Section 3.3 of OAuth 2.0 RFC6749\. The scopes associated with Access Tokens determine what resources will be available when they are used to access OAuth 2.0 protected endpoints. If you are using a built-in provider, you probably don't want to set customized scopes.
### Identity Provider Service Account
- Environmental Variable: `IDP_SERVICE_ACCOUNT`
- Type: `string`
- Required, depending on provider
Identity Provider Service Account is field used to configure any additional user account or access-token that may be required for querying additional user information during authentication. For a concrete example, Google an additional service account and to make a follow-up request to query a user's group membership. For more information, refer to the [identity provider] docs to see if your provider requires this setting.
## Proxy Service
### Signing Key
- Environmental Variable: `SIGNING_KEY`
- Type: [base64 encoded] `string`
- Optional
Signing key is the base64 encoded key used to sign outbound requests. For more information see the [signed headers](./signed-headers.md) docs.
### Authenticate Service URL
- Environmental Variable: `AUTHENTICATE_SERVICE_URL`
- Type: `URL`
- Required
- Example: `https://authenticate.corp.example.com`
Authenticate Service URL is the externally accessible URL for the authenticate service.
### Authenticate Internal Service URL
- Environmental Variable: `AUTHENTICATE_INTERNAL_URL`
- Type: `string`
- Optional
- Example: `pomerium-authenticate-service.pomerium.svc.cluster.local`
Authenticate Internal Service URL is the internally routed dns name of the authenticate service. This setting is typically used with load balancers that do not gRPC, thus allowying you to specificy an internally routable name.
### Authorize Service URL
- Environmental Variable: `AUTHORIZE_SERVICE_URL`
- Type: `URL`
- Required
- Example: `https://access.corp.example.com` or `pomerium-authorize-service.pomerium.svc.cluster.local`
Authorize Service URL is the location of the internally routable authorize service. NOTE: Unlike authenticate, authorize has no publically acccessible http handlers so this setting is purely for gRPC communicaiton.
If your load balancer does not support gRPC passthrough you'll need to set this value to an internally routable location (`pomerium-authorize-service.pomerium.svc.cluster.local`) instead of an externally routable one (`https://access.corp.example.com`).
### Override Certificate Name
- Environmental Variable: `OVERRIDE_CERTIFICATE_NAME`
- Type: `int`
- Optional (but typically required if Authenticate Internal Service Address is set)
- Example: `*.corp.example.com` if wild card or `authenticate.corp.example.com`/`authorize.corp.example.com`
When Authenticate Internal Service Address is set, secure service communication can fail because the external certificate name will not match the internally routed service url. This setting allows you to override that check.
### Certificate Authority
- Environmental Variable: `CERTIFICATE_AUTHORITY` or `CERTIFICATE_AUTHORITY_FILE`
- Type: [base64 encoded] `string` or relative file location
- Optional
Certificate Authority is set when behind-the-ingress service communication uses self-signed certificates. Be sure to include the intermediary certificate.
[base64 encoded]: https://en.wikipedia.org/wiki/Base64
[environmental variables]: https://en.wikipedia.org/wiki/Environment_variable
[identity provider]: ./identity-providers.md
[letsencrypt]: https://letsencrypt.org/
[oidc rfc]: https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest
[script]: https://github.com/pomerium/pomerium/blob/master/scripts/generate_wildcard_cert.sh

View file

@ -2,7 +2,7 @@
sidebarDepth: 3
---
# Example Configurations
# Example configs
A collection of copy-and-paste-able configurations for various types of clouds, use-cases, and deployments. These files can also be found in the git repository in the `docs/docs/examples/` directory.
@ -35,7 +35,7 @@ Uses the [latest pomerium build](https://hub.docker.com/r/pomerium/pomerium) fro
- Minimal container-based configuration.
- Docker and Docker-Compose based.
- Runs a single container for all pomerium services
- Routes default to on-prem [helloworld], [httpbin].
- Routes default to on-premise [helloworld], [httpbin].
Customize for your identity provider run `docker-compose up -f basic.docker-compose.yml`
@ -48,7 +48,7 @@ Customize for your identity provider run `docker-compose up -f basic.docker-comp
- Docker and Docker-Compose based.
- Uses pre-configured built-in nginx load balancer
- Runs separate containers for each service
- Routes default to on-prem [helloworld], and [httpbin].
- Routes default to on-premise [helloworld], and [httpbin].
Customize for your identity provider run `docker-compose up -f nginx.docker-compose.yml`

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

View file

@ -2,27 +2,46 @@
## What
Pomerium is an open-source, identity-aware access proxy.
Pomerium is an identity-aware access proxy. Pomerium can be used to:
- enable secure remote access to internal websites, without a VPN.
- provide unified authentication ([SSO]) using the [identity provider] of your choice.
- enforce dynamic access policy based on context, identity, and device state.
- aggregate access logs and telemetry data.
## Why
Traditional [perimeter](https://www.redbooks.ibm.com/redpapers/pdfs/redp4397.pdf) [security](https://en.wikipedia.org/wiki/Perimeter_Security) has some shortcomings, namely:
### Perimeter security's shortcomings
- Insider threat is not well addressed and 28% of breaches are [by internal actors](http://www.documentwereld.nl/files/2018/Verizon-DBIR_2018-Main_report.pdf).
- Impenetrable fortress in theory falls in practice; multiple entry points (like VPNs), lots of firewall rules, network segmentation creep.
- Failure to encapsulate a heterogeneous mix of cloud, on-premise, cloud, and multi-cloud environments.
- User's don't like VPNs.
For years, secure remote access meant firewalls, network segmentation, and VPNs. However, several [high-profile](https://en.wikipedia.org/wiki/Operation_Aurora) [security](https://krebsonsecurity.com/2014/02/target-hackers-broke-in-via-hvac-company/) breaches have shown the limitations of [perimeter](https://www.redbooks.ibm.com/redpapers/pdfs/redp4397.pdf) [security](https://en.wikipedia.org/wiki/Perimeter_Security), namely:
Pomerium attempts to mitigate these shortcomings by adopting the following principles.
- Perimeter security does a poor job of addressing the insider-threat and 28% percent of breaches are [by internal actors](http://www.documentwereld.nl/files/2018/Verizon-DBIR_2018-Main_report.pdf).
- The _impenetrable fortress_ theory of perimeter security is anything but in practice; most corporate networks have multiple entry points, lots of firewall rules, and constant pressure to expand network segmentation boundaries.
- Even defining "what" a perimeter is is difficult as corporate networks have come to consist of an increasingly [heterogeneous](https://youtu.be/bDJb8WOJYdA?t=532) mix of on-premise, public, and private clouds.
- VPNs frustrate end-users, give a false sense of security, and often fail to provide defense-in-depth.
- Trust flows from user, device, and context.
- Network location _does not impart trust_. Treat both internal and external networks as completely untrusted.
- Act like you are already breached, because your probably are.
Or for the visually inclined.
![NSA exploiting google's SSL termination](./google-cloud-exploitation620x466.jpg)
> SSL added and removed here :^) - [NSA](https://www.zdnet.com/article/google-the-nsa-and-the-need-for-locking-down-datacenter-traffic/)
### Zero-trust
Pomerium -- and zero-trust more broadly -- attempts to mitigate these shortcomings by adopting principles like:
- Trust flows from identity, device-state, and context; not network location.
- Treat both internal and external networks as completely untrusted.
- Act like you are already breached, because you probably are.
- Every device, user, and application's communication should be authenticated, authorized, and encrypted.
- Policy should be dynamic, and built from multiple sources.
- Access policy should be dynamic, and built from multiple sources.
## Resources
Pomerium was designed around the security model originally articulated by [John Kindervag](http://www.virtualstarmedia.com/downloads/Forrester_zero_trust_DNA.pdf) in 2010, and by Google in 2011 which as a result of the [Operation Aurora](https://en.wikipedia.org/wiki/Operation_Aurora) breach.
Typically this approach to security is called either zero-trust or BeyondCorp-inspired. Here's a curated list of resources covering th
### Books
- [Zero Trust Networks](http://shop.oreilly.com/product/0636920052265.do) by Gilman and Barth
@ -51,3 +70,6 @@ Pomerium attempts to mitigate these shortcomings by adopting the following princ
- [What, Why, and How of Zero Trust Networking](https://youtu.be/eDVHIfVSdIo?list=PLKb9-P1fRHxhSmCy5OaYZ5spcY8v3Pbaf) by Armon Dadgar, Hashicorp
- [O'Reilly Security 2017 NYC Beyondcorp: Beyond Fortress Security](https://youtu.be/oAvDASLehpY?list=PLKb9-P1fRHxhSmCy5OaYZ5spcY8v3Pbaf) by Neal Muller, Google
- [Be Ready for BeyondCorp: enterprise identity, perimeters and your application](https://youtu.be/5UiWAlwok1s?list=PLKb9-P1fRHxhSmCy5OaYZ5spcY8v3Pbaf) by Jason Kent
[identity provider]: ../docs/identity-providers.md
[sso]: https://en.wikipedia.org/wiki/Single_sign-on

View file

@ -8,13 +8,7 @@ description: >-
# Securing your app with signed headers
This page describes how to secure your app with signed headers. When configured, pomerium uses JSON Web Tokens (JWT) to make sure that a request to your app is authorized.
::: warning
Health checks don't include JWT headers and pomerium doesn't handle health checks. If your health check returns access errors, make sure that you have it configured correctly and that your JWT header validation whitelists the health check path.
:::
This page describes how to add an additional layer of security to your apps with signed headers. When configured, pomerium uses JSON Web Tokens (JWT) to make sure that a given request was handled by pomerium and the request to your app is authorized.
## Prerequisites
@ -27,9 +21,9 @@ To secure your app with signed headers, you'll need the following:
Signed headers provide **secondary** security in case someone bypasses mTLS and network segmentation. This protects your app from the following kind of risks:
- Pomerium is accidentally disabled;
- Misconfigured firewalls;
- Mutually-authenticated TLS;
- Pomerium is accidentally disabled
- Misconfigured firewalls
- Mutually-authenticated TLS
- Access from within the project.
To properly secure your app, you must use signed headers for all app types.