|  | 
|  | 1 | +# How to: Setup externally signed TLS certificates | 
|  | 2 | + | 
|  | 3 | +The playbook is able to provision an internal CA and automatically sign the host certificates. | 
|  | 4 | + | 
|  | 5 | +However, it is more likely that an external CA will be used in production environments. | 
|  | 6 | + | 
|  | 7 | +This guide will run through specifics for deploying clusters using an external CA to sign the host certificates. | 
|  | 8 | + | 
|  | 9 | +At a high-level, the playbook generates and distributes the TLS keys and certificates in three steps: | 
|  | 10 | + | 
|  | 11 | +- Phase 1 (generation) | 
|  | 12 | +  * Create the host keys | 
|  | 13 | +  * Generate the keystores | 
|  | 14 | +  * Generate the CSRs | 
|  | 15 | +  * Copy the CSRs to the Ansible controller | 
|  | 16 | +- Phase 2 (signing) | 
|  | 17 | +  * Sign the certificates | 
|  | 18 | +- Phase 3 (installation) | 
|  | 19 | +  * Copy the signed certificates to the hosts | 
|  | 20 | +  * Copy the CA certificates to the hosts | 
|  | 21 | + | 
|  | 22 | +When `ca_server` is used, this all occurs automatically. | 
|  | 23 | + | 
|  | 24 | +However, when an external CA is used, a few manual steps are required to complete the deployment: | 
|  | 25 | + | 
|  | 26 | +Starting with the definition, assuming nothing has been deployed: | 
|  | 27 | + | 
|  | 28 | +## Ensure that `ca_server` is **not** present in the inventory | 
|  | 29 | + | 
|  | 30 | +The `ca_server` is the playbook's internal CA. | 
|  | 31 | + | 
|  | 32 | +As we wish to use an external CA, it should be omitted from the inventory file. | 
|  | 33 | + | 
|  | 34 | +## Set `tls_ca_certs` to point to the external CA certificates | 
|  | 35 | + | 
|  | 36 | +Here, we need to set `tls_ca_certs` in `defintion.yml` to point to the external CA certificates (on the Ansible controller): | 
|  | 37 | + | 
|  | 38 | +``` | 
|  | 39 | +tls_ca_certs: | 
|  | 40 | +  - alias: ipaca | 
|  | 41 | +    path: /root/ca.crt | 
|  | 42 | +``` | 
|  | 43 | + | 
|  | 44 | +In this example, our CA certificate exists on the Ansible controller at `/root/ca.crt`. | 
|  | 45 | + | 
|  | 46 | +**Note:** If you have an intermediate CA and a root CA, please include both certificates here. | 
|  | 47 | + | 
|  | 48 | +## Run the playbook deployment as usual | 
|  | 49 | + | 
|  | 50 | +If everything is configured correctly, it should run as usual until we reach `prepare_tls.yml`. | 
|  | 51 | + | 
|  | 52 | +Here, in `prepare_tls.yml`, it will fail with a message: | 
|  | 53 | + | 
|  | 54 | +> Signed cert for <hostname> could not be found. If manual signing is required, do this now and re-run the playbook with 'tls_signed_certs_dir' variable set. | 
|  | 55 | +
 | 
|  | 56 | +E.g. | 
|  | 57 | + | 
|  | 58 | +``` | 
|  | 59 | +TASK [security/tls_install_certs : fail] ************************************************************************************************************** | 
|  | 60 | +fatal: [host-1.example.com] FAILED! => {"changed": false, "msg": "\"Signed cert for host-1.example.com could not be found. If manual signing is required, do this now and re-run the playbook with 'tls_signed_certs_dir' variable set.\n"} | 
|  | 61 | +fatal: [host-2.example.com] FAILED! => {"changed": false, "msg": "\"Signed cert for host-1.example.com could not be found. If manual signing is required, do this now and re-run the playbook with 'tls_signed_certs_dir' variable set.\n"} | 
|  | 62 | +fatal: [host-3.example.com] FAILED! => {"changed": false, "msg": "\"Signed cert for host-1.example.com could not be found. If manual signing is required, do this now and re-run the playbook with 'tls_signed_certs_dir' variable set.\n"} | 
|  | 63 | +fatal: [host-4.example.com] FAILED! => {"changed": false, "msg": "\"Signed cert for host-1.example.com could not be found. If manual signing is required, do this now and re-run the playbook with 'tls_signed_certs_dir' variable set.\n"} | 
|  | 64 | +``` | 
|  | 65 | + | 
|  | 66 | +This is expected. | 
|  | 67 | + | 
|  | 68 | +At this point, the playbook will have generated the TLS keys and CSRs and copied the CSRs to the Ansible controller (stage 1). | 
|  | 69 | + | 
|  | 70 | +It is up to us now to sign the CSRs and copy the signed certificates back to the Ansible controller: | 
|  | 71 | + | 
|  | 72 | +## Sign the CSRs generated by the playbook | 
|  | 73 | + | 
|  | 74 | +You will find copies of the TLS CSRs in `{{ local_temp_dir }}/csrs` on the Ansible controller (default `/tmp/csrs`). | 
|  | 75 | + | 
|  | 76 | +``` | 
|  | 77 | +# ls /tmp/csrs | 
|  | 78 | +host-1.example.com.csr  host-3.example.com.csr | 
|  | 79 | +host-2.example.com.csr  host-4.example.com.csr | 
|  | 80 | +``` | 
|  | 81 | + | 
|  | 82 | +Sign the CSRs and copy the signed certificates to the Ansible controller using the same filename, replacing `.csr` with `.pem`. | 
|  | 83 | + | 
|  | 84 | +Place these signed certificates in `{{ local_temp_dir }}/certs` on the Ansible controller (default `/tmp/certs`). | 
|  | 85 | + | 
|  | 86 | +``` | 
|  | 87 | +# ls /tmp/certs | 
|  | 88 | +host-1.example.com.pem  host-3.example.com.pem | 
|  | 89 | +host-2.example.com.pem  host-4.example.com.pem | 
|  | 90 | +``` | 
|  | 91 | + | 
|  | 92 | +## Rerun the playbook | 
|  | 93 | + | 
|  | 94 | +The playbook can be restarted now that the signed certificates exist on the Ansible controller (stage 2). | 
|  | 95 | + | 
|  | 96 | +The playbook will distribute the new signed certificates and continue as usual. | 
|  | 97 | + | 
|  | 98 | +No other steps are required. | 
0 commit comments