commit dcfdc638b9b20d3facdec50a3b76f8fe4163508b Author: Raphaël Hertzog Date: Tue Jun 21 00:59:06 2016 +0200 Initial commit diff --git a/CHANGELOG.rst b/CHANGELOG.rst new file mode 100644 index 0000000..4b97e46 --- /dev/null +++ b/CHANGELOG.rst @@ -0,0 +1,7 @@ +letsencrypt-sh formula +====================== + +0.1.0 (2016-06-21) + +- Initial version, compatible with version 0.1.0 of the client + (tested with version 0.1.0-3~bpo8+1 of the Debian package). diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..caf1e28 --- /dev/null +++ b/LICENSE @@ -0,0 +1,14 @@ + Copyright (c) 2016 Salt Stack Formulas + Copyright (c) 2016 Raphaël Hertzog + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/README.rst b/README.rst new file mode 100644 index 0000000..0a2ea8e --- /dev/null +++ b/README.rst @@ -0,0 +1,42 @@ +====================== +letsencrypt-sh-formula +====================== + +This formula allows you to use the +`letsencrypt.sh ` client +to automatically manage TLS certificates issued by the +`letsencrypt.org ` service. + +Available states +================ + +.. contents:: + :local: + +``letsencrypt-sh`` +------------------ + +Installs the letsencrypt.sh client, its configuration file, the apache +integration and the cron job. + +``letsencrypt-sh.install`` +-------------------------- + +Installs the letsencrypt.sh client. + +``letsencrypt-sh.config`` +------------------------- + +Installs the letsencrypt.sh configuration file. + +``letsencrypt-sh.apache`` +------------------------- + +Installs the Apache integration allowing letsencrypt.sh to validate HTTP +challenges required by letsencrypt.org to issue/renew TLS certificates. + +``letsencrypt-sh.cron`` +----------------------- + +Enables a periodic task that renews managed TLS certificates that are +about to expire. diff --git a/VERSION b/VERSION new file mode 100644 index 0000000..6e8bf73 --- /dev/null +++ b/VERSION @@ -0,0 +1 @@ +0.1.0 diff --git a/letsencrypt-sh/apache.sls b/letsencrypt-sh/apache.sls new file mode 100644 index 0000000..e521369 --- /dev/null +++ b/letsencrypt-sh/apache.sls @@ -0,0 +1,8 @@ +# -*- coding: utf-8 -*- +# vim: ft=sls + +{% from "letsencrypt-sh/map.jinja" import letsencrypt_sh with context %} + +letsencrypt-sh-pkg-apache: + pkg.installed: + - name: {{ letsencrypt_sh.pkg_apache }} diff --git a/letsencrypt-sh/config.sls b/letsencrypt-sh/config.sls new file mode 100644 index 0000000..6eb2797 --- /dev/null +++ b/letsencrypt-sh/config.sls @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# vim: ft=sls + +{% from "letsencrypt-sh/map.jinja" import letsencrypt_sh with context %} + +letsencrypth-sh-config: + file.managed: + - name: {{ letsencrypt_sh.config_file }} + - source: salt://letsencrypt-sh/files/config.sh + - mode: 644 + - user: root + - group: root + - template: jinja + +letsencrypt-sh-domains: + file.managed: + - name: {{ letsencrypt_sh.domains_txt }} + - source: salt://letsencrypt-sh/files/domains.txt + - mode: 644 + - user: root + - group: root + - template: jinja diff --git a/letsencrypt-sh/cron.sls b/letsencrypt-sh/cron.sls new file mode 100644 index 0000000..6f8c3a7 --- /dev/null +++ b/letsencrypt-sh/cron.sls @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +# vim: ft=sls + +{% from "letsencrypt-sh/map.jinja" import letsencrypt_sh with context %} + +{% if letsencrypt_sh.cron_enabled %} +letsencrypt-sh-cron: + cron.present: + - name: {{ letsencrypt_sh.cron_command }} + - user: root + - identifier: letsencrypt-sh-cron + - minute: {{ letsencrypt_sh.cron_minute }} + - hour: {{ letsencrypt_sh.cron_hour }} + - dayweek: {{ letsencrypt_sh.cron_dayweek }} + - comment: Renew TLS certificates with letsencrypt.org +{% else %} +disable-letsencrypt-sh-cron: + cron.absent: + - user: root + - identifier: letsencrypt-sh-cron +{% endif %} diff --git a/letsencrypt-sh/defaults.yaml b/letsencrypt-sh/defaults.yaml new file mode 100644 index 0000000..a86b023 --- /dev/null +++ b/letsencrypt-sh/defaults.yaml @@ -0,0 +1,13 @@ +# -*- coding: utf-8 -*- +# vim: ft=yaml +letsencrypt_sh: + pkg: 'letsencrypt.sh' + pkg_apache: 'letsencrypt.sh-apache2' + config_file: '/etc/letsencrypt.sh/conf.d/defaults.sh' + basedir: '/var/lib/letsencrypt.sh' + domains_txt: '/var/lib/letsencrypt.sh/domains.txt' + cron_command: 'letsencrypt.sh --cron >/var/log/letsencrypt.sh.log 2>&1; res=$?; [ $res -eq 0 ] || cat /var/log/letsencrypt.sh.log; exit $res' + cron_minute: random + cron_hour: random + cron_dayweek: random + cron_enabled: True diff --git a/letsencrypt-sh/files/config.sh b/letsencrypt-sh/files/config.sh new file mode 100644 index 0000000..017f3c1 --- /dev/null +++ b/letsencrypt-sh/files/config.sh @@ -0,0 +1,74 @@ +{% set cfg_client = salt['pillar.get']('letsencrypt-sh:config', {}) -%} +{%- macro get_config(configname, default_value) -%} +{%- set varname = configname.replace("-", "_") -%} +{%- if configname in cfg_client -%} +{{ varname|upper }}="{{ cfg_client[configname] }}" +{%- else -%} +#{{ varname|upper }}="{{ default_value }}" +{%- endif -%} +{%- endmacro -%} +# This file is managed by Salt, do not edit by hand! +# Based on letsencrypt.sh version 0.1.0 default config + +######################################################## +# This is the main config file for letsencrypt.sh # +# # +# Default values of this config are in comments # +######################################################## + +# Path to certificate authority (default: https://acme-v01.api.letsencrypt.org/directory) +{{ get_config('ca', 'https://acme-v01.api.letsencrypt.org/directory') }} + +# Path to license agreement (default: https://letsencrypt.org/documents/LE-SA-v1.0.1-July-27-2015.pdf) +{{ get_config('license', 'https://letsencrypt.org/documents/LE-SA-v1.0.1-July-27-2015.pdf') }} + +# Which challenge should be used? Currently http-01 and dns-01 are supported +{{ get_config('challengetype', 'http-01') }} + +# Base directory for account key, generated certificates and list of domains (default: $SCRIPTDIR -- uses config directory if undefined) +{{ get_config('basedir', '/var/lib/letsencrypt.sh') }} + +# Output directory for challenge-tokens to be served by webserver or deployed in HOOK (default: $BASEDIR/.acme-challenges) +{{ get_config('wellknown', '/var/lib/letsencrypt.sh/acme-challenges') }} + +# Location of private account key (default: $BASEDIR/private_key.pem) +{{ get_config('private-key', '${BASEDIR}/private_key.pem') }} + +# Location of private account registration information (default: $BASEDIR/private_key.json) +{{ get_config('private-key-json', '${BASEDIR}/private_key.json') }} + +# Default keysize for private keys (default: 4096) +{{ get_config('keysize', '4096') }} + +# Path to openssl config file (default: - tries to figure out system default) +{{ get_config('openssl_cnf', '') }} + +# Program or function called in certain situations +# +# After generating the challenge-response, or after failed challenge (in this case altname is empty) +# Given arguments: clean_challenge|deploy_challenge altname token-filename token-content +# +# After successfully signing certificate +# Given arguments: deploy_cert domain path/to/privkey.pem path/to/cert.pem path/to/fullchain.pem +# +# BASEDIR and WELLKNOWN variables are exported and can be used in an external program +# default: +{{ get_config('hook', '') }} + +# Chain clean_challenge|deploy_challenge arguments together into one hook call per certificate (default: no) +{{ get_config('hook-chain', 'no') }} + +# Minimum days before expiration to automatically renew certificate (default: 30) +{{ get_config('renew-days', '30') }} + +# Regenerate private keys instead of just signing new certificates on renewal (default: no) +{{ get_config('private-key-renew', 'no') }} + +# Which public key algorithm should be used? Supported: rsa, prime256v1 and secp384r1 +{{ get_config('key-algo', 'rsa') }} + +# E-mail to use during the registration (default: ) +{{ get_config('contact-email', '') }} + +# Lockfile location, to prevent concurrent access (default: $BASEDIR/lock) +{{ get_config('lockfile', '${BASEDIR}/lock') }} diff --git a/letsencrypt-sh/files/domains.txt b/letsencrypt-sh/files/domains.txt new file mode 100644 index 0000000..6d54389 --- /dev/null +++ b/letsencrypt-sh/files/domains.txt @@ -0,0 +1,5 @@ +{%- from "letsencrypt-sh/map.jinja" import letsencrypt_sh with context -%} +# This file is managed by Salt, do not edit by hand! +{% for domain in letsencrypt_sh.domains -%} +{{ domain }} +{% endfor -%} diff --git a/letsencrypt-sh/init.sls b/letsencrypt-sh/init.sls new file mode 100644 index 0000000..3b25835 --- /dev/null +++ b/letsencrypt-sh/init.sls @@ -0,0 +1,8 @@ +# -*- coding: utf-8 -*- +# vim: ft=sls + +include: + - letsencrypt-sh.install + - letsencrypt-sh.config + - letsencrypt-sh.apache + - letsencrypt-sh.cron diff --git a/letsencrypt-sh/install.sls b/letsencrypt-sh/install.sls new file mode 100644 index 0000000..bb715a1 --- /dev/null +++ b/letsencrypt-sh/install.sls @@ -0,0 +1,8 @@ +# -*- coding: utf-8 -*- +# vim: ft=sls + +{% from "letsencrypt-sh/map.jinja" import letsencrypt_sh with context %} + +letsencrypt-sh-pkg: + pkg.installed: + - name: {{ letsencrypt_sh.pkg }} diff --git a/letsencrypt-sh/map.jinja b/letsencrypt-sh/map.jinja new file mode 100644 index 0000000..80c4b48 --- /dev/null +++ b/letsencrypt-sh/map.jinja @@ -0,0 +1,29 @@ +# -*- coding: utf-8 -*- +# vim: ft=jinja + +{## Start with defaults from defaults.sls ##} +{% import_yaml 'letsencrypt-sh/defaults.yaml' as default_settings %} + +{## +Setup variable using grains['os_family'] based logic, only add key:values here +that differ from whats in defaults.yaml +##} +{% set os_family_map = salt['grains.filter_by']({ + 'Debian': {}, + 'Suse': {}, + 'Arch': {}, + 'RedHat': {}, + } + , grain="os_family" + , merge=salt['pillar.get']('letsencrypt-sh:lookup')) +%} +{## Merge the os_family_map to the default settings ##} +{% do default_settings.letsencrypt_sh.update(os_family_map) %} + +{## Merge in letsencrypt-sh pillar ##} +{% set letsencrypt_sh = salt['pillar.get']( + 'letsencrypt-sh', + default=default_settings.letsencrypt_sh, + merge=True + ) +%} diff --git a/pillar.example b/pillar.example new file mode 100644 index 0000000..82f45a2 --- /dev/null +++ b/pillar.example @@ -0,0 +1,22 @@ +letsencrypt-sh: + # Recommended parameters + # List of domains that need a TLS certificate + domains: + - example.com www.example.com + - example.net + # Parameters of configuration file + config: + # Email contact to register to letsencrypt.org + contact-email: admin@example.com + # Optional parameters + renew-days: 30 + keysize: 4096 + ca: https://acme-v01.api.letsencrypt.org/directory + openssl-cnf: /usr/lib/ssl/openssl.cnf + # see letsencrypt-sh/files/config.sh for more + # Override formula parameters + lookup: + pkg: letsencrypt.sh + pkg_apache: letsencrypt.sh-apache2 + cron_command: cronic letsencrypt.sh --cron + # see defaults.yaml for full list