Clark Boylan 2066403ed1 Only update acme.sh if necessary
We install acme.sh into /opt on our servers. Some of our servers rely on
/opt for data intensive activities and we can run out of disk space on
/opt/. When our daily Ansible runs fire and hit servers in this
situation we end up with corrupted acme.sh repos on those servers. Then
acme.sh roles fail.

Avoid this problem by only updating the git repo for acme.sh if it isn't
already up to date on the versions we expect. We can still fill the disk
but this won't affect acme.sh only server operations that rely on /opt
disk space.

This is an alternative to https://review.opendev.org/c/opendev/system-config/+/934247
which will try to force updates to occur regardless of git repo
corruption.

Change-Id: Ib0ad55de833a2c2d9e8cacec0493b8422e486789
2024-11-06 09:32:21 -08:00

119 lines
4.0 KiB
YAML

- name: Check status of acme.sh script
stat:
path: /opt/acme.sh/acme.sh
get_checksum: true
checksum_algorithm: sha256
register: acme_sh_stat
- name: Install acme.sh if not already up to date
when: not acme_sh_stat.stat.exists or acme_sh_stat.stat.checksum != "5c298a2bd5f90635aef8d013b02b25f34027ad0cb2cef2bdca68f3d13b931216"
block:
# We only want to update the clone and checkout if things are not already
# in place or at the expected versions. This avoids unnecessary daily
# git operations and makes us more resilient to full disks.
- name: Install acme.sh client
git:
repo: https://github.com/acmesh-official/acme.sh
dest: /opt/acme.sh
# Pinned due to https://github.com/acmesh-official/acme.sh/issues/4416
version: 3.0.5
register: clone_acmesh_result
until: clone_acmesh_result is not failed
retries: 3
delay: 2
# Temporary https://github.com/acmesh-official/acme.sh/issues/4659 fix
# until we can upgrade to 3.0.6 or later
- name: Patch for issue 4659
shell: |
git -C /opt/acme.sh cherry-pick 4c30250
git -C /opt/acme.sh cherry-pick 327e2fb
- name: Install letsencrypt group
group:
name: letsencrypt
state: present
gid: "{{ letsencrypt_gid | default(omit) }}"
- name: Install driver script
copy:
# Because this is a fily copy and not git operations with multiple states
# Ansible should successfully determine that the file doesn't need to be
# copied after the initial copy unless the file changes.
src: driver.sh
dest: /opt/acme.sh/driver.sh
mode: 0755
- name: Setup log directory
file:
path: /var/log/acme.sh
state: directory
mode: 0755
- name: Setup log rotation
include_role:
name: logrotate
vars:
logrotate_file_name: /var/log/acme.sh/acme.sh.log
- name: Setup top level cert directory
file:
path: /etc/letsencrypt-certs
state: directory
owner: root
group: letsencrypt
mode: u=rwx,g=rx,o=,g+s
- name: Create acme.sh config directory
file:
path: /root/.acme.sh
state: directory
owner: root
group: root
mode: u=rwx,g=rx,o=
# An implementation note on accounts: We could share an account key
# across all our hosts and this would be the logical place to deploy
# it. However, really the only thing you can do with an account key
# is revoke a certificate if you lose the private key. It makes more
# sense to have an account per host with key material that never
# leaves the host rather than keeping a global secret that, if leaked,
# could revoke all keys simultaneously.
- name: Check for account email
assert:
that: letsencrypt_account_email is defined
- name: Configure account email
lineinfile:
path: /root/.acme.sh/account.conf
regexp: '^ACCOUNT_EMAIL='
line: 'ACCOUNT_EMAIL={{ letsencrypt_account_email }}'
create: true
register: account_email
# If we updated the email and we have existing accounts, we should
# update the address.
# NOTE(ianw) 2020-03-04 : acme.sh dumps the 200 response json from the
# ACME api when creating an account into this file to keep track of
# the account-id. However, it doesn't actually then update it in
# response to --updateaccount although the details in the account
# *are* correctly updated. It doesn't make a difference to ongoing
# operation since all that cares about is the unchanging id, but can
# be confusing if you check this and don't see an updated email
# address. I have filed:
# https://github.com/acmesh-official/acme.sh/pull/2769
- name: Check for existing account setup
stat:
path: '{{ item }}'
loop:
- /root/.acme.sh/ca/acme-v02.api.letsencrypt.org/account.json
- /root/.acme.sh/ca/acme-staging-v02.api.letsencrypt.org/account.json
register: existing_accounts
- name: Run account update
shell: |
/opt/acme.sh/acme.sh --debug --updateaccount
when: account_email.changed and (existing_accounts.results | selectattr('stat.exists') | map(attribute='item') | list | length > 0)