From 9ea1d88273221d90ddf91b4cf39c2343636cdd3c Mon Sep 17 00:00:00 2001 From: NeatNerdPrime Date: Mon, 9 Sep 2024 22:29:02 +0200 Subject: [PATCH] Feature: Certbot plugin Apache It was strange to me that the module mentions the apache plugin, but has no installation of said plugin anywhere. In the meantime i used standalone and did an ugly cron pre/post combo But this should address the issue properly * adds the plugin class 'apache' * adds python2 package names for old EL7 distro's * includes green tests. --- REFERENCE.md | 28 +++++++++++++ data/os/CentOS/7.yaml | 1 + data/os/RedHat/7.yaml | 1 + manifests/certonly.pp | 11 +++++ manifests/plugin/apache.pp | 16 ++++++++ .../letsencrypt_plugin_apache_spec.rb | 14 +++++++ spec/classes/plugin/apache_spec.rb | 41 +++++++++++++++++++ spec/defines/letsencrypt_certonly_spec.rb | 20 +++++++++ 8 files changed, 132 insertions(+) create mode 100644 manifests/plugin/apache.pp create mode 100644 spec/acceptance/letsencrypt_plugin_apache_spec.rb create mode 100644 spec/classes/plugin/apache_spec.rb diff --git a/REFERENCE.md b/REFERENCE.md index 3936bc75..6cdaba49 100644 --- a/REFERENCE.md +++ b/REFERENCE.md @@ -9,6 +9,7 @@ #### Public Classes * [`letsencrypt`](#letsencrypt): Install and configure Certbot, the LetsEncrypt client +* [`letsencrypt::plugin::apache`](#letsencrypt--plugin--apache): install and configure the Let's Encrypt apache plugin * [`letsencrypt::plugin::dns_cloudflare`](#letsencrypt--plugin--dns_cloudflare): Installs and configures the dns-cloudflare plugin * [`letsencrypt::plugin::dns_rfc2136`](#letsencrypt--plugin--dns_rfc2136): Installs and configures the dns-rfc2136 plugin * [`letsencrypt::plugin::dns_route53`](#letsencrypt--plugin--dns_route53): Installs and configures the dns-route53 plugin @@ -338,6 +339,33 @@ certificate. Two environmental variables are supplied by certbot: Default value: `[]` +### `letsencrypt::plugin::apache` + +install and configure the Let's Encrypt apache plugin + +#### Parameters + +The following parameters are available in the `letsencrypt::plugin::apache` class: + +* [`manage_package`](#-letsencrypt--plugin--apache--manage_package) +* [`package_name`](#-letsencrypt--plugin--apache--package_name) + +##### `manage_package` + +Data type: `Boolean` + +Manage the plugin package. + +Default value: `true` + +##### `package_name` + +Data type: `String[1]` + +The name of the package to install when $manage_package is true. + +Default value: `'python3-certbot-apache'` + ### `letsencrypt::plugin::dns_cloudflare` This class installs and configures the Let's Encrypt dns-cloudflare plugin. diff --git a/data/os/CentOS/7.yaml b/data/os/CentOS/7.yaml index 3920067f..65f6516b 100644 --- a/data/os/CentOS/7.yaml +++ b/data/os/CentOS/7.yaml @@ -3,3 +3,4 @@ letsencrypt::plugin::dns_rfc2136::package_name: 'python2-certbot-dns-rfc2136' letsencrypt::plugin::dns_route53::package_name: 'python2-certbot-dns-route53' letsencrypt::plugin::dns_cloudflare::package_name: 'python2-certbot-dns-cloudflare' letsencrypt::plugin::nginx::package_name: 'python2-certbot-nginx' +letsencrypt::plugin::apache::package_name: 'python2-certbot-apache' diff --git a/data/os/RedHat/7.yaml b/data/os/RedHat/7.yaml index 3920067f..65f6516b 100644 --- a/data/os/RedHat/7.yaml +++ b/data/os/RedHat/7.yaml @@ -3,3 +3,4 @@ letsencrypt::plugin::dns_rfc2136::package_name: 'python2-certbot-dns-rfc2136' letsencrypt::plugin::dns_route53::package_name: 'python2-certbot-dns-route53' letsencrypt::plugin::dns_cloudflare::package_name: 'python2-certbot-dns-cloudflare' letsencrypt::plugin::nginx::package_name: 'python2-certbot-nginx' +letsencrypt::plugin::apache::package_name: 'python2-certbot-apache' diff --git a/manifests/certonly.pp b/manifests/certonly.pp index b04f94b5..f8148ad2 100644 --- a/manifests/certonly.pp +++ b/manifests/certonly.pp @@ -216,6 +216,17 @@ } } + 'apache': { + require letsencrypt::plugin::apache + + if $ensure == 'present' { + $_domains = join($domains, '\' -d \'') + $plugin_args = "--cert-name '${cert_name}' -d '${_domains}'" + } else { + $plugin_args = "--cert-name '${cert_name}'" + } + } + default: { if $ensure == 'present' { $_domains = join($domains, '\' -d \'') diff --git a/manifests/plugin/apache.pp b/manifests/plugin/apache.pp new file mode 100644 index 00000000..500dbc9d --- /dev/null +++ b/manifests/plugin/apache.pp @@ -0,0 +1,16 @@ +# @summary install and configure the Let's Encrypt apache plugin +# +# @param manage_package Manage the plugin package. +# @param package_name The name of the package to install when $manage_package is true. +class letsencrypt::plugin::apache ( + Boolean $manage_package = true, + String[1] $package_name = 'python3-certbot-apache', +) { + include letsencrypt + + if $manage_package { + package { $package_name: + ensure => $letsencrypt::package_ensure, + } + } +} diff --git a/spec/acceptance/letsencrypt_plugin_apache_spec.rb b/spec/acceptance/letsencrypt_plugin_apache_spec.rb new file mode 100644 index 00000000..f3e6732e --- /dev/null +++ b/spec/acceptance/letsencrypt_plugin_apache_spec.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +require 'spec_helper_acceptance' + +describe 'letsencrypt::plugin::apache' do + it_behaves_like 'an idempotent resource' do + let(:manifest) do + <<-PUPPET + include letsencrypt + include letsencrypt::plugin::apache + PUPPET + end + end +end diff --git a/spec/classes/plugin/apache_spec.rb b/spec/classes/plugin/apache_spec.rb new file mode 100644 index 00000000..a9b739e0 --- /dev/null +++ b/spec/classes/plugin/apache_spec.rb @@ -0,0 +1,41 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'letsencrypt::plugin::apache' do + on_supported_os.each do |os, os_facts| + context "on #{os}" do + let(:facts) { os_facts } + let(:params) { {} } + let(:pre_condition) do + <<-PUPPET + class { 'letsencrypt': + email => 'foo@example.com', + } + PUPPET + end + let(:package_name) do + if facts[:os]['family'] == 'RedHat' && facts[:os]['release']['major'] == '7' + 'python2-certbot-apache' + else + 'python3-certbot-apache' + end + end + + context 'with default parameters' do + it { is_expected.to compile.with_all_deps } + + it 'installs the certbot apache plugin' do + is_expected.to contain_class('letsencrypt::plugin::apache') + is_expected.to contain_package(package_name).with_ensure('installed') + end + + describe 'with manage_package => false' do + let(:params) { super().merge(manage_package: false, package_name: 'apache-package') } + + it { is_expected.not_to contain_package('apache-package') } + end + end + end + end +end diff --git a/spec/defines/letsencrypt_certonly_spec.rb b/spec/defines/letsencrypt_certonly_spec.rb index 26c5ee77..761a5833 100644 --- a/spec/defines/letsencrypt_certonly_spec.rb +++ b/spec/defines/letsencrypt_certonly_spec.rb @@ -185,6 +185,26 @@ class { 'letsencrypt::plugin::nginx': it { is_expected.to contain_exec('letsencrypt certonly foo.example.com').with_command "letsencrypt --text --agree-tos --non-interactive certonly --rsa-key-size 4096 -a nginx --cert-name 'foo.example.com' -d 'foo.example.com'" } end + context 'with apache plugin' do + let(:title) { 'foo.example.com' } + let(:params) { { plugin: 'apache', letsencrypt_command: 'letsencrypt' } } + let(:pre_condition) do + <<-PUPPET + class { 'letsencrypt': + email => 'foo@example.com', + config_dir => '/etc/letsencrypt', + } + class { 'letsencrypt::plugin::apache': + package_name => 'irrelevant', + } + PUPPET + end + + it { is_expected.to compile.with_all_deps } + it { is_expected.to contain_class('letsencrypt::plugin::apache') } + it { is_expected.to contain_exec('letsencrypt certonly foo.example.com').with_command "letsencrypt --text --agree-tos --non-interactive certonly --rsa-key-size 4096 -a apache --cert-name 'foo.example.com' -d 'foo.example.com'" } + end + context 'with dns-cloudflare plugin' do let(:title) { 'foo.example.com' } let(:params) { { plugin: 'dns-cloudflare', letsencrypt_command: 'letsencrypt' } }