Merge pull request #8 from smallstep/docker-nginx

NGINX demo
This commit is contained in:
Mariano Cano 2018-11-12 12:24:33 -08:00 committed by GitHub
commit 40d7959c6d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 363 additions and 0 deletions

View file

@ -316,3 +316,129 @@ sure the certificate changes after 74-80 seconds.
```sh
certificates $ step certificate inspect --insecure https://localhost:8443
```
## NGINX with Step CA certificates
The example under the `docker` directory shows how to combine the Smallstep CA
with NGINX to server pages or proxy services using certificates created by the
step-ca.
This example creates 3 different docker images:
* nginx-test: docker image with NGINX and a script using inotify-tools to watch
for changes in the certificate to reload NGINX.
* step-ca-test: docker image with the Smallstep CA
* step-renewer-test: docker images with the step cli tool, it creates the
certificate and has a cron that renews the certificate. Right now the cron
runs every minute for testing purposes.
To run this test you need to have docker daemon running. With docker running
swith to the `examples/docker directory` and just run `make`
```
certificates $ cd examples/docker/
docker $ make
GOOS=linux go build -o ca/step-ca github.com/smallstep/certificates/cmd/step-ca
GOOS=linux go build -o renewer/step github.com/smallstep/cli/cmd/step
docker build -t nginx-test:latest nginx
...
docker-compose up
WARNING: The Docker Engine you're using is running in swarm mode.
Compose does not use swarm mode to deploy services to multiple nodes in a swarm. All containers will be scheduled on the current node.
To deploy your application across the swarm, use `docker stack deploy`.
Creating network "docker_default" with the default driver
Creating docker_ca_1 ... done
Creating docker_renewer_1 ... done
Creating docker_nginx_1 ... done
Attaching to docker_ca_1, docker_renewer_1, docker_nginx_1
ca_1 | 2018/11/12 19:39:16 Serving HTTPS on :443 ...
nginx_1 | Setting up watches.
nginx_1 | Watches established.
...
```
Make will build the binaries for step and step-ca, create the images, create the
containers and start them using docker composer.
NGINX will be listening on your local machine on https://localhost:4443, but to
make sure the cert is right we need to add the following entry to `/etc/hosts`:
```
127.0.0.1 nginx
```
Now we can use curl to check:
```sh
docker $ curl --cacert ca/pki/secrets/root_ca.crt https://nginx:4443/
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
```
Now you can use `make inspect` to inspect the certificate to see how the
certificate gets updated every minute:
```sh
docker $ make inspect | head
step certificate inspect https://localhost:4443 --insecure
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 220353801925419530569669982276277771655 (0xa5c6993a7e110e6f009c83c79edc1d87)
Signature Algorithm: ECDSA-SHA256
Issuer: CN=Smallstep Intermediate CA
Validity
Not Before: Nov 10 02:13:00 2018 UTC
Not After : Nov 11 02:13:00 2018 UTC
docker $ make inspect | head
step certificate inspect https://localhost:4443 --insecure
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 207756171799719353821615361892302471392 (0x9c4c621c04d3e8be401ff0d14c5440e0)
Signature Algorithm: ECDSA-SHA256
Issuer: CN=Smallstep Intermediate CA
Validity
Not Before: Nov 10 02:14:00 2018 UTC
Not After : Nov 11 02:14:00 2018 UTC
```
Finally, to remove the containers and volumes you can use `make down`:
```sh
docker $ make down
docker-compose down
Stopping docker_nginx_1 ... done
Stopping docker_renewer_1 ... done
Stopping docker_ca_1 ... done
Removing docker_nginx_1 ... done
Removing docker_renewer_1 ... done
Removing docker_ca_1 ... done
Removing network docker_default
```

23
examples/docker/Makefile Normal file
View file

@ -0,0 +1,23 @@
all: binaries build up
binaries:
GOOS=linux go build -o ca/step-ca github.com/smallstep/certificates/cmd/step-ca
GOOS=linux go build -o renewer/step github.com/smallstep/cli/cmd/step
build: build-nginx build-ca build-renewer
build-nginx:
docker build -t nginx-test:latest nginx
build-ca:
docker build -t step-ca-test:latest ca
build-renewer:
docker build -t step-renewer-test:latest renewer
up:
docker-compose up
down:
docker-compose down
inspect:
step certificate inspect https://localhost:4443 --insecure

View file

@ -0,0 +1,7 @@
FROM alpine
ADD step-ca /usr/local/bin/step-ca
COPY pki /run
# Smallstep CA
CMD ["step-ca", "/run/config/ca.json"]

View file

@ -0,0 +1,58 @@
{
"root": "/run/secrets/root_ca.crt",
"crt": "/run/secrets/intermediate_ca.crt",
"key": "/run/secrets/intermediate_ca_key",
"password": "password",
"address": ":443",
"dnsNames": [
"ca"
],
"logger": {
"format": "text"
},
"authority": {
"provisioners": [
{
"name": "mariano@smallstep.com",
"type": "jwk",
"key": {
"use": "sig",
"kty": "EC",
"kid": "DmAtZt2EhmZr_iTJJ387fr4Md2NbzMXGdXQNW1UWPXk",
"crv": "P-256",
"alg": "ES256",
"x": "jXoO1j4CXxoTC32pNzkVC8l6k2LfP0k5ndhJZmcdVbk",
"y": "c3JDL4GTFxJWHa8EaHdMh4QgwMh64P2_AGWrD0ADXcI"
},
"encryptedKey": "eyJhbGciOiJQQkVTMi1IUzI1NitBMTI4S1ciLCJjdHkiOiJqd2sranNvbiIsImVuYyI6IkEyNTZHQ00iLCJwMmMiOjEwMDAwMCwicDJzIjoiOTFVWjdzRGw3RlNXcldfX1I1NUh3USJ9.FcWtrBDNgrkA33G9Ll9sXh1cPF-3jVXeYe1FLmSDc_Q2PmfLOPvJOA.0ZoN32ayaRWnufJb.WrkffMmDLWiq1-2kn-w7-kVBGW12gjNCBHNHB1hyEdED0rWH1YWpKd8FjoOACdJyLhSn4kAS3Lw5AH7fvO27A48zzvoxZU5EgSm5HG9IjkIH-LBJ-v79ShkpmPylchgjkFhxa5epD11OIK4rFmI7s-0BCjmJokLR_DZBhDMw2khGnsr_MEOfAz9UnqXaQ4MIy8eT52xUpx68gpWFlz2YP3EqiYyNEv0PpjMtyP5lO2i8-p8BqvuJdus9H3fO5Dg-1KVto1wuqh4BQ2JKTauv60QAnM_4sdxRHku3F_nV64SCrZfDvnN2ve21raFROtyXaqHZhN6lyoPxDncy8v4.biaOblEe0N-gMpJyFZ-3-A"
},
{
"name": "mike@smallstep.com",
"type": "jwk",
"key": {
"use": "sig",
"kty": "EC",
"kid": "YYNxZ0rq0WsT2MlqLCWvgme3jszkmt99KjoGEJJwAKs",
"crv": "P-256",
"alg": "ES256",
"x": "LsI8nHBflc-mrCbRqhl8d3hSl5sYuSM1AbXBmRfznyg",
"y": "F99LoOvi7z-ZkumsgoHIhodP8q9brXe4bhF3szK-c_w"
},
"encryptedKey": "eyJhbGciOiJQQkVTMi1IUzI1NitBMTI4S1ciLCJjdHkiOiJqd2sranNvbiIsImVuYyI6IkEyNTZHQ00iLCJwMmMiOjEwMDAwMCwicDJzIjoiVERQS2dzcEItTUR4ZDJxTGo0VlpwdyJ9.2_j0cZgTm2eFkZ-hrtr1hBIvLxN0w3TZhbX0Jrrq7vBMaywhgFcGTA.mCasZCbZJ-JT7vjA.bW052WDKSf_ueEXq1dyxLq0n3qXWRO-LXr7OzBLdUKWKSBGQrzqS5KJWqdUCPoMIHTqpwYvm-iD6uFlcxKBYxnsAG_hoq_V3icvvwNQQSd_q7Thxr2_KtPIDJWNuX1t5qXp11hkgb-8d5HO93CmN7xNDG89pzSUepT6RYXOZ483mP5fre9qzkfnrjx3oPROCnf3SnIVUvqk7fwfXuniNsg3NrNqncHYUQNReiq3e9I1R60w0ZQTvIReY7-zfiq7iPgVqmu5I7XGgFK4iBv0L7UOEora65b4hRWeLxg5t7OCfUqrS9yxAk8FdjFb9sEfjopWViPRepB0dYPH8dVI.fb6-7XWqp0j6CR9Li0NI-Q",
"claims": {
"minTLSCertDuration": "60s",
"defaultTLSCertDuration": "120s"
}
}
]
},
"tls": {
"cipherSuites": [
"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305",
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"
],
"minVersion": 1.2,
"maxVersion": 1.2,
"renegotiation": false
}
}

View file

@ -0,0 +1,12 @@
-----BEGIN CERTIFICATE-----
MIIBxjCCAWugAwIBAgIQAYoOWhdChUmmKzlc0DWcWDAKBggqhkjOPQQDAjAcMRow
GAYDVQQDExFTbWFsbHN0ZXAgUm9vdCBDQTAeFw0xODExMDIyMzU0MTNaFw0yODEw
MzAyMzU0MTNaMCQxIjAgBgNVBAMTGVNtYWxsc3RlcCBJbnRlcm1lZGlhdGUgQ0Ew
WTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASxvIWme8/yDAxkR63KgSYkpN7mHKBH
k5c8S+uzba4xWbaxZtEZ9NNhEIAgYFZ9/3ThrzLOsuGwRCvPTaD5iycQo4GGMIGD
MA4GA1UdDwEB/wQEAwIBpjAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIw
EgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQU8dKIy5ZLH2h3ihWgqjcpoo5e
q3YwHwYDVR0jBBgwFoAU0IpOvAyBnn9UhDqOQzXnfEU3aYMwCgYIKoZIzj0EAwID
SQAwRgIhANXlcktuaEvORhgRvzQ6vVNgvpqCEXW3CcCHjUl1xSdaAiEAmakkpfFq
VsT5PqPnTRgOWlFESRhQ9btl6nQ+2Lt/S5A=
-----END CERTIFICATE-----

View file

@ -0,0 +1,8 @@
-----BEGIN EC PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-256-CBC,4c7758e66df1884f6560839de64d4dd3
S8Ha8uA+bA3IGPurYODwd9VaJZ6FHI2tlznHXCOxT1MlGqyEAc4aWS11QBUz0Ucp
excwlqM8kfh5BcN5a+vvInHnv74ZiNPdpt/apzz2LIx52pApzASiKVXRsAUmR4Pv
3MsO1/cVHkilpee1uC+axL32d5YmyP0URpSNJK9BhZo=
-----END EC PRIVATE KEY-----

View file

@ -0,0 +1,10 @@
-----BEGIN CERTIFICATE-----
MIIBfDCCASGgAwIBAgIQY0CXerxuM+EhTbpVxxLRKjAKBggqhkjOPQQDAjAcMRow
GAYDVQQDExFTbWFsbHN0ZXAgUm9vdCBDQTAeFw0xODExMDIyMzU0MTNaFw0yODEw
MzAyMzU0MTNaMBwxGjAYBgNVBAMTEVNtYWxsc3RlcCBSb290IENBMFkwEwYHKoZI
zj0CAQYIKoZIzj0DAQcDQgAEEGa7ZeL4WVIfPFDS7glJkIVsITVQgjfyz+AhcYaS
rkJZlWOGZ60br9uE/wEfUcX1zavrX1Wz+bSJzTvT0AVBNqNFMEMwDgYDVR0PAQH/
BAQDAgGmMBIGA1UdEwEB/wQIMAYBAf8CAQEwHQYDVR0OBBYEFNCKTrwMgZ5/VIQ6
jkM153xFN2mDMAoGCCqGSM49BAMCA0kAMEYCIQCRA4EdlTTMhs2Zd1cT75ZgxeGa
mjVPl1vqBxLkHqEO+QIhAPKVm7E452ZBe2o5rQRxGwa94MI+CyuEIH9md3nTgWWX
-----END CERTIFICATE-----

View file

@ -0,0 +1,8 @@
-----BEGIN EC PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-256-CBC,98fdc560ba714aebb9fd4b714395d8ce
2bFn8yRb8lMvDR6oh22PocfhXdaoVNt4QwHCJNy0K0fG8CMokwDfEec//LseP6rA
7/EV11+ZgoN9xyTNe1kB6zFv7/kzCpRm23sqtyio+8xXWnLZNYKBRYYEeJWBUqqd
GAfazg4ZFzoIH5TEPWCEAp7M9CVvtiw1SeA/zjewp2k=
-----END EC PRIVATE KEY-----

View file

@ -0,0 +1,42 @@
version: '3.3'
services:
ca:
image: step-ca-test:latest
ports:
- "8443:443"
restart: always
renewer:
depends_on:
- ca
image: step-renewer-test:latest
volumes:
- certificates:/var/local/step
secrets:
- password
environment:
STEPPATH: /home/step
STEP_CA_URL: https://ca
STEP_FINGERPRINT: 84a033e84196f73bd593fad7a63e509e57fd982f02084359c4e8c5c864efc27d
STEP_ROOT: /var/local/step/root_ca.crt
STEP_KID: DmAtZt2EhmZr_iTJJ387fr4Md2NbzMXGdXQNW1UWPXk
STEP_PASSWORD_FILE: /run/secrets/password
COMMON_NAME: nginx
nginx:
depends_on:
- renewer
image: nginx-test:latest
ports:
- "4443:443"
volumes:
- certificates:/var/local/step:ro
restart: always
volumes:
certificates:
secrets:
password:
file: ./password.txt

View file

@ -0,0 +1,11 @@
FROM nginx:alpine
RUN apk add inotify-tools
RUN mkdir -p /var/local/step
COPY site.conf /etc/nginx/conf.d/
COPY certwatch.sh /
COPY entrypoint.sh /
# Certificate watcher and nginx
ENTRYPOINT ["/entrypoint.sh"]
CMD ["nginx", "-g", "daemon off;"]

View file

@ -0,0 +1,6 @@
#!/bin/sh
while true; do
inotifywait -e modify /var/local/step/site.crt
nginx -s reload
done

View file

@ -0,0 +1,10 @@
#!/bin/sh
# Wait for renewer
sleep 10
# watch for the update of the cert and reload nginx
/certwatch.sh &
# Run docker CMD
exec "$@"

View file

@ -0,0 +1,11 @@
server {
listen 443 ssl;
server_name localhost;
ssl_certificate /var/local/step/site.crt;
ssl_certificate_key /var/local/step/site.key;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
}

View file

@ -0,0 +1 @@
password

View file

@ -0,0 +1,10 @@
FROM alpine:latest
RUN mkdir -p /var/local/step
ADD step /usr/local/bin/step
ADD crontab /var/spool/cron/crontabs/root
RUN chmod 0644 /var/spool/cron/crontabs/root
COPY entrypoint.sh /
ENTRYPOINT ["/entrypoint.sh"]
CMD ["/usr/sbin/crond", "-l", "2", "-f"]

View file

@ -0,0 +1,2 @@
# min hour day month weekday command
* * * * * rm -f /var/local/step/site-new.crt && step ca renew --out /var/local/step/site-new.crt /var/local/step/site.crt /var/local/step/site.key && mv /var/local/step/site-new.crt /var/local/step/site.crt

View file

@ -0,0 +1,18 @@
#!/bin/sh
# Wait for CA
sleep 5
if [ ! -f /var/local/step/root_ca.crt ]; then
# Donwload the root certificate
step ca root /var/local/step/root_ca.crt
fi
if [ ! -f /var/local/step/site.crt ]; then
# Get token
STEP_TOKEN=$(step ca token $COMMON_NAME)
# Donwload the root certificate
step ca certificate --token $STEP_TOKEN $COMMON_NAME /var/local/step/site.crt /var/local/step/site.key
fi
exec "$@"