1 changed files with 223 additions and 0 deletions
@ -0,0 +1,223 @@ |
|||
# Using public certificates on your OpenShift cluster |
|||
|
|||
## Context |
|||
|
|||
By default, the OpenShift installer generates a self-signed Certification |
|||
Authority to issue all the certificates of the cluster. This is convenient |
|||
but it has the drawback to generate warnings in the browser. |
|||
|
|||
This guide explains how to use the [Let's Encrypt](https://letsencrypt.org/) |
|||
service to get a free public certificate for your OpenShift cluster. |
|||
|
|||
You can use a public certificate for: |
|||
|
|||
- the OpenShift router that serves your default subdomain (`openshift_master_default_subdomain`) |
|||
- the OpenShift master |
|||
|
|||
## Pre-requisites |
|||
|
|||
To complete this workshop you will need to have: |
|||
|
|||
- an OpenShift cluster |
|||
- your own DNS domain hosted by a public DNS hosting service (Gandi, SimpleDNS, etc.) |
|||
- the DNS domain must be under your control |
|||
- If you plan to issue a public certificate for your OpenShift master, |
|||
it must have both a public and a private hostname. |
|||
|
|||
**Note:** the OpenShift cluster does **NOT** have to be reachable on the |
|||
Internet but your DNS domain has to be registered, hosted on a public DNS |
|||
hosting service and must be under your control. |
|||
|
|||
`nip.io` and `xip.io` are **NOT** compatible. |
|||
|
|||
## Install acme.sh |
|||
|
|||
To get a public certificate from Let's Encrypt, we will use |
|||
[acme.sh](https://github.com/Neilpang/acme.sh). |
|||
|
|||
Install `acme.sh` on the Ansible control node, that is to say the server |
|||
**that runs your OpenShift playbooks**: |
|||
|
|||
```sh |
|||
curl https://get.acme.sh | sh |
|||
``` |
|||
|
|||
## Get a public certificate for your OpenShift Router |
|||
|
|||
From the Ansible control node, run the `acme.sh` command to get a certificate |
|||
for your default subdomain. In this example I used `*.app.openshift.test` but |
|||
you will have to replace it with your domain. |
|||
|
|||
```sh |
|||
acme.sh --issue --dns -d 'app.openshift.test' -d '*.app.openshift.test' --yes-I-know-dns-manual-mode-enough-go-ahead-please |
|||
``` |
|||
|
|||
You should get something like this: |
|||
|
|||
```raw |
|||
[Thu Aug 2 11:43:00 CEST 2018] Creating domain key |
|||
[Thu Aug 2 11:43:00 CEST 2018] The domain key is here: /home/nicolas/.acme.sh/app.openshift.test/app.openshift.test.key |
|||
[Thu Aug 2 11:43:00 CEST 2018] Multi domain='DNS:app.openshift.test,DNS:*.app.openshift.test' |
|||
[Thu Aug 2 11:43:00 CEST 2018] Getting domain auth token for each domain |
|||
[Thu Aug 2 11:43:02 CEST 2018] Getting webroot for domain='app.openshift.test' |
|||
[Thu Aug 2 11:43:02 CEST 2018] Getting webroot for domain='*.app.openshift.test' |
|||
[Thu Aug 2 11:43:02 CEST 2018] Add the following TXT record: |
|||
[Thu Aug 2 11:43:02 CEST 2018] Domain: '_acme-challenge.app.openshift.test' |
|||
[Thu Aug 2 11:43:02 CEST 2018] TXT value: 'y6FiU9ZCBKi8koQGGQDXWyKJYOXTTsqgU6LTd_CBAeE' |
|||
[Thu Aug 2 11:43:02 CEST 2018] Please be aware that you prepend _acme-challenge. before your domain |
|||
[Thu Aug 2 11:43:02 CEST 2018] so the resulting subdomain will be: _acme-challenge.app.openshift.test |
|||
[Thu Aug 2 11:43:02 CEST 2018] Add the following TXT record: |
|||
[Thu Aug 2 11:43:02 CEST 2018] Domain: '_acme-challenge.app.openshift.test' |
|||
[Thu Aug 2 11:43:02 CEST 2018] TXT value: 'Bo4VxqsPvOHWymqvmUR43wVoucQroe3QV041ZWjah-c' |
|||
[Thu Aug 2 11:43:02 CEST 2018] Please be aware that you prepend _acme-challenge. before your domain |
|||
[Thu Aug 2 11:43:02 CEST 2018] so the resulting subdomain will be: _acme-challenge.app.openshift.test |
|||
[Thu Aug 2 11:43:02 CEST 2018] Please add the TXT records to the domains, and re-run with --renew. |
|||
``` |
|||
|
|||
Go to your DNS hosting service and add the required records. |
|||
|
|||
In the previous example, I would have to add: |
|||
|
|||
```bind |
|||
_acme-challenge.app.openshift.test. 300 IN TXT "y6FiU9ZCBKi8koQGGQDXWyKJYOXTTsqgU6LTd_CBAeE" |
|||
_acme-challenge.app.openshift.test. 300 IN TXT "Bo4VxqsPvOHWymqvmUR43wVoucQroe3QV041ZWjah-c" |
|||
``` |
|||
|
|||
Please pay attention to add a dot after the domain name if you enter the FQDN |
|||
and reciprocally remove the final dot if you entered just the record name |
|||
(`_acme-challenge.app`). |
|||
|
|||
Wait for the new DNS records to propagate (20-30 minutes) and check that the |
|||
new records are available: |
|||
|
|||
```sh |
|||
dig _acme-challenge.app.openshift.test IN TXT |
|||
``` |
|||
|
|||
Once the records have been propagated, you can fetch the public certificates: |
|||
|
|||
```sh |
|||
acme.sh --renew --dns -d 'app.openshift.test' -d '*.app.openshift.test' --yes-I-know-dns-manual-mode-enough-go-ahead-please |
|||
``` |
|||
|
|||
And everything went fine, you should get something like this: |
|||
|
|||
```raw |
|||
[Thu Aug 2 13:53:15 CEST 2018] Renew: 'app.openshift.test' |
|||
[Thu Aug 2 13:53:15 CEST 2018] Multi domain='DNS:app.openshift.test,DNS:*.app.openshift.test' |
|||
[Thu Aug 2 13:53:15 CEST 2018] Getting domain auth token for each domain |
|||
[Thu Aug 2 13:53:15 CEST 2018] Verifying:app.openshift.test |
|||
[Thu Aug 2 13:53:19 CEST 2018] Success |
|||
[Thu Aug 2 13:53:19 CEST 2018] Verifying:*.app.openshift.test |
|||
[Thu Aug 2 13:53:21 CEST 2018] Success |
|||
[Thu Aug 2 13:53:24 CEST 2018] Verify finished, start to sign. |
|||
[Thu Aug 2 13:53:26 CEST 2018] Cert success. |
|||
[Thu Aug 2 13:53:26 CEST 2018] Your cert is in /home/nicolas/.acme.sh/app.openshift.test/app.openshift.test.cer |
|||
[Thu Aug 2 13:53:26 CEST 2018] Your cert key is in /home/nicolas/.acme.sh/app.openshift.test/app.openshift.test.key |
|||
[Thu Aug 2 13:53:26 CEST 2018] The intermediate CA cert is in /home/nicolas/.acme.sh/app.openshift.test/ca.cer |
|||
[Thu Aug 2 13:53:26 CEST 2018] And the full chain certs is there: /home/nicolas/.acme.sh/app.openshift.test/fullchain.cer |
|||
``` |
|||
|
|||
## Get a public certificate for your OpenShift Master |
|||
|
|||
Using a public certificate for the OpenShift master is very similar to the |
|||
procedure for the OpenShift router but there is an additional requirement: |
|||
the master **MUST** have a public and an internal hostname. |
|||
|
|||
This requirement exists because we can replace the certificate for the public |
|||
hostname with a public certificate but we cannot do the same with the internal |
|||
hostname. And if there is only one hostname that is used for both public and |
|||
internal, the public certificate will be served from within the cluster and |
|||
will mostly break your cluster. **YOU HAVE BEEN WARNED !** |
|||
|
|||
First, confirm you have different hostnames for public and internal by checking |
|||
your master configuration: |
|||
|
|||
```sh |
|||
$ egrep 'master(Public)?URL' /etc/origin/master/master-config.yaml |
|||
masterPublicURL: https://master.openshift.test:8443 |
|||
masterURL: https://openshift.openshift.internal:8443 |
|||
``` |
|||
|
|||
As you can see, in this example this master has two hostnames: |
|||
|
|||
- `master.openshift.test` is the public hostname |
|||
- `master.openshift.internal` is the internal hostname |
|||
|
|||
From the Ansible control node, run the `acme.sh` command to get a certificate |
|||
for your master public hostname. In this example I used `master.openshift.test` but |
|||
you will have to replace it with your domain. |
|||
|
|||
```sh |
|||
acme.sh --issue --dns -d 'master.openshift.test' --yes-I-know-dns-manual-mode-enough-go-ahead-please |
|||
``` |
|||
|
|||
As in the previous section, go to your DNS hosting service, add the required |
|||
records, wait for the DNS propagation, and re-run the `acme.sh` command: |
|||
|
|||
```sh |
|||
acme.sh --renew --dns -d 'master.openshift.test' --yes-I-know-dns-manual-mode-enough-go-ahead-please |
|||
``` |
|||
|
|||
## Install the certificates |
|||
|
|||
Until now, we fetched the public certificates for our OpenShift router and |
|||
OpenShift master but they have not been installed yet. |
|||
|
|||
Add to your Ansible inventory file: |
|||
|
|||
```ini |
|||
[OSEv3:vars] |
|||
openshift_master_overwrite_named_certificates=true |
|||
openshift_master_named_certificates=[{ "certfile": "{{ lookup('env','HOME') }}/.acme.sh/master.openshift.test/master.openshift.test.cer", "keyfile": "{{ lookup('env','HOME') }}/.acme.sh/master.openshift.test/master.openshift.test.key", "cafile": "{{ lookup('env','HOME') }}/.acme.sh/master.openshift.test/ca.cer", "names": [ "master.openshift.test" ] }] |
|||
openshift_hosted_router_certificate={ "certfile": "{{ lookup('env','HOME') }}/.acme.sh/app.openshift.test/app.openshift.test.cer", "keyfile": "{{ lookup('env','HOME') }}/.acme.sh/app.openshift.test/app.openshift.test.key", "cafile": "{{ lookup('env','HOME') }}/.acme.sh/app.openshift.test/ca.cer" } |
|||
``` |
|||
|
|||
And run the `redeploy-certificates.yml` playbook: |
|||
|
|||
```sh |
|||
ansible-playbook /usr/share/ansible/openshift-ansible/playbooks/redeploy-certificates.yml |
|||
``` |
|||
|
|||
You can confirm the certificates have been correctly deployed: |
|||
|
|||
```raw |
|||
$ openssl s_client -host test.app.openshift.test -port 443 -servername test.app.openshift.test < /dev/null |head -n 9 |
|||
depth=1 C = US, O = Let's Encrypt, CN = Let's Encrypt Authority X3 |
|||
verify error:num=20:unable to get local issuer certificate |
|||
verify return:0 |
|||
poll errorCONNECTED(00000005) |
|||
--- |
|||
Certificate chain |
|||
0 s:/CN=app.openshift.test |
|||
i:/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3 |
|||
1 s:/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3 |
|||
i:/O=Digital Signature Trust Co./CN=DST Root CA X3 |
|||
--- |
|||
Server certificate |
|||
``` |
|||
|
|||
```raw |
|||
$ openssl s_client -host master.openshift.test -port 8443 -servername master.openshift.test < /dev/null |head -n 9 |
|||
depth=1 C = US, O = Let's Encrypt, CN = Let's Encrypt Authority X3 |
|||
verify error:num=20:unable to get local issuer certificate |
|||
verify return:0 |
|||
poll errorCONNECTED(00000005) |
|||
--- |
|||
Certificate chain |
|||
0 s:/CN=master.openshift.test |
|||
i:/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3 |
|||
1 s:/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3 |
|||
i:/O=Digital Signature Trust Co./CN=DST Root CA X3 |
|||
--- |
|||
Server certificate |
|||
``` |
|||
|
|||
## Further improvements |
|||
|
|||
The certificates issued by Let's Encrypt are valid for only 90 days. So you |
|||
will have to get a new certificate and install it with the |
|||
`redeploy-certificates.yml` playbook every 90 days or less. |
|||
|
|||
If your DNS hosting service is listed in the [supported Automatic DNS API Integration page](https://github.com/Neilpang/acme.sh#7-automatic-dns-api-integration), |
|||
you can leverage it to automate the process. |
|||
Loading…
Reference in new issue