mirror of
https://github.com/nickjj/ansible-acme-sh.git
synced 2025-02-27 00:21:38 +01:00
Initial commit
This commit is contained in:
commit
0fb24730a1
8
.gitignore
vendored
Normal file
8
.gitignore
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
.DS_Store
|
||||
*/**.DS_Store
|
||||
._*
|
||||
.*.sw*
|
||||
*~
|
||||
.idea/
|
||||
.vscode/
|
||||
*.retry
|
17
.travis.yml
Normal file
17
.travis.yml
Normal file
@ -0,0 +1,17 @@
|
||||
---
|
||||
|
||||
services: "docker"
|
||||
|
||||
env:
|
||||
- distro: "ubuntu1604"
|
||||
- distro: "ubuntu1804"
|
||||
- distro: "debian8"
|
||||
- distro: "debian9"
|
||||
|
||||
script:
|
||||
# Download test shim.
|
||||
- wget -O ${PWD}/tests/test.sh https://gist.githubusercontent.com/nickjj/d12353b5b601e33cd62fda111359957a/raw
|
||||
- chmod +x ${PWD}/tests/test.sh
|
||||
|
||||
# Run tests.
|
||||
- ${PWD}/tests/test.sh
|
7
CHANGES.md
Executable file
7
CHANGES.md
Executable file
@ -0,0 +1,7 @@
|
||||
# Changelog
|
||||
|
||||
### v1.0.0
|
||||
|
||||
*Released: September 29th 2018*
|
||||
|
||||
- Initial release
|
22
LICENSE
Normal file
22
LICENSE
Normal file
@ -0,0 +1,22 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2018 Nick Janetakis nick.janetakis@gmail.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
'Software'), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
397
README.md
Normal file
397
README.md
Normal file
@ -0,0 +1,397 @@
|
||||
## What is ansible-acme-sh? [](http://travis-ci.org/nickjj/ansible-acme-sh)
|
||||
|
||||
It is an [Ansible](http://www.ansible.com/home) role to:
|
||||
|
||||
- Install acme.sh to issue, renew or remove Let's Encrypt based SSL certificates
|
||||
- Issue certificates for single, multiple or wildcard domains
|
||||
- Configure multiple domains through 1 certificate or separate certificates
|
||||
- Issue DNS based challenges using acme.sh's automated DNS API feature
|
||||
- Run custom acme.sh commands if the presets are not enough for you
|
||||
|
||||
## Why would you want to use this role?
|
||||
|
||||
This role uses [acme.sh](https://github.com/Neilpang/acme.sh) which is a self
|
||||
contained Bash script to handle all of the complexities of issuing and
|
||||
automatically renewing your SSL certificates.
|
||||
|
||||
This role's goals are to be highly configurable but have enough sane defaults
|
||||
so that you can get going by supplying nothing more than a list of domain names,
|
||||
setting your DNS provider and supplying your DNS provider's API key.
|
||||
|
||||
It's also idempotent for every task because that's the only way I roll!
|
||||
|
||||
#### Why is DNS based challenges the only supported method?
|
||||
|
||||
Having challenges done through DNS means you can set up your certificates before
|
||||
your web server or proxy is provisioned. It also means your web server doesn't
|
||||
need to know anything about how the ACME challenge works. All you have to do is
|
||||
reference the final certificates this role generates.
|
||||
|
||||
Another perk is if you're running a web server inside of Docker, you might not
|
||||
have that up and running until after your server has been provisioned by Ansible.
|
||||
For example, it's common to set up git based deploys to kick off an app deploy.
|
||||
|
||||
Also, it's nice using DNS challenges because DNS challenges are the only way to
|
||||
issue wildcard certificates using Let's Encrypt. Focusing efforts onto 1 solution
|
||||
that works with all certificate types seemed like the right move.
|
||||
|
||||
With that said, I probably won't be supporting other modes such as standalone,
|
||||
webroot, nginx or Apache but nothing is set in stone.
|
||||
|
||||
## Supported platforms
|
||||
|
||||
- Ubuntu 16.04 LTS (Xenial)
|
||||
- Ubuntu 18.04 LTS (Bionic)
|
||||
- Debian 8 (Jessie)
|
||||
- Debian 9 (Stretch)
|
||||
|
||||
## Role variables
|
||||
|
||||
```
|
||||
# The user on the system that acme.sh will run as. Keep in mind this user
|
||||
# needs to already exist, this role will not create it.
|
||||
acme_sh_become_user: "root"
|
||||
|
||||
# The acme.sh repo to clone.
|
||||
acme_sh_git_url: "https://github.com/Neilpang/acme.sh"
|
||||
|
||||
# The branch, tag or commit that will be cloned.
|
||||
acme_sh_git_version: "master"
|
||||
|
||||
# By default if you were to clone this repo now and then 6 months from now you
|
||||
# clonged it again, it will stick with the old master version from 6 months ago.
|
||||
# If you want to pull the latest master version on every run, set this to True.
|
||||
acme_sh_git_update: False
|
||||
|
||||
# Where will this repo get cloned to?
|
||||
acme_sh_git_clone_dest: "/usr/local/src/acme.sh"
|
||||
|
||||
# When enabled, acme.me will upgrade itself to the latest version which is
|
||||
# separate from updating the git repo. That's because acme.sh installs itself
|
||||
# with an installer after cloning the source code.
|
||||
#
|
||||
# Enabling it could be good to get the latest release which may have bug fixes
|
||||
# but keep in mind if you do this, you may get different results per run. I
|
||||
# recommend occasionally setting this to True but keeping it disabled usually.
|
||||
acme_sh_upgrade: False
|
||||
|
||||
# When enabled the cloned source code, installation path, log files and renewal
|
||||
# cron jobs will be removed.
|
||||
#
|
||||
# Installed certificates will not be removed. If you want to remove the installed
|
||||
# certificates there is another option for that which we'll cover later.
|
||||
acme_sh_uninstall: False
|
||||
|
||||
# When creating an initial Let's Encrypt account, you can optionally supply an
|
||||
# email address. By default this isn't set, but feel free to add your email
|
||||
# address in if you want. If you do set it, you'll get emailed when your
|
||||
# certificates are within 20 days of expiring.
|
||||
#
|
||||
# I highly recommend setting this because if all goes as planned you'll never
|
||||
# get emailed unless acme.sh malfunctioned and failed to renew a certificate.
|
||||
acme_sh_account_email: ""
|
||||
|
||||
# Certificates will be renewed through an acme.sh managed cron job. By default
|
||||
# acme.sh uses 60 days for each renewal attempt, but I've chosen to go with 30
|
||||
# by default to give 1 extra attempt in case something unexpected happens.
|
||||
#
|
||||
# Certificates that don't need to be renewed will be skipped by acme.sh, so
|
||||
# it's all good. It's also worth mentioning this value cannot be > 60 days which
|
||||
# is a limit enforced by acme.sh, this role does not double check the value.
|
||||
acme_sh_renew_time_in_days: 30
|
||||
|
||||
# The base path where certificates will be copied into. If you're familiar with
|
||||
# acme.sh, this is for the certificates generated with --install-cert.
|
||||
#
|
||||
# This is the final destination for your certificates and the user you've chosen
|
||||
# will need write access to this path. This path will end up being having its
|
||||
# owner:group set to the acme_sh_become_user's value.
|
||||
acme_sh_copy_certs_to_path: "/etc/ssl/ansible"
|
||||
|
||||
# At the end of the run, an Ansible debug message will print out a list of
|
||||
# domains that have valid SSL certificates along with their expiration dates.
|
||||
# You can disable this by setting it to False.
|
||||
acme_sh_list_domains: True
|
||||
|
||||
# When set to False, it will use the live Let's Encrypt servers, so please make
|
||||
# sure everything works with staging True or you may find yourself rate limited.
|
||||
#
|
||||
# It is worth mentioning you'll need to force issue a new certificate when
|
||||
# swiching between staging and live or vice versa.
|
||||
acme_sh_default_staging: True
|
||||
|
||||
# When set to True, this will regenerate a new certificate even if your list of
|
||||
# domains didn't change. It's also used to set a new DNS provider and API keys.
|
||||
#
|
||||
# Be careful with this because you may get rate limited if on the live server.
|
||||
# Only consider using this to update your DNS provider. You should set it back
|
||||
# to False when you're done.
|
||||
acme_sh_default_force_issue: False
|
||||
|
||||
# When set to True, this will regenerate a new certificate for an existing list
|
||||
# of certificates. This will not update your DNS provider or API keys.
|
||||
#
|
||||
# This could be useful to use if your certificates expired. You should set it
|
||||
# back to False when you're done.
|
||||
acme_sh_default_force_renew: False
|
||||
|
||||
# When set to True, this will provide more detailed information to STDOUT. This
|
||||
# could be useful if you're testing the role in staging mode.
|
||||
acme_sh_default_debug: False
|
||||
|
||||
# Which DNS provider should you use?
|
||||
# A list of supported providers can be found at:
|
||||
# https://github.com/Neilpang/acme.sh#7-automatic-dns-api-integration
|
||||
# As for getting the name to use, you can find that at:
|
||||
# https://github.com/Neilpang/acme.sh/tree/master/dnsapi
|
||||
#
|
||||
# It defaults to DigitalOcean. Make sure to include the dns_ part of the name,
|
||||
# but leave off the .sh file extension.
|
||||
acme_sh_default_dns_provider: "dns_dgon"
|
||||
|
||||
# What are your DNS provider's API key(s)?
|
||||
# The key names to use can be found at:
|
||||
# https://github.com/Neilpang/acme.sh/tree/master/dnsapi
|
||||
#
|
||||
# The API key can be created on your DNS provider's website. Some providers
|
||||
# require 1 key, while others require 2+. Just add them as key / value pairs here
|
||||
# without the "export ".
|
||||
#
|
||||
# For example if you were using DigitalOcean you would enter:
|
||||
# acme_sh_default_dns_provider_api_keys:
|
||||
# "DO_API_KEY": "THE_API_SECRET_TOKEN_FROM_THE_DO_DASHBOARD"
|
||||
acme_sh_default_dns_provider_api_keys: {}
|
||||
|
||||
# How long should acme.sh sleep after attempting to set the TXT record to your
|
||||
# DNS records? Some DNS providers do not update as fast as others.
|
||||
#
|
||||
# 120 is the default value from acme.sh itself but keep in mind if you use
|
||||
# NameSilo, their DNS updates only propagate once per 15 minutes so you'll need
|
||||
# to set this value to 900 or you run the risk of getting a DNS NXDOMAIN error.
|
||||
#
|
||||
# I recommend keeping it set to 120 or higher if your DNS provider requires it.
|
||||
#
|
||||
# Although as an aside, I used 10 when testing this role against DigitalOcean
|
||||
# and it worked about 30 times in a row. Still, in production I would use 120
|
||||
# just to be safe because this 2 minute delay will only affect you on the first
|
||||
# Ansible run. After that it will be updated in the background through a cron job.
|
||||
acme_sh_default_dns_sleep: 120
|
||||
|
||||
# When issuing new certificates, you can choose to add additional flags that
|
||||
# are not present here by default. Supply them just as you would on the command
|
||||
# line, such as "--help".
|
||||
acme_sh_default_extra_flags_issue: ""
|
||||
|
||||
# When renewing certificates, you can choose to add additional flags that
|
||||
# are not present here by default. Supply them just as you would on the command
|
||||
# line, such as "--help".
|
||||
acme_sh_default_extra_flags_renew: ""
|
||||
|
||||
# When installing certificates, you can choose to add additional flags that
|
||||
# are not present here by default. Supply them just as you would on the command
|
||||
# line, such as "--help".
|
||||
#
|
||||
# Installing is different than issuing and we'll cover that later.
|
||||
acme_sh_default_extra_flags_install_cert: ""
|
||||
|
||||
# When a certificate is issued or renewed, acme.sh will attempt to run a command
|
||||
# of your choosing. This could be to restart or reload your web server or proxy.
|
||||
#
|
||||
# Keep in mind the user you set in acme_sh_become_user needs access rights to
|
||||
# sudo if you use sudo here, or if not, they need access rights to reload your
|
||||
# web server / proxy.
|
||||
#
|
||||
# For a Docker example, check the example section of this README.
|
||||
acme_sh_default_install_cert_reloadcmd: "sudo systemctl reload nginx"
|
||||
|
||||
# If you need more fine grain control than the reloadcmd you can hook into the
|
||||
# life cycle of issuing or renewing a certificate. By default the following 3
|
||||
# options do nothing unless you fill them out. They are not needed for everything
|
||||
# to function as long as your reloadcmd works.
|
||||
#
|
||||
# When a certificate is issued or renewed, acme.sh will attempt to run a command
|
||||
# before attempting to issue a certificate. This can only be applied while
|
||||
# issuing a certificate but it will be saved and used for renewing as well.
|
||||
#
|
||||
# This will execute even if the certificate wasn't successfully issued / renewed.
|
||||
acme_sh_default_issue_pre_hook: ""
|
||||
|
||||
# When a certificate is issued or renewed, acme.sh will attempt to run a command
|
||||
# after attempting to issue a certificate. This can only be applied while
|
||||
# issuing a certificate but it will be saved and used for renewing as well.
|
||||
#
|
||||
# This will execute even if the certificate wasn't successfully issued / renewed.
|
||||
acme_sh_default_issue_post_hook: ""
|
||||
|
||||
# When a certificate is issued or renewed, acme.sh will attempt to run a command
|
||||
# after a certificate is successfully renewed. This can only be applied while
|
||||
# issuing a certificate but it will be saved and used for renewing as well.
|
||||
#
|
||||
# This will only execute if the certificate was successfully issued / renewed.
|
||||
acme_sh_default_issue_renew_hook: ""
|
||||
|
||||
# When set to True, certificates will be removed and unset from being renewed
|
||||
# instead of being created and set for renewal. This will not uninstall acme.sh.
|
||||
acme_sh_default_remove: False
|
||||
|
||||
# This list contains a list of domains, along with key / value pairs to
|
||||
# configure each set of domains individually.
|
||||
#
|
||||
# Here's an example with every available option documented, and a couple of real
|
||||
# examples will also be included in the example section of this README:
|
||||
acme_sh_domains:
|
||||
# A list of 1 or more domains, you can use ["*.example.com" ,"example.com] for
|
||||
# setting a wildcard + root domain certificate. Domains listed here will
|
||||
# all belong to the same certificate. If you want separate certificate files
|
||||
# then create a new "domains:" item in the list.
|
||||
#
|
||||
# The first domain in the list will end up being used as a base file name for
|
||||
# the certificate name. In this case it would be "example.com.pem".
|
||||
# - domains: ["example.com", "www.example.com]
|
||||
# # Optionally override the default staging variable. This overall pattern lets
|
||||
# # you situationally override the defaults listed above for each domain list.
|
||||
# staging: False
|
||||
# # Optionally force issue new certificates.
|
||||
# force_issue: False
|
||||
# # Optionally force renew certificates.
|
||||
# force_renew: False
|
||||
# # Optionally turn on debug mode.
|
||||
# debug: True
|
||||
# # Optionally override the default DNS provider.
|
||||
# dns_provider: "dns_namesilo"
|
||||
# # Optionally override the default DNS API keys.
|
||||
# dns_provider_api_keys:
|
||||
# "Namesilo_Key": "THE_API_SECRET_TOKEN_FROM_THE_NAMESILO_DASHBOARD"
|
||||
# # Optionally override the default DNS sleep time.
|
||||
# dns_sleep: 900
|
||||
# # Optionally add extra flags to any of these 3 actions:
|
||||
# extra_flags_issue: ""
|
||||
# extra_flags_renew: ""
|
||||
# extra_flags_install_cert: ""
|
||||
# # Optionally set a different reload command.
|
||||
# install_cert_reloadcmd: "whoami"
|
||||
# # Optionally run commands during different points in the cert issue process:
|
||||
# extra_issue_pre_hook: ""
|
||||
# extra_issue_post_hook: ""
|
||||
# extra_issue_renew_hook: ""
|
||||
# # Optionally remove and disable the certificate.
|
||||
# remove: True
|
||||
|
||||
# How long should the apt-cache last in seconds?
|
||||
acme_sh_apt_cache_time: 86400
|
||||
```
|
||||
|
||||
## Example usage
|
||||
|
||||
For the sake of this example let's assume you have a group called **app** and
|
||||
you have a typical `site.yml` file.
|
||||
|
||||
To use this role edit your `site.yml` file to look something like this:
|
||||
|
||||
```
|
||||
---
|
||||
|
||||
- name: Configure app server(s)
|
||||
hosts: "app"
|
||||
become: True
|
||||
|
||||
roles:
|
||||
- { role: "nickjj.acme-sh", tags: ["acme-sh"] }
|
||||
```
|
||||
|
||||
Here's a few examples. You can recreate this example on your end by opening or
|
||||
creating `group_vars/app.yml` which is located relative to your `inventory`
|
||||
directory and then making it look like this:
|
||||
|
||||
```
|
||||
---
|
||||
|
||||
acme_sh_account_email: "you@example.com"
|
||||
|
||||
# An example where a DNS provider has 2 keys for API access:
|
||||
acme_sh_default_dns_provider: "dns_cf"
|
||||
acme_sh_default_dns_provider_api_keys:
|
||||
"CF_Key": "THE_API_SECRET_TOKEN_FROM_THE_CLOUDFLARE_DASHBOARD"
|
||||
"CF_Email: "you@example.com"
|
||||
|
||||
# Reloading nginx inside of a Docker container that is named "nginx".
|
||||
# If you are running nginx in a Docker container then you'll also need to volume
|
||||
# mount in your certificates, but I'm sure you knew that already!
|
||||
acme_sh_default_install_cert_reloadcmd: "docker exec nginx nginx -s reload"
|
||||
|
||||
# --- Here's a few different acme_sh_domains examples --------------------------
|
||||
# You would only need to supply one of these based on what you wanted to do!
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
# 1 certificate file for all of the domains.
|
||||
acme_sh_domains:
|
||||
- domains: ["example.com", "www.example.com", "admin.example.com"]
|
||||
|
||||
# Produces this on your server:
|
||||
# /etc/ssl/ansible/example.com.key (the private key)
|
||||
# /etc/ssl/ansible/example.com.pem (the full chain certificate)
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
# 2 certificate files using the same domains as above.
|
||||
acme_sh_domains:
|
||||
- domains: ["example.com", "www.example.com"]
|
||||
- domains: ["admin.example.com"]
|
||||
|
||||
# Produces this on your server:
|
||||
# /etc/ssl/ansible/example.com.key (the private key)
|
||||
# /etc/ssl/ansible/example.com.pem (the full chain certificate)
|
||||
# /etc/ssl/ansible/admin.example.com.key (the private key)
|
||||
# /etc/ssl/ansible/admin.example.com.pem (the full chain certificate)
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
# 2 certificate files using the same example but the admin certificate will get
|
||||
# removed and disabled.
|
||||
acme_sh_domains:
|
||||
- domains: ["example.com", "www.example.com"]
|
||||
- domains: ["admin.example.com"]
|
||||
remove: True
|
||||
|
||||
# Produces this on your server:
|
||||
# /etc/ssl/ansible/example.com.key (the private key)
|
||||
# /etc/ssl/ansible/example.com.pem (the full chain certificate)
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
# 2 certificate files using the same example but switching from staging to live
|
||||
# on admin.example.com (but remember to remove force_issue after it runs once).
|
||||
acme_sh_domains:
|
||||
- domains: ["example.com", "www.example.com"]
|
||||
- domains: ["admin.example.com"]
|
||||
staging: False
|
||||
force_issue: True
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
# 2 certificate files using the same example but forcing a renew on
|
||||
# admin.example.com (let's say a catastrophic error happened and the cert expired).
|
||||
acme_sh_domains:
|
||||
- domains: ["example.com", "www.example.com"]
|
||||
- domains: ["admin.example.com"]
|
||||
force_renew: True
|
||||
```
|
||||
|
||||
*If you're looking for an Ansible role to create users, then check out my
|
||||
[user role](https://github.com/nickjj/ansible-user)*.
|
||||
|
||||
Now you would run `ansible-playbook -i inventory/hosts site.yml -t acme-sh`.
|
||||
|
||||
## Installation
|
||||
|
||||
`$ ansible-galaxy install nickjj.acme-sh`
|
||||
|
||||
## Ansible Galaxy
|
||||
|
||||
You can find it on the official
|
||||
[Ansible Galaxy](https://galaxy.ansible.com/nickjj/acme-sh/) if you want to
|
||||
rate it.
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
46
defaults/main.yml
Normal file
46
defaults/main.yml
Normal file
@ -0,0 +1,46 @@
|
||||
---
|
||||
|
||||
acme_sh_become_user: "root"
|
||||
|
||||
acme_sh_git_url: "https://github.com/Neilpang/acme.sh"
|
||||
acme_sh_git_version: "master"
|
||||
acme_sh_git_update: False
|
||||
acme_sh_git_clone_dest: "/usr/local/src/acme.sh"
|
||||
|
||||
acme_sh_upgrade: False
|
||||
acme_sh_uninstall: False
|
||||
|
||||
acme_sh_account_email: ""
|
||||
|
||||
acme_sh_renew_time_in_days: 30
|
||||
|
||||
acme_sh_copy_certs_to_path: "/etc/ssl/ansible"
|
||||
|
||||
acme_sh_list_domains: True
|
||||
|
||||
acme_sh_default_staging: True
|
||||
|
||||
acme_sh_default_force_issue: False
|
||||
acme_sh_default_force_renew: False
|
||||
|
||||
acme_sh_default_debug: False
|
||||
|
||||
acme_sh_default_dns_provider: "dns_dgon"
|
||||
acme_sh_default_dns_provider_api_keys: {}
|
||||
acme_sh_default_dns_sleep: 120
|
||||
|
||||
acme_sh_default_extra_flags_issue: ""
|
||||
acme_sh_default_extra_flags_renew: ""
|
||||
acme_sh_default_extra_flags_install_cert: ""
|
||||
|
||||
acme_sh_default_install_cert_reloadcmd: "sudo service nginx reload"
|
||||
|
||||
acme_sh_default_issue_pre_hook: ""
|
||||
acme_sh_default_issue_post_hook: ""
|
||||
acme_sh_default_issue_renew_hook: ""
|
||||
|
||||
acme_sh_default_remove: False
|
||||
|
||||
acme_sh_domains: []
|
||||
|
||||
acme_sh_apt_cache_time: 86400
|
27
meta/main.yml
Normal file
27
meta/main.yml
Normal file
@ -0,0 +1,27 @@
|
||||
---
|
||||
|
||||
galaxy_info:
|
||||
role_name: "acme-sh"
|
||||
author: "Nick Janetakis"
|
||||
description: "Install and auto-renew SSL certificates with Let's Encrypt using acme.sh."
|
||||
license: "license (MIT)"
|
||||
min_ansible_version: 2.5
|
||||
|
||||
platforms:
|
||||
- name: "Ubuntu"
|
||||
versions:
|
||||
- "xenial"
|
||||
- "bionic"
|
||||
- name: "Debian"
|
||||
versions:
|
||||
- "jessie"
|
||||
- "stretch"
|
||||
|
||||
galaxy_tags:
|
||||
- "https"
|
||||
- "networking"
|
||||
- "security"
|
||||
- "ssl"
|
||||
- "system"
|
||||
|
||||
dependencies: []
|
233
tasks/main.yml
Normal file
233
tasks/main.yml
Normal file
@ -0,0 +1,233 @@
|
||||
---
|
||||
|
||||
- name: Install dependencies
|
||||
apt:
|
||||
name: "{{ item }}"
|
||||
update_cache: True
|
||||
cache_valid_time: "{{ acme_sh_apt_cache_time }}"
|
||||
loop: ["cron", "git", "wget"]
|
||||
when: not acme_sh_uninstall
|
||||
|
||||
- name: Create git clone path
|
||||
file:
|
||||
path: "{{ acme_sh_git_clone_dest | dirname }}"
|
||||
state: "directory"
|
||||
owner: "{{ acme_sh_become_user }}"
|
||||
group: "{{ acme_sh_become_user }}"
|
||||
mode: "0755"
|
||||
when: not acme_sh_uninstall
|
||||
|
||||
- name: Git clone https://github.com/Neilpang/acme.sh
|
||||
git:
|
||||
repo: "{{ acme_sh_git_url }}"
|
||||
version: "{{ acme_sh_git_version }}"
|
||||
dest: "{{ acme_sh_git_clone_dest }}"
|
||||
update: "{{ acme_sh_git_update }}"
|
||||
when: not acme_sh_uninstall
|
||||
become_user: "{{ acme_sh_become_user }}"
|
||||
|
||||
- name: Install acme.sh
|
||||
command: >-
|
||||
./acme.sh --install --log
|
||||
--days {{ acme_sh_renew_time_in_days }}
|
||||
{{ "--accountemail " + acme_sh_account_email if acme_sh_account_email else "" }}
|
||||
args:
|
||||
chdir: "{{ acme_sh_git_clone_dest }}"
|
||||
creates: "~/.acme.sh/acme.sh"
|
||||
when: not acme_sh_uninstall
|
||||
become_user: "{{ acme_sh_become_user }}"
|
||||
|
||||
- name: Determine if acme.sh is installed
|
||||
stat:
|
||||
path: "~/.acme.sh/acme.sh"
|
||||
register: is_acme_sh_installed
|
||||
become_user: "{{ acme_sh_become_user }}"
|
||||
|
||||
- name: Upgrade acme.sh
|
||||
command: ./acme.sh --upgrade
|
||||
args:
|
||||
chdir: "~/.acme.sh"
|
||||
when:
|
||||
- acme_sh_upgrade
|
||||
- is_acme_sh_installed.stat.exists
|
||||
- not acme_sh_uninstall
|
||||
register: upgrade_result
|
||||
changed_when: upgrade_result.rc == 0 and "Upgrade success" in upgrade_result.stdout
|
||||
become_user: "{{ acme_sh_become_user }}"
|
||||
|
||||
- name: Create certificate path
|
||||
file:
|
||||
path: "{{ acme_sh_copy_certs_to_path }}"
|
||||
state: "directory"
|
||||
owner: "{{ acme_sh_become_user }}"
|
||||
group: "{{ acme_sh_become_user }}"
|
||||
mode: "0755"
|
||||
when: not acme_sh_uninstall
|
||||
|
||||
- name: Uninstall acme.sh and disable all certificate renewals
|
||||
command: ./acme.sh --uninstall
|
||||
args:
|
||||
chdir: "~/.acme.sh"
|
||||
when:
|
||||
- acme_sh_uninstall
|
||||
- is_acme_sh_installed.stat.exists
|
||||
become_user: "{{ acme_sh_become_user }}"
|
||||
|
||||
- name: Remove acme.sh certificate(s) renewals from cron job
|
||||
command: >-
|
||||
./acme.sh --remove -d {{ item.domains | first }}
|
||||
{{ "--debug" if item.debug | default(acme_sh_default_debug) else "" }}
|
||||
args:
|
||||
chdir: "~/.acme.sh"
|
||||
removes: "~/.acme.sh/{{ item.domains | first }}"
|
||||
loop: "{{ acme_sh_domains }}"
|
||||
when:
|
||||
- acme_sh_domains and item.domains is defined and item.domains
|
||||
- item.remove is defined and item.remove
|
||||
- not acme_sh_uninstall
|
||||
become_user: "{{ acme_sh_become_user }}"
|
||||
register: remove_result
|
||||
|
||||
- name: Remove acme.sh internal certificate files
|
||||
file:
|
||||
path: "~/.acme.sh/{{ item.domains | first }}"
|
||||
state: "absent"
|
||||
when:
|
||||
- acme_sh_domains and item.domains is defined and item.domains
|
||||
- item.remove is defined and item.remove
|
||||
- not acme_sh_uninstall
|
||||
loop: "{{ acme_sh_domains }}"
|
||||
become_user: "{{ acme_sh_become_user }}"
|
||||
|
||||
- name: Remove acme.sh installed certificate files
|
||||
file:
|
||||
path: "{{ acme_sh_copy_certs_to_path }}/{{ item.domains | first }}*"
|
||||
state: "absent"
|
||||
loop: "{{ acme_sh_domains }}"
|
||||
when:
|
||||
- acme_sh_domains and item.domains is defined and item.domains
|
||||
- item.remove is defined and item.remove
|
||||
- not acme_sh_uninstall
|
||||
|
||||
- name: Remove acme.sh's cloned source code, installation path and log files
|
||||
file:
|
||||
path: "{{ item }}"
|
||||
state: "absent"
|
||||
loop:
|
||||
- "{{ acme_sh_git_clone_dest }}"
|
||||
- "~/.acme.sh"
|
||||
when:
|
||||
- acme_sh_uninstall
|
||||
become_user: "{{ acme_sh_become_user }}"
|
||||
|
||||
- name: Run custom acme.sh command
|
||||
command: ./acme.sh {{ item.custom_command }}
|
||||
args:
|
||||
chdir: "~/.acme.sh"
|
||||
environment: "{{ item.dns_provider_api_keys | default(acme_sh_default_dns_provider_api_keys) }}"
|
||||
loop: "{{ acme_sh_domains }}"
|
||||
when:
|
||||
- acme_sh_domains and item.domains is defined and item.domains
|
||||
- item.dns_provider | default(acme_sh_default_dns_provider)
|
||||
- item.dns_provider_api_keys | default(acme_sh_default_dns_provider_api_keys)
|
||||
- item.custom_command is defined and item.custom_command
|
||||
- item.remove is undefined or not item.remove
|
||||
- not acme_sh_uninstall
|
||||
become_user: "{{ acme_sh_become_user }}"
|
||||
|
||||
- name: Issue acme.sh certificate(s) (this will sleep for dns_sleep seconds)
|
||||
command: >-
|
||||
./acme.sh --issue -d {{ item.domains | join(" -d ") }}
|
||||
--dns {{ item.dns_provider | default(acme_sh_default_dns_provider) }}
|
||||
--dnssleep {{ item.dns_sleep | default(acme_sh_default_dns_sleep) }}
|
||||
{{ "--force" if item.force_issue | default(acme_sh_default_force_issue) else "" }}
|
||||
{{ "--staging" if item.staging | default(acme_sh_default_staging) else "" }}
|
||||
{{ "--debug" if item.debug | default(acme_sh_default_debug) else "" }}
|
||||
{{ "--pre-hook " + '"' + item.issue_pre_hook | default(acme_sh_default_issue_pre_hook) + '"' if item.issue_pre_hook | default(acme_sh_default_issue_pre_hook) else "" }}
|
||||
{{ "--post-hook " + '"' + item.issue_post_hook | default(acme_sh_default_issue_post_hook) + '"' if item.issue_post_hook | default(acme_sh_default_issue_post_hook) else "" }}
|
||||
{{ "--renew-hook " + '"' + item.issue_renew_hook | default(acme_sh_default_issue_renew_hook) + '"' if item.issue_renew_hook | default(acme_sh_default_issue_renew_hook) else "" }}
|
||||
{{ item.extra_flags_issue | default(acme_sh_default_extra_flags_issue) }}
|
||||
args:
|
||||
chdir: "~/.acme.sh"
|
||||
environment: "{{ item.dns_provider_api_keys | default(acme_sh_default_dns_provider_api_keys) }}"
|
||||
loop: "{{ acme_sh_domains }}"
|
||||
when:
|
||||
- acme_sh_domains and item.domains is defined and item.domains
|
||||
- item.dns_provider | default(acme_sh_default_dns_provider)
|
||||
- item.dns_provider_api_keys | default(acme_sh_default_dns_provider_api_keys)
|
||||
- item.force_renew is undefined or not item.force_renew
|
||||
- item.custom_command is undefined or not item.custom_command
|
||||
- item.remove is undefined or not item.remove
|
||||
- not acme_sh_uninstall
|
||||
become_user: "{{ acme_sh_become_user }}"
|
||||
register: issue_result
|
||||
changed_when: issue_result.rc == 0 and "Cert success" in issue_result.stdout
|
||||
failed_when: issue_result.rc != 0 and "Domains not changed" not in issue_result.stdout
|
||||
|
||||
- name: Force renew acme.sh certificate(s)
|
||||
command: >-
|
||||
./acme.sh --renew -d {{ item.domains | first }} --force
|
||||
{{ "--debug" if item.debug | default(acme_sh_default_debug) else "" }}
|
||||
{{ item.extra_flags_renew | default(acme_sh_default_extra_flags_renew) }}
|
||||
args:
|
||||
chdir: "~/.acme.sh"
|
||||
loop: "{{ acme_sh_domains }}"
|
||||
when:
|
||||
- acme_sh_domains and item.domains is defined and item.domains
|
||||
- item.force_issue is undefined or not item.force_issue
|
||||
- item.force_renew is defined and item.force_renew
|
||||
- item.remove is undefined or not item.remove
|
||||
- not acme_sh_uninstall
|
||||
become_user: "{{ acme_sh_become_user }}"
|
||||
register: renew_result
|
||||
failed_when: renew_result.rc != 0 and "Reload error for" not in renew_result.stderr
|
||||
|
||||
- name: Ensure installed certificates have correct user / group ownership
|
||||
file:
|
||||
path: "{{ acme_sh_copy_certs_to_path }}/{{ item.domains | first }}*"
|
||||
group: "{{ acme_sh_become_user }}"
|
||||
owner: "{{ acme_sh_become_user }}"
|
||||
loop:
|
||||
- "{{ acme_sh_domains }}"
|
||||
when:
|
||||
- acme_sh_domains and item.domains is defined and item.domains
|
||||
- item.custom_command is undefined or not item.custom_command
|
||||
- item.remove is undefined or not item.remove
|
||||
- not acme_sh_uninstall
|
||||
|
||||
- name: Install acme.sh certificate(s)
|
||||
command: >-
|
||||
./acme.sh --install-cert -d {{ item.domains | first }}
|
||||
--key-file {{ acme_sh_copy_certs_to_path }}/{{ item.domains | first }}.key
|
||||
--fullchain-file {{ acme_sh_copy_certs_to_path }}/{{ item.domains | first }}.pem
|
||||
--reloadcmd "{{ item.install_cert_reloadcmd | default(acme_sh_default_install_cert_reloadcmd) }}"
|
||||
{{ "--debug" if item.debug | default(acme_sh_default_debug) else "" }}
|
||||
{{ item.extra_flags_install_cert | default(acme_sh_default_extra_flags_install_cert) }}
|
||||
args:
|
||||
chdir: "~/.acme.sh"
|
||||
loop: "{{ acme_sh_domains }}"
|
||||
loop_control:
|
||||
index_var: domains_index
|
||||
when:
|
||||
- acme_sh_domains and item.domains is defined and item.domains
|
||||
- item.custom_command is undefined or not item.custom_command
|
||||
- item.remove is undefined or not item.remove
|
||||
- not acme_sh_uninstall
|
||||
become_user: "{{ acme_sh_become_user }}"
|
||||
register: install_cert_result
|
||||
changed_when: issue_result.results[domains_index].changed or renew_result.results[domains_index].changed
|
||||
failed_when: install_cert_result.rc != 0 and "Reload error for" not in install_cert_result.stderr
|
||||
|
||||
- name: Register acme.sh certificate information
|
||||
command: ./acme.sh --list
|
||||
args:
|
||||
chdir: "~/.acme.sh"
|
||||
when: acme_sh_list_domains and not acme_sh_uninstall
|
||||
changed_when: False
|
||||
register: list_domains
|
||||
become_user: "{{ acme_sh_become_user }}"
|
||||
|
||||
- name: List acme.sh certificate information
|
||||
debug:
|
||||
msg: "{{ list_domains.stdout_lines }}"
|
||||
when: acme_sh_list_domains and not acme_sh_uninstall
|
34
tests/test.yml
Normal file
34
tests/test.yml
Normal file
@ -0,0 +1,34 @@
|
||||
---
|
||||
|
||||
- hosts: "all"
|
||||
become: True
|
||||
|
||||
vars:
|
||||
acme_sh_become_user: "test"
|
||||
roles:
|
||||
- "role_under_test"
|
||||
|
||||
pre_tasks:
|
||||
- name: Add test user
|
||||
user:
|
||||
name: "{{ acme_sh_become_user }}"
|
||||
shell: "/bin/bash"
|
||||
|
||||
post_tasks:
|
||||
- name: Ensure acme.me was cloned
|
||||
command: test -d /usr/local/src/acme.sh
|
||||
register: result_cloned
|
||||
changed_when: result_cloned.rc != 0
|
||||
|
||||
- name: Ensure acme.me was installed
|
||||
command: ./acme.sh --version
|
||||
args:
|
||||
chdir: "~/.acme.sh"
|
||||
register: result_installed
|
||||
changed_when: result_installed.rc != 0
|
||||
become_user: "{{ acme_sh_become_user }}"
|
||||
|
||||
- name: Ensure certificate installation path exists
|
||||
command: test -d /etc/ssl/ansible
|
||||
register: result_cert_installed_path
|
||||
changed_when: result_cert_installed_path.rc != 0
|
Loading…
Reference in New Issue
Block a user