updated README.md

pull/31/head
Mike Malone 5 years ago
parent 32c7be6f9d
commit e70a5dae7d

@ -1,27 +1,65 @@
![Autocert architecture diagram](https://raw.githubusercontent.com/smallstep/certificates/autocert/autocert/autocert-logo.png)
# Autocert # Autocert
[![GitHub stars](https://img.shields.io/github/stars/smallstep/certificates.svg)](https://github.com/smallstep/certificates/stargazers)
[![GitHub release](https://img.shields.io/github/release/smallstep/certificates.svg)](https://github.com/smallstep/certificates/releases)
[![CA Image](https://images.microbadger.com/badges/image/smallstep/step-ca.svg)](https://microbadger.com/images/smallstep/step-ca)
[![Go Report Card](https://goreportcard.com/badge/github.com/smallstep/certificates)](https://goreportcard.com/report/github.com/smallstep/certificates)
<!--- [![Build Status](https://travis-ci.org/smallstep/certificates.svg?branch=master)](https://travis-ci.org/smallstep/certificates)
[![Coverage Status](https://coveralls.io/repos/github/smallstep/certificates/badge.svg?branch=master)](https://coveralls.io/github/smallstep/certificates?branch=master)
[![Autocert Image](https://images.microbadger.com/badges/image/smallstep/autocert-controller.svg)](https://microbadger.com/images/smallstep/autocert-controller)
[![Renewer Image](https://images.microbadger.com/badges/image/smallstep/autocert-renewer.svg)](https://microbadger.com/images/smallstep/autocert-renewer) -->
**Autocert** is a kubernetes add-on that automatically injects TLS/HTTPS certificates into your containers. **Autocert** is a kubernetes add-on that automatically injects TLS/HTTPS certificates into your containers.
<p align="center"><img src="demo.gif" style="max-width: 600px" alt="Animated terminal showing autocert in practice"></p> <!--- 👋 Welcome. We ❤️ feedback. Submit an issue. Fork and send a PR. Give us a ⭐ if you like what we're doing. --->
To request a certificate simply annotate your pods with a name. Certificates are issued by a private **internal certificate authority** that runs on your cluster and are mounted at `/var/run/autocert.step.sm` along with a corresponding private key and root certificate. To get a certificate **simply annotate your pods** with a name. An X.509 (TLS/HTTPS) certificate is automatically created and mounted at `/var/run/autocert.step.sm/` along with a corresponding private key and root certificate (everything you need for [mTLS](#motivation)).
TLS (e.g., HTTPS) is the most widely deployed cryptographic protocol in the world. Mutual TLS (mTLS) provides end-to-end security for service-to-service communication and can **replace complex VPNs** to secure communication into, out of, and between kubernetes clusters. But **to use mTLS you need certificates issued by your own certificate authority (CA)**. > *Note: this project is in **ALPHA**. DON'T use it for anything mission critical. EXPECT breaking changes in minor revisions with little or not warning. PLEASE provide feedback:*
Building and operating a CA, issuing certificates, and making sure they're renewed before they expire is tricky. Autocert does all of this for you. TODO: Twitter, Slack, Issues (tagged with #autocert / special template)...
![Autocert demo gif](https://raw.githubusercontent.com/smallstep/certificates/autocert/autocert/demo.gif)
## Table of Contents
* [Features](#features)
* [Motivation](#motivation)
* [Getting Started](#getting-started)
* [Prerequisites](#prerequisites)
* [Installation](#install)
* [Enabling autocert](#enable-autocert)
* [Annotating pods](#annotate-pods)
* [Examples](#example)
* [Mutual TLS](#mutual-tls)
* [Getting a certificate locally](#local-certificate)
* [How it works](#how-it-works)
* [Uninstalling](#uninstalling)
* [Questions](#questions)
## Features
## Key Features Autocert uses [`step certificates`](https://github.com/smallstep/certificates) to generate keys and issue certificates from your own **internal certificate authority**. This process is secure and automatic, all you have to do is [install autocert](#install) and [annotate your pods](#annotate-pods). Features include:
* A complete public key infrastructure that you control for your kubernetes clusters * A complete **public key infrastructure** (PKI) for your kubernetes clusters
* Certificate authority that's easy to initialize and install * A fully featured internal **certificate authority** (CA) that you control so you can **use mTLS to control access to services**
* Automatic injection of certificates and keys in annotated containers * Ability to run subnordinate to or federated with an existing PKI
* Enable on a per-namespace basis * CA and PKI artifacts are installed in their own namespace (`step`) for easy access control
* Namespaced installation to restrict access to privileged CA and provisioner containers * Modern certificate best practices
* Ability to run subordinate to an existing public key infrastructure * Automated certificate management (auto enrollment and renewal)
* Supports federatation with other roots * Short-lived certificates
* Short-lived certificates * Private keys are never transmitted across the network (and aren't stored in `etcd`)
* Automatic renewal * RFC5280 and CA/Browser Forum compliant certificates that work with browsers and other standard TLS implementations
* Uses your own certificate authority -- you control who or what gets a certificate * Easily enable/disable per-namespace [using labels](#enable-autocert)
* Builds on [`step certificates`](https://github.com/smallstep/certificates) so you can also issue certificates to servers, people, and code running in a different cluster and outside of kubernetes
## Motivation
TLS (e.g., HTTPS) is the most widely deployed cryptographic protocol in the world. Mutual TLS (mTLS) provides end-to-end security for service-to-service communication and can **replace complex VPNs** to secure communication into, out of, and between kubernetes clusters. But **to use mTLS to secure internal services you need certificates issued by your own certificate authority (CA)**.
Building and operating a CA, issuing certificates, and making sure they're renewed before they expire is tricky. Autocert does all of this for you.
## Getting Started ## Getting Started
@ -29,15 +67,7 @@ These instructions will get `autocert` installed quickly on an existing kubernet
### Prerequisites ### Prerequisites
Make sure you've [`installed step`](https://github.com/smallstep/cli#installing) version `0.8.3` or later: You'll need `kubectl` and a kubernetes cluster running version `1.9` or later with [webhook admission controllers](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#admission-webhooks) enabled:
```bash
$ step version
Smallstep CLI/0.8.3 (darwin/amd64)
Release Date: 2019-01-16 01:46 UTC
```
You'll also need `kubectl` and a kubernetes cluster running version `1.9` or later with [webhook admission controllers](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#admission-webhooks) enabled:
```bash ```bash
$ kubectl version --short $ kubectl version --short
@ -47,18 +77,12 @@ $ kubectl api-versions | grep "admissionregistration.k8s.io/v1beta1"
admissionregistration.k8s.io/v1beta1 admissionregistration.k8s.io/v1beta1
``` ```
We'll be creating a new kubernetes namespace and setting up some RBAC rules during installation. You'll need appropriate permissions in your cluster (e.g., you may need to be cluster-admin). For [manual installation](INSTALL.md) you'll also need to [`install step`](https://github.com/smallstep/cli#installing) version `0.8.3` or later.
```bash
TODO: Check whether you have cluster permissions..? GKE instructions here if you don't have them.
```
In order to grant these permissions you may need to give yourself cluster-admin rights in your cluster. GKE, in particular, does not give the cluster owner these rights by default. You can give yourself cluster-admin rights by running:
```bash ```bash
kubectl create clusterrolebinding cluster-admin-binding \ $ step version
--clusterrole cluster-admin \ Smallstep CLI/0.8.3 (darwin/amd64)
--user $(gcloud config get-value account) Release Date: 2019-01-16 01:46 UTC
``` ```
### Install ### Install
@ -69,23 +93,41 @@ To install `step certificates` and `autocert` in one step run:
$ kubectl run autocert-init -it --rm --image smallstep/autocert-init --restart Never $ kubectl run autocert-init -it --rm --image smallstep/autocert-init --restart Never
``` ```
You may need to adjust the RBAC policies to run `autocert-init`: The init script will end by printing:
```bash * The admin provisioner password (also used to encrypt the CA's key material)
$ kubectl create clusterrolebinding autocert-init-binding --clusterrole cluster-admin --user "system:serviceaccount:default:default" * The `autocert` provisioner password (used by the mutating webhook)
``` * Your CA's root certificate fingerprint (used to bootstrap secure communication)
Once `autocert-init` is complete you can delete this binding: Feel free to store these some place safe. The passwords are also stored as secrets in the `step` namespace.
```bash > 🤔 **Tip:** If you lose your root certificate fingerprint you can calculate it again by running:
$ kubectl delete clusterrolebinding autocert-init-binding >
``` > ```
> $ export CA_POD=$(kubectl -n step get pods -l app=ca \
You can also [install manually](INSTALL.md). > -o jsonpath={$.items[0].metadata.name})
> $ kubectl -n step exec -it $CA_POD -- step certificate fingerprint /home/step/.step/certs/root_ca.crt
> ```
> 🤯 **Note:** You may need to adjust your RBAC policies to run `autocert-init`:
>
> ```bash
> $ kubectl create clusterrolebinding autocert-init-binding \
> --clusterrole cluster-admin \
> --user "system:serviceaccount:default:default"
> ```
>
> Once `autocert-init` is complete you can delete this binding:
>
> ```bash
> $ kubectl delete clusterrolebinding autocert-init-binding
> ```
Feel free to [check out what the `autocert-init` container does](init/autocert.sh) if you're curious. You can also [install manually](INSTALL.md).
### Enable autocert ### Enable autocert
To enable `autocert` for a namespace the `autocert.step.sm=enabled` label (the `autocert` webhook will not affect namespaces for which it is not enabled). To enable `autocert` for the default namespace run: To enable `autocert` for a namespace it must be labelled `autocert.step.sm=enabled`. To label the `default` namespace run:
```bash ```bash
$ kubectl label namespace default autocert.step.sm=enabled $ kubectl label namespace default autocert.step.sm=enabled
@ -102,11 +144,9 @@ default Active 59m enabled
### Annotate pods ### Annotate pods
In addition to enabling `autocert` for a namespace, pods must be annotated with their name for certificates to be injected. The annotated name will appear as the common name and SAN in the issued certificate. For `autocert` to inject a certificate pods must use the `autocert.step.sm/name` annotation to specify their name. The value of this annotation will appear as the name in the issued certificate (the X.509 common name and SAN).
To trigger certificate injection pods must be annotated at creation time. You can do this in your deployment YAMLs:
```bash ```yaml
$ cat <<EOF | kubectl apply -f - $ cat <<EOF | kubectl apply -f -
apiVersion: apps/v1 apiVersion: apps/v1
kind: Deployment kind: Deployment
@ -117,6 +157,7 @@ spec:
template: template:
metadata: metadata:
annotations: annotations:
# Autocert annotation
autocert.step.sm/name: sleep.default.svc.cluster.local autocert.step.sm/name: sleep.default.svc.cluster.local
labels: {app: sleep} labels: {app: sleep}
spec: spec:
@ -124,83 +165,299 @@ spec:
- name: sleep - name: sleep
image: alpine image: alpine
command: ["/bin/sleep", "86400"] command: ["/bin/sleep", "86400"]
imagePullPolicy: IfNotPresent
EOF EOF
``` ```
The `autocert` admission webhook will intercept this pod creation request and inject an init container and sidecar to manage certificate issuance and renewal, respectively. Once the pod has started we can check that our certificate, private key, and root certificate have been properly mounted in our container at `/var/run/autocert.step.sm`.
```bash
$ export SLEEP_POD=$(kubectl get pods -l app=sleep \
-o jsonpath={$.items[0].metadata.name})
$ kubectl exec -it $SLEEP_POD -c sleep -- ls /var/run/autocert.step.sm
root.crt site.crt site.key
```
> 🤔 **Tip:** The `autocert-renewer` sidecar also installs the [`step` CLI tool](https://github.com/smallstep/cli), which we can use to inspect the issued certificate.
>
> ```bash
> $ kubectl exec -it $SLEEP_POD -c autocert-renewer -- step \
> certificate inspect /var/run/autocert.step.sm/site.crt
> Certificate:
> Data:
> Version: 3 (0x2)
> Serial Number: 38872628668914277126045555806003435350 (0x1d3e9890a42ae5861b8a6cb51aa29756)
> Signature Algorithm: ECDSA-SHA256
> Issuer: CN=Autocert Intermediate CA
> Validity
> Not Before: Jan 19 01:59:06 2019 UTC
> Not After : Jan 20 01:59:06 2019 UTC
> Subject: CN=sleep.default.svc.cluster.local
> Subject Public Key Info:
> Public Key Algorithm: ECDSA
> Public-Key: (256 bit)
> X:
> e9:f7:f6:04:c5:b5:af:c7:ff:95:19:69:09:74:57:
> 31:a9:24:a7:31:d8:e4:f1:2a:0e:8c:89:fa:b5:aa:
> fa:d9
> Y:
> 26:bc:6c:0f:ad:57:6e:75:ea:8e:d5:ca:bf:b0:c9:
> 43:61:dc:42:8a:ef:42:79:17:b7:02:8a:07:2e:58:
> 4c:50
> Curve: P-256
> X509v3 extensions:
> X509v3 Key Usage: critical
> Digital Signature, Key Encipherment
> X509v3 Extended Key Usage:
> TLS Web Server Authentication, TLS Web Client Authentication
> X509v3 Subject Key Identifier:
> BE:3E:92:68:7D:82:61:91:93:C2:E0:DF:77:1F:CD:EF:36:2D:8E:41
> X509v3 Authority Key Identifier:
> keyid:69:BA:E5:9C:6D:66:39:B3:3E:8B:28:85:26:75:34:A6:91:07:F6:4E
> X509v3 Subject Alternative Name:
> DNS:sleep.default.svc.cluster.local
> X509v3 Step Provisioner:
> Type: JWK
> Name: autocert
> CredentialID: 7OOZUAEgixopdF_Yk7wMtkHv-op6p8FqSfEk3B6nry0
>
> Signature Algorithm: ECDSA-SHA256
> 30:45:02:20:6c:79:31:69:11:65:88:48:fc:a0:a0:f4:8e:bd:
> 81:62:83:6a:d7:66:fa:9c:d0:43:1e:15:69:3a:3c:e0:8e:2b:
> 02:21:00:c2:4a:51:85:25:4f:c1:68:de:07:50:53:8c:36:b3:
> 2c:a3:56:d1:1d:11:3d:aa:77:d1:2e:1e:54:75:1d:f3:0d
> ```
## Examples
With `autocert` issuing and rotating certificates we can start using mTLS between services. The [`examples/hello-mtls`](examples/hello-mtls) directory demonstrates the right way to do mTLS in several languages (contributions welcome :). Let's deploy one.
### Mutual TLS
Build and deploy the `hello-mtls` server for golang:
```bash
$ cd examples/hello-mtls/go
$ docker build -f Dockerfile.server -t hello-mtls-server-go .
$ kubectl apply -f hello-mtls.server.yaml
```
Build and deploy the `hello-mtls` client for golang:
```bash
$ docker build -f Dockerfile.client -t hello-mtls-client-go .
$ kubectl apply -f hello-mtls.client.yaml
```
Check that the client is connecting and working as expected:
```bash
$ export HELLO_MTLS=$(kubectl get pods -l app=hello-mtls-client \
-o jsonpath={$.items[0].metadata.name})
$ kubectl logs $HELLO_MTLS -c hello-mtls-client -f
2019-01-25T01:36:57Z: Hello, hello-mtls-client.default.pod.cluster.local!
2019-01-25T01:37:02Z: Hello, hello-mtls-client.default.pod.cluster.local!
2019-01-25T01:37:07Z: Hello, hello-mtls-client.default.pod.cluster.local!
...
```
We can also `exec` into the `sleep` container we deployed earlier
```bash ```bash
$ kubectl get pods -l app=sleep \ $ kubectl exec -it $SLEEP_POD -c sleep -- sh
-o=custom-columns=NAME:.metadata.name,CONTAINERS:.spec.containers[*].name,INIT_CONTAINERS:.spec.initContainers[*].name
NAME CONTAINERS INIT_CONTAINERS
sleep-f996bd578-tzwvm sleep,autocert-renewer autocert-bootstrapper
``` ```
Certificates are mounted in containers at `/var/run/autocert.step.sm`. We can inspect this directory to make sure everything worked correctly: install `curl`, and hit `hello-mtls` from there:
```bash ```bash
$ kubectl exec -it sleep-f996bd578-nch7c -c sleep -- ls -lias /var/run/autocert.step.sm sleep# apk add curl
total 20 sleep# curl --cacert /var/run/autocert.step.sm/root.crt \
1593393 4 drwxrwxrwx 2 root root 4096 Jan 17 21:27 . --cert /var/run/autocert.step.sm/site.crt \
1339651 4 drwxr-xr-x 1 root root 4096 Jan 17 21:27 .. --key /var/run/autocert.step.sm/site.key \
1593451 4 -rw------- 1 root root 574 Jan 17 21:27 root.crt https://hello-mtls.default.svc.cluster.local
1593442 4 -rw-r--r-- 1 root root 1352 Jan 17 21:41 site.crt Hello, sleep.default.svc.cluster.local!
1593443 4 -rw-r--r-- 1 root root 227 Jan 17 21:27 site.key ```
> 🤯 **A few ways things that can go sideways:**
>
> If we don't provide a client certificate for authentication the request will fail because we haven't authenticated ourselves to the server:
>
> ```
> sleep# curl --cacert /var/run/autocert.step.sm/root.crt \
> https://hello-mtls.default.svc.cluster.local
> curl: (35) error:1401E412:SSL routines:CONNECT_CR_FINISHED:sslv3 alert bad certificate
> ```
>
> `curl` will also balk if we don't tell it to trust our `root.crt`, this time because it can't validate the server's certificate:
>
> ```
> sleep# curl https://hello-mtls.default.svc.cluster.local
> curl: (60) SSL certificate problem: unable to get local issuer certificate
> More details here: https://curl.haxx.se/docs/sslcerts.html
>
> curl failed to verify the legitimacy of the server and therefore could not
> establish a secure connection to it. To learn more about this situation and
> how to fix it, please visit the web page mentioned above.
> ```
>
> You'll get similar errors from other tools, libraries, and applications if they're not properly configured to use the `autocert` certificates and keys. Minimally, for (non-mutual) TLS:
>
> * Clients must be configured to trust the `autocert` root certificate (`/var/run/autocert.step.sm/root.crt`) to authenticate a server
> * Servers must be configured to use the key and certificate issued by `autocert` (`/var/run/autocert.step.sm/site.crt` and `/var/run/autocert.step.sm/site.key`) to authenticate *to* a client
>
> If you're doing mTLS the inverse is also true: the server must trust the root certificate to authenticate client, and the client must be configured to use the `autocert`-issued key and certificate. In other words, for mTLS both the client and server should be configured to use `autocert`'s `root.crt`, `site.crt`, and `site.key`. With `curl` this is done using the `--cacert`, `--cert`, and `--key` flags, respectively.
### Exposing services using mTLS
With properly configured mTLS, services can be safely exposed directly to the public internet: **only clients that have a certificate issued by the internal certificate authority will be allowed to connect**. To demonstrate let's expose our `hello-mtls` service.
If you need a refresher, here's a rough approximation of how an mTLS handshake works:
![mTLS handshake diagram](https://raw.githubusercontent.com/smallstep/certificates/autocert/autocert/mtls-handshake.png)
A few things to note:
* It's the signing of random numbers that proves we're talking to the right remote. It's the digital equivalent of asking someone to send you a photo of them with today's newspaper.
* The client and server need to have prior knowledge of the root certificate(s) used for signing other certificates.
* The client and server need to be configured to use the correct certificate and private key (the certificate must have been issued by a CA with a trusted root certificate)
#### Exposing `hello-mtls`
Because `hello-mtls` does proper mTLS itself we can expose it simply using a [service with type LoadBalancer](https://kubernetes.io/docs/concepts/services-networking/service/#loadbalancer).
```
$ kubectl expose deployment hello-mtls --name=hello-mtls-lb --port=443 --target-port=443 --type=LoadBalancer
service/loadbalancer exposed
$ kubectl get svc hello-mtls-lb
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
hello-mtls-lb LoadBalancer 10.0.65.118 104.198.149.140 443/TCP 5m
``` ```
The `autocert-renewer` sidecar also installs the `step` CLI tool, which we can use to inspect the issued certificate: #### Obtaining a certificate locally
To connect to `hello-mtls` from outside kubernetes we need a certificate issued by our internal CA. Since `autocert` is built on `step certificates` we can securely issue certificates to users, devices, and workloads running in other environments.
> 🤯 **Note:** To follow along you'll need `step` [installed locally](https://github.com/smallstep/cli#installing).
First, port-forward from localhost to the `step-ca` pod:
```
$ export CA_POD=$(kubectl -n step get pods -l app=ca \
-o jsonpath={$.items[0].metadata.name})
$ kubectl -n step port-forward $CA_POD 4443:4443
```
Now we can use `step` to securely grab the CA's root certificate and obtain a certificate. You'll be prompted to select a provisioner and enter the correct password to continue:
```bash ```bash
$ kubectl exec -it sleep-f996bd578-nch7c -c autocert-renewer -- step certificate inspect /var/run/autocert.step.sm/site.crt # Get root certificate fingerprint
Certificate: $ export FINGERPRINT="$(kubectl -n step exec -it $CA_POD -- \
Data: step certificate fingerprint /home/step/.step/certs/root_ca.crt | tr -d '[:space:]')"
Version: 3 (0x2)
Serial Number: 46935033335539540860078000614852612373 (0x234f5bce23705f015a8377ab1cfd5115) # Fetch and verify root certificate
Signature Algorithm: ECDSA-SHA256 $ step ca root root.crt \
Issuer: CN=Autocert Intermediate CA --ca-url https://127.0.0.1:4443 \
Validity --fingerprint $FINGERPRINT
Not Before: Jan 17 21:41:04 2019 UTC
Not After : Jan 17 21:46:14 2019 UTC # Get a certificate locally
Subject: CN=sleep.default.svc.cluster.local $ step ca certificate snarf.local.dev snarf.crt snarf.key \
Subject Public Key Info: --ca-url https://127.0.0.1:4443 \
Public Key Algorithm: ECDSA --root root.crt
Public-Key: (256 bit) ✔ Key ID: H4vH5VfvaMro0yrk-UIkkeCoPFqEfjF6vg0GHFdhVyM (admin)
X: ✔ Please enter the password to decrypt the provisioner key: 0QOC9xcq56R1aEyLHPzBqN18Z3WfGZ01
31:aa:a1:7f:c8:b4:c6:da:90:fc:b8:3a:e9:cc:48: ✔ CA: https://127.0.0.1:4443/1.0/sign
f9:89:b9:5d:d7:a4:63:80:76:9f:21:6d:e5:88:4c: ✔ Certificate: snarf.crt
a8:e4 ✔ Private Key: snarf.key
Y: $ step ca certificate snarf.local.dev snarf.crt snarf.key
ed:21:38:57:cd:3f:32:71:6f:ca:81:34:b0:4a:bd: ```
a3:c4:8d:d1:87:bc:2c:4c:42:79:e5:35:49:38:3f:
b7:c8 We can inspect our newly minted certificate and verify that it's been issued by `autocert` and includes the right common name:
Curve: P-256
X509v3 extensions: ```
X509v3 Key Usage: critical $ step certificate inspect --format json snarf.crt | jq '{issuer,subject}'
Digital Signature, Key Encipherment {
X509v3 Extended Key Usage: "issuer": {
TLS Web Server Authentication, TLS Web Client Authentication "common_name": [
X509v3 Subject Key Identifier: "Autocert Intermediate CA"
43:0E:0A:50:30:A5:5B:AF:22:AC:28:49:26:53:2A:B4:D4:20:E0:E0 ]
X509v3 Authority Key Identifier: },
keyid:61:45:1E:E4:95:4C:0A:6B:37:4C:43:41:FD:54:2E:8E:5E:A2:24:EF "subject": {
X509v3 Subject Alternative Name: "common_name": [
DNS:sleep.default.svc.cluster.local "snarf.local.dev"
]
Signature Algorithm: ECDSA-SHA256 }
30:44:02:20:0c:c5:ab:0d:22:17:a2:04:9f:ff:5f:b1:c0:a5: }
8b:94:88:e0:40:66:e1:19:e9:34:2f:67:74:12:4f:bb:51:8b: ```
02:20:01:7e:0d:44:ce:b2:92:41:d5:78:0d:02:5a:68:05:7c:
c2:a9:81:28:71:5c:95:6d:56:51:49:e0:37:b7:09:87 > 🤔 **Tip:** If you want someone (or something) to have a certificate with a particular name, but don't want to give them the ability to provision arbitrary certificates, you can generate a bootstrap token for them:
``` >
> ```bash
### Test your installation > $ step ca token snarf.local.dev \
> --ca-url https://127.0.0.1:4443 \
To test your installation you can install the `hello-mtls` demo app. > --root root.crt
> eyJhbG...
* Install app, which uses mTLS and responds "hello, `identity`" > ```
* Do a `kubectl run` of `step-cli` then get a certificate using `step` and `curl hello-mtls` from within the cluster >
* Port forward from localhost to get a certificate then `curl` with `--resolve` > They can use the token to obtain a certificate (once):
>
> ```bash
> $ step ca certificate snarf.local.dev snarf.crt snarf.key --token "eyJhbG..."
> ```
>
> Actually, this is exactly what the `autocert` mutating webhook is doing for your pods! Read [how it works](#how-it-works) for more info.
#### Connecting to `hello-mtls`
We're ready to securely connect to `hello-mtls`.
```
$ export HELLO_MTLS_IP=$(kubectl get svc hello-mtls-lb -ojsonpath={$.status.loadBalancer.ingress...?})
$ export HELLO_MTLS_IP="127.0.0.1"
$ curl --resolve hello-mtls.default.svc.cluster.local:443:$HELLO_MTLS_IP \
--cacert root.crt \
--cert snarf.crt \
--key snarf.key \
https://hello-mtls.default.svc.cluster.local
Hello, snarf.local.dev!
```
🎉
> 🤯 **Note:** HTTPS clients check that the name in the server's cerificate match the `authority` portion of the URL (e.g., `https://smallstep.com/` must present a certificate with the name `smallstep.com`). (See [RFC2818](https://tools.ietf.org/html/rfc2818#section-3).)
>
> Our `hello-mtls` service's certificate binds the name `hello-mtls.default.svc.cluster.local` so we *must* connect to it using that name. If we use a different authority we'll get an error:
>
> ```
> $ curl --cacert root.crt \
> --cert snarf.crt \
> --key snarf.key \
> https://127.0.0.1
> curl: (51) SSL: no alternative certificate subject name matches target host name '127.0.0.1'
> ```
>
> In a real production environment you'd address this by either:
>
> * using a properly registered domain name and configuring DNS either globally (e.g., using [ExternalDNS](https://github.com/kubernetes-incubator/external-dns/)), or
> * using internal names and configuring DNS locally in each environment (e.g., using an [ExternalName service](https://kubernetes.io/docs/concepts/services-networking/service/#externalname))
>
> In any case, `hello-mtls.default.svc.cluster.local` must resolve to the right IP.
>
> You could use `/etc/hosts`. Since we're testing with `curl` it's even easier to use the `--resolve` flag to override resolution for a single request.
## How it works
### Architecture
`Autocert` consists of a [webhook admission controllers](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#admission-webhooks) that injects one init container and one sidecar container to handle obtaining a certificate for the first time and renewing a certificate, respectively.
The `autocert` admission webhook will intercept this pod creation request and inject an [init container](bootstrapper/) and [sidecar](renewer/) to manage certificate issuance and renewal, respectively.
![Autocert architecture diagram](https://raw.githubusercontent.com/smallstep/certificates/autocert/autocert/autocert-arch.png)
### Enrollment & renewal
It integrates with [`step certificates`](https://github.com/smallstep/certificates) and uses the single-use token bootstrap protocol from that project to mutually authenticate a new pod with your certificate authority.
![Autocert bootstrap protocol diagram](https://raw.githubusercontent.com/smallstep/certificates/autocert/autocert/autocert-bootstrap.png)
### Further reading ### Further reading
@ -227,10 +484,38 @@ Yes, but it's designed for use by the kubernetes control plane rather than by yo
It's harder and less secure. It's harder and less secure.
#### Why not use kubernetes service accounts instead of bootstrap tokens?
#### Why does the mutating webhook have to create secrets / need cluster role bindings?
#### Why do I have to tell you the name to put in a certificate? Why can't you automatically bind service names?
#### What are `autocert` certificates good for? #### What are `autocert` certificates good for?
Autocert certificates let you secure your data plane (service-to-service) communication using mutual TLS (mTLS). Services and proxies can limit access to clients that also have a certificate issued by your certificate authority (CA). Servers can identify which client is connecting improving visibility and enabling granular access control. Autocert certificates let you secure your data plane (service-to-service) communication using mutual TLS (mTLS). Services and proxies can limit access to clients that also have a certificate issued by your certificate authority (CA). Servers can identify which client is connecting improving visibility and enabling granular access control.
Once certificates are issued you can use mTLS to secure communication in to, out of, and between kubernetes clusters. Services can use mTLS to only allow connections from clients that have their own certificate issued from your CA. Once certificates are issued you can use mTLS to secure communication in to, out of, and between kubernetes clusters. Services can use mTLS to only allow connections from clients that have their own certificate issued from your CA.
It's like your own Let's Encrypt, but you control who gets a certificate. It's like your own Let's Encrypt, but you control who gets a certificate.
#### How is this different than a service mesh?
Certificate management is a necessary building block for any service mesh that uses mutual TLS for authenticated encryption (e.g., istio, linkerd, consul connect). Typically, service mesh systems will provide their own certificate management solution. However, these systems
#### What about DaemonSets, ReplicaSets, StatefulSets, and all the other things that might need certificates?
...?
## Building
...
## Contributing
...
## License
Copyright 2019 Smallstep Labs
Licensed under [the Apache License, Version 2.0](https://github.com/smallstep/certificates/blob/master/LICENSE)

Loading…
Cancel
Save