Automate TLS/SSL Certificate Renewal Seamlessly with Ansible
Automate SSL/TLS Certificate Management with Ansible:
Our organization manually renews SSL/TLS certificates for multiple hosts on a monthly or yearly basis, which sometimes causes downtime and errors in updating certificates on host machines, posing a risk of installing incorrect TLS/SSL certificates. Recognizing these challenges, we have opted to automate the renewal process.
TLS/SSL Certificate Preparation:
In an Ansible playbook focused on certificate preparation, specific tasks are orchestrated to generate essential components for secure communication, including private keys and complete chain certificates.
---
- name: TLS/SSL Automation
hosts: localhost
tasks:
- name: Generate an acme_account_key
community.crypto.openssl_privatekey:
path: "./certificates/acme_account_key"
- name: Generate an OpenSSL private key if necessary
community.crypto.openssl_privatekey:
path: "./certificates/tls.key"
- name: Generate an OpenSSL Certificate Signing Request if necessary
community.crypto.openssl_csr:
path: "./certificates/tls.csr"
privatekey_path: "./certificates/tls.key"
country_name: "IN"
organization_name: "Organization name"
email_address: "admin@domain.com"
common_name: "domain.com"
- name: Create a challenge for the domain
community.crypto.acme_certificate:
account_key_src: "./certificates/acme_account_key"
csr: "./certificates/tls.csr"
dest: "./certificates/tls.crt"
challenge: "dns-01"
acme_version: "2"
acme_directory: "https://acme-v02.api.letsencrypt.org/directory"
terms_agreed: true
force: true
register: dns_challenge
- name: Get TXT record for the challenge
ansible.builtin.set_fact:
record: "{{ dns_challenge.challenge_data[domain]['dns-01'].record }}"
when: dns_challenge.challenge_data is defined
- name: Get value of the TXT record
ansible.builtin.set_fact:
record_value: "{{ dns_challenge.challenge_data[domain]['dns-01'].resource_value }}"
when: dns_challenge.challenge_data is defined
- name: Update the AWS route53 DNS TXT record
amazon.aws.route53:
command: present
zone: "domain.com"
record: "{{ record }}"
type: TXT
ttl: 300
value: '"{{ record_value }}"'
overwrite: true
- name: Pause for five minutes
ansible.builtin.pause:
minutes: 5
- name: Validate challenge
community.crypto.acme_certificate:
account_key_src: "./certificates/acme_account_key"
account_email: "admin@domain.com"
csr: "./certificates/tls.csr"
dest: "./certificates/tls.crt"
chain_dest: "./certificates/intermediate.crt"
fullchain_dest: "./certificates/fullchain.crt"
challenge: "dns-01"
acme_directory: "https://acme-v02.api.letsencrypt.org/directory"
remaining_days: 15
acme_version: 2
force: true
when: dns_challenge is changed
- Generate ACME Account Key: The
community.crypto.openssl_privatekeymodule is used to create a private key for the ACME account. This key is crucial for the ACME protocol to issue and manage SSL certificates. - Generate Private Key: The
community.crypto.openssl_privatekeymodule creates an OpenSSL private key. This key is used later to generate the CSR and certificate. - Generate CSR: The
community.crypto.openssl_csrmodule creates a Certificate Signing Request (CSR) using the private key. The CSR includes information such as country name, organization name, email address, and the common name (domain). This CSR is required by the CA (Let's Encrypt) to issue the certificate. - Create ACME Challenge: The
community.crypto.acme_certificatemodule initiates a DNS-01 challenge with Let's Encrypt to prove domain ownership. It registers the challenge data, which will be used to update the DNS records. - Retrieve DNS TXT Record Name and Value: Using
ansible.builtin.set_fact, the playbook retrieves both the DNS TXT record name and its corresponding value from the dns_challenge data. - Update DNS Record: The
amazon.aws.route53module updates the AWS Route53 DNS TXT record with the challenge information. This step is critical for completing the DNS-01 challenge by proving ownership of the domain to Let's Encrypt. - Validate Challenge: The
community.crypto.acme_certificatemodule validates the DNS challenge with Let's Encrypt. Once the challenge is validated, it retrieves the SSL certificate, saving it along with the intermediate and full chain certificates in the specified directory.
TLS/SSL Certificate Updation:
To automate the update process for SSL/TLS certificates on multiple remote hosts, the playbook copies the fullchain.crt file from the local directory ./certificates/ to the destination /etc/domain/ssl/fullchain.crt on each remote host. Similarly, it copies the tls.key file. During this process, the file permissions (mode) are set to 0644, ensuring that the certificate file is readable by hosts.
After the SSL/TLS certificate update process, you can implement a post-task that checks the existence or validity of the updated certificates on each host. This ensures that the update was successful across all targeted machines.
Conclusion:
By automating the SSL/TLS certificate updates with this Ansible playbook, you reduce the risk of downtime and errors, ensuring that your systems remain secure and up-to-date. Whether integrated into your CI/CD pipeline, executed manually, or scheduled via cron job, this approach streamlines the certificate management process, providing a reliable solution for maintaining your infrastructure.