aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHugo Hörnquist <hugo@lysator.liu.se>2023-01-05 16:29:24 +0100
committerHugo Hörnquist <hugo@lysator.liu.se>2023-01-05 16:29:24 +0100
commitd21390519026e6d31ffb2cfbb08bd77aebfce7c3 (patch)
tree7f3f4c79f3a62564f92bda45a365a51596fa37e1
parentInitial commit (diff)
downloadhugonikanor-letsencrypt-d21390519026e6d31ffb2cfbb08bd77aebfce7c3.tar.gz
hugonikanor-letsencrypt-d21390519026e6d31ffb2cfbb08bd77aebfce7c3.tar.xz
Initial code.
-rw-r--r--data/Archlinux.yaml3
-rw-r--r--data/FreeBSD.yaml3
-rw-r--r--files/letsencrypt-renew.service8
-rw-r--r--files/letsencrypt-renew.timer8
-rw-r--r--manifests/cert.pp39
-rw-r--r--manifests/domain.pp18
-rw-r--r--manifests/init.pp28
-rw-r--r--manifests/nginx.pp42
-rw-r--r--manifests/renew.pp13
-rw-r--r--manifests/renew/cron.pp6
-rw-r--r--manifests/renew/setup.pp17
-rw-r--r--manifests/renew/systemd.pp16
-rw-r--r--metadata.json35
13 files changed, 236 insertions, 0 deletions
diff --git a/data/Archlinux.yaml b/data/Archlinux.yaml
new file mode 100644
index 0000000..386801e
--- /dev/null
+++ b/data/Archlinux.yaml
@@ -0,0 +1,3 @@
+---
+letsencrypt::nginx::certbot_plugin_package: certbot-nginx
+letsencrypt::apache::certbot_plugin_package: certbot-apache
diff --git a/data/FreeBSD.yaml b/data/FreeBSD.yaml
new file mode 100644
index 0000000..6e2fe58
--- /dev/null
+++ b/data/FreeBSD.yaml
@@ -0,0 +1,3 @@
+---
+letsencrypt::nginx::certbot_plugin_package: py38-certbot-nginx
+letsencrypt::apache::certbot_plugin_package: py38-certbot-apache
diff --git a/files/letsencrypt-renew.service b/files/letsencrypt-renew.service
new file mode 100644
index 0000000..253f260
--- /dev/null
+++ b/files/letsencrypt-renew.service
@@ -0,0 +1,8 @@
+[Unit]
+Description=Renew certificate %i
+Documentation=man:certbot(1)
+
+[Service]
+Type=oneshot
+EnvironmentFile=/etc/letsencrypt/env/%i
+ExecStart=certbot --text --agree-tos --non-interactive certonly --rsa-key-size 4086 --cert-name '%i' -a $AUTHENTICATOR $DOMAINS --post-hook $POST_HOOK --quiet --keep-until-expiring
diff --git a/files/letsencrypt-renew.timer b/files/letsencrypt-renew.timer
new file mode 100644
index 0000000..f9c5d7a
--- /dev/null
+++ b/files/letsencrypt-renew.timer
@@ -0,0 +1,8 @@
+[Unit]
+Description=Renew certificate %i
+Documentation=man:certbot(1)
+
+[Timer]
+FixedRandomDelay=true
+OnCalendar=*-*-* 00:00
+RandomizedDelaySec=24h
diff --git a/manifests/cert.pp b/manifests/cert.pp
new file mode 100644
index 0000000..a8cc94e
--- /dev/null
+++ b/manifests/cert.pp
@@ -0,0 +1,39 @@
+# A single certificate
+# TODO possibly default cert_name to $::fqdn instead
+define letsencrypt::cert (
+ String $cert_name => $::name,
+ Enum['present', 'absent'] $ensure => 'present',
+ Boolean $include_self => true,
+) {
+
+ # TODO these env files are systemd specific
+ # TODO concat::fragment is clumsy, look at re-implementing the
+ # functionallity internally
+
+ concat { "${letsencrypt::config_dir}/env/${cert_name}":
+ ensure => present,
+ warn => true,
+ }
+
+ concat::fragment { "letsencrypt ${cert_name} preamble":
+ target => "${letsencrypt::config_dir}/env/${cert_name}",
+ order => '0',
+ content => @(EOF)
+ AUTHENTICATOR = ''
+ POST_HOOK = ''
+ DOMAINS =
+ |- EOF
+ }
+ concat::fragment { "letsencrypt ${cert_name} postamble":
+ target => "${letsencrypt::config_dir}/env/${cert_name}",
+ order => '99',
+ content => "\n\n",
+ }
+
+ if $include_self {
+ letsencrypt::domain { $cert_name: }
+ }
+
+ letsencrypt::renew { $cert_name:
+ }
+}
diff --git a/manifests/domain.pp b/manifests/domain.pp
new file mode 100644
index 0000000..cc9e2af
--- /dev/null
+++ b/manifests/domain.pp
@@ -0,0 +1,18 @@
+# A single domain belonging to a certificate
+# Example
+# letsencrypt::domain { 'www.example.com':
+# cert_name => 'example.com',
+# }
+define letsencrypt::domain (
+ String $domain_name => $name,
+ String $cert_name => $::fqdn,
+) {
+ ensure_resource('letsencrypt::cert', $cert_name, {
+ ensure => present,
+ })
+
+ concat::fragment { "letsencrypt ${cert_name} - ${domain_name}":
+ target => "${letsencrypt::config_dir}/env/${cert_name}",
+ content => " -d ${domain_name}",
+ }
+}
diff --git a/manifests/init.pp b/manifests/init.pp
new file mode 100644
index 0000000..0fedb85
--- /dev/null
+++ b/manifests/init.pp
@@ -0,0 +1,28 @@
+class letsencrypt (
+ String $email,
+ String $default_cert_name = $::fqdn,
+ Stdlib::Unixpath $config_dir = '/etc/letsencrypt',
+ Boolean $default_cert = true,
+ # TODO renewal provider here?
+) {
+
+ if $default_cert {
+ letsencrypt::cert { $default_cert_name:
+ ensure => present,
+ }
+ }
+
+
+ file { $config_dir:
+ ensure => directory,
+ }
+
+ file { "${config_dir}/cli.ini":
+ content = @("EOF")
+ email = $email
+ | EOF
+ }
+
+
+ include letsencrypt::renew::setup
+}
diff --git a/manifests/nginx.pp b/manifests/nginx.pp
new file mode 100644
index 0000000..82fcda4
--- /dev/null
+++ b/manifests/nginx.pp
@@ -0,0 +1,42 @@
+# Sets up nginx specific configuration, and provides access to
+# variables for enterpolating into nginx configurations
+# Usage:
+#
+# These use the default cert name
+#
+# nginx::resource::server { 'servername':
+# * => $letsescrypt::nginx::server_ssl
+# }
+# $letsencrypt::nginx::location_ssl
+class letsencrypt::nginx (
+ Boolean $manage_package: true,
+ String $certbot_plugin_package,
+) {
+
+ # TODO $cert_path
+ $cert_path = "/etc/letsencrypt/live/${certname}"
+
+ $server_ssl = if $ssl_configured {
+ {
+ ssl => true,
+ ssl_redirect => true,
+ ssl_cert => "${cert_path}/fullchain.pem",
+ ssl_key => "${cert_path}/privkey.pem",
+ }
+ } else {
+ {
+ ssl => false,
+ }
+ }
+
+ $location_ssl = if $ssl_configured {
+ {
+ ssl => true,
+ ssl_only => true,
+ }
+ } else {
+ {
+ ssl => false,
+ }
+ }
+}
diff --git a/manifests/renew.pp b/manifests/renew.pp
new file mode 100644
index 0000000..681a236
--- /dev/null
+++ b/manifests/renew.pp
@@ -0,0 +1,13 @@
+define letsencrypt::renew (
+ String $cert_name = $name,
+) {
+
+ # TODO this is systemd specific
+ # TODO ensure letsencrypt::renew::setup is included beforehand
+ service { "${letsencrypt::renew::systemd::service_name}@${cert_name}.timer":
+ ensure => 'running',
+ enable => true,
+ }
+
+}
+
diff --git a/manifests/renew/cron.pp b/manifests/renew/cron.pp
new file mode 100644
index 0000000..91d5483
--- /dev/null
+++ b/manifests/renew/cron.pp
@@ -0,0 +1,6 @@
+# Handles renewal certificates through CRON
+# private
+class letsencrypt::renew::cron (
+) {
+ fail("Not yet implemented")
+}
diff --git a/manifests/renew/setup.pp b/manifests/renew/setup.pp
new file mode 100644
index 0000000..360136c
--- /dev/null
+++ b/manifests/renew/setup.pp
@@ -0,0 +1,17 @@
+# Sets up timers for automatically renewing certificates
+# TODO
+# - make provider OS dependant
+# - is provider the correct name?
+# private
+class letsencrypt::renew::setup (
+ Enum['systemd', 'cron'] $provider = 'systemd',
+) {
+ file { [
+ '/etc/letsencrypt/env',
+ ]:
+ ensure => directory,
+ }
+
+ include "letsencrypt::renew::${provider}"
+}
+
diff --git a/manifests/renew/systemd.pp b/manifests/renew/systemd.pp
new file mode 100644
index 0000000..4b6f23e
--- /dev/null
+++ b/manifests/renew/systemd.pp
@@ -0,0 +1,16 @@
+# Handles renewal certificates through systemd timers
+# private
+class letsencrypt::renew::systemd (
+ String $service_name = 'letsencrypt-renew'
+ String $service_path = '/etc/systemd/system',
+) {
+
+
+ file { "${service_path}/${service_name}@.service":
+ source => "puppet:///modules/${module_name}/letsencrypt-renew.service",
+ }
+
+ file { "${service_path}/${service_name}@.timer":
+ source => "puppet:///modules/${module_name}/letsencrypt-renew.timer",
+ }
+}
diff --git a/metadata.json b/metadata.json
new file mode 100644
index 0000000..8ec88ca
--- /dev/null
+++ b/metadata.json
@@ -0,0 +1,35 @@
+{
+ "name": "HugoNikanor-letsencrypt",
+ "version": "0.1.0",
+ "author": "HugoNikanor",
+ "license": "Apache-2.0",
+ "tags": [
+ "letsencrypt",
+ "let's encrypt",
+ "certbot",
+ "acme"
+ ],
+ "operatingsystem_support": [
+ {
+ "operatingsystem": "Archlinux"
+ },
+ {
+ "operatingsystem": "CentOS",
+ "operatingsystemrelease": [
+ "7", "8"
+ ]
+ },
+ {
+ "operatingsystem": "Fedora",
+ "operatingsystemrelease": [
+ "36"
+ ]
+ },
+ {
+ "operatingsystem": "FreeBSD, Debian, Ubuntu, ..."
+ }
+ ],
+ "dependencies": {
+ "stdlib": {}
+ }
+}