From ac4febaa9325d4a97339afb4e604f9c0bf932777 Mon Sep 17 00:00:00 2001 From: Frank Wall Date: Sat, 31 Jul 2021 14:30:57 +0200 Subject: [PATCH] security/acme-client: add support for new ACME CA's, closes #2361 --- security/acme-client/pkg-descr | 9 ++++ .../OPNsense/AcmeClient/forms/settings.xml | 6 +-- .../library/OPNsense/AcmeClient/LeAccount.php | 8 +-- .../OPNsense/AcmeClient/LeAutomation/Base.php | 6 +-- .../OPNsense/AcmeClient/LeCertificate.php | 6 +-- .../library/OPNsense/AcmeClient/LeCommon.php | 28 ++++++++-- .../OPNsense/AcmeClient/LeValidation/Base.php | 10 ++-- .../models/OPNsense/AcmeClient/AcmeClient.xml | 16 +++++- .../OPNsense/AcmeClient/Migrations/M3_0_0.php | 54 +++++++++++++++++++ .../views/OPNsense/AcmeClient/settings.volt | 4 +- 10 files changed, 120 insertions(+), 27 deletions(-) create mode 100644 security/acme-client/src/opnsense/mvc/app/models/OPNsense/AcmeClient/Migrations/M3_0_0.php diff --git a/security/acme-client/pkg-descr b/security/acme-client/pkg-descr index 0f08eea38..b6dc6e05e 100644 --- a/security/acme-client/pkg-descr +++ b/security/acme-client/pkg-descr @@ -8,6 +8,15 @@ WWW: https://github.com/acmesh-official/acme.sh Plugin Changelog ================ +3.0 + +Added: +* add support for new ACME CA's: buypass, buypass_test, sslcom, zerossl (#2361) + +Changed: +* rename "Let's Encrypt Environment" to "ACME CA" (#2361) +* preserve old LE accounts/certs by adding a compatibility layer (#2361) + 2.6 Added: diff --git a/security/acme-client/src/opnsense/mvc/app/controllers/OPNsense/AcmeClient/forms/settings.xml b/security/acme-client/src/opnsense/mvc/app/controllers/OPNsense/AcmeClient/forms/settings.xml index ad0247d9e..b72241e64 100644 --- a/security/acme-client/src/opnsense/mvc/app/controllers/OPNsense/AcmeClient/forms/settings.xml +++ b/security/acme-client/src/opnsense/mvc/app/controllers/OPNsense/AcmeClient/forms/settings.xml @@ -12,10 +12,10 @@ - acmeclient.settings.environment - + acmeclient.settings.ca + dropdown - relaxed rate limits.
NOTE:Certificates signed by the staging environment are NOT valid. You need to forcefully re-sign (or delete and re-create) them after switching from staging to production environment.
]]>
+ acme.sh documentation for a list of supported CAs.]]>
acmeclient.settings.haproxyIntegration diff --git a/security/acme-client/src/opnsense/mvc/app/library/OPNsense/AcmeClient/LeAccount.php b/security/acme-client/src/opnsense/mvc/app/library/OPNsense/AcmeClient/LeAccount.php index dc8f0d33f..5aa9e2ab2 100644 --- a/security/acme-client/src/opnsense/mvc/app/library/OPNsense/AcmeClient/LeAccount.php +++ b/security/acme-client/src/opnsense/mvc/app/library/OPNsense/AcmeClient/LeAccount.php @@ -1,7 +1,7 @@ setLoglevel(); - // Set Let's Encrypt environment - $this->setEnvironment(); + // Set ACME CA + $this->setCa(); // Store acme filenames $this->acme_args[] = LeUtils::execSafe('--home %s', self::ACME_HOME_DIR); @@ -66,7 +66,7 @@ class LeAccount extends LeCommon public function generateKey() { // Collect account information - $account_conf_dir = self::ACME_BASE_ACCOUNT_DIR . '/' . (string)$this->config->id . '_' . $this->environment; + $account_conf_dir = self::ACME_BASE_ACCOUNT_DIR . '/' . (string)$this->config->id . '_' . $this->ca_compat; $account_conf_file = $account_conf_dir . '/account.conf'; $account_key_file = $account_conf_dir . '/account.key'; $account_json_file = $account_conf_dir . '/account.json'; diff --git a/security/acme-client/src/opnsense/mvc/app/library/OPNsense/AcmeClient/LeAutomation/Base.php b/security/acme-client/src/opnsense/mvc/app/library/OPNsense/AcmeClient/LeAutomation/Base.php index b6a07a727..67ce269f2 100644 --- a/security/acme-client/src/opnsense/mvc/app/library/OPNsense/AcmeClient/LeAutomation/Base.php +++ b/security/acme-client/src/opnsense/mvc/app/library/OPNsense/AcmeClient/LeAutomation/Base.php @@ -1,7 +1,7 @@ * All rights reserved. @@ -63,8 +63,8 @@ abstract class Base extends \OPNsense\AcmeClient\LeCommon // Set log level $this->setLoglevel(); - // Set Let's Encrypt environment - $this->setEnvironment(); + // Set ACME CA + $this->setCa(); return true; } diff --git a/security/acme-client/src/opnsense/mvc/app/library/OPNsense/AcmeClient/LeCertificate.php b/security/acme-client/src/opnsense/mvc/app/library/OPNsense/AcmeClient/LeCertificate.php index 97b4d2364..bc84d49b3 100644 --- a/security/acme-client/src/opnsense/mvc/app/library/OPNsense/AcmeClient/LeCertificate.php +++ b/security/acme-client/src/opnsense/mvc/app/library/OPNsense/AcmeClient/LeCertificate.php @@ -74,8 +74,8 @@ class LeCertificate extends LeCommon // Set log level $this->setLoglevel(); - // Set Let's Encrypt environment - $this->setEnvironment(); + // Set ACME CA + $this->setCa(); // Handle special key types if ($this->config->keyLength == 'key_ec256' || $this->config->keyLength == 'key_ec384') { @@ -528,7 +528,7 @@ class LeCertificate extends LeCommon LeUtils::log('revoking certificate: ' . (string)$this->config->name); // Collect account information - $account_conf_dir = self::ACME_BASE_ACCOUNT_DIR . '/' . $this->account_id . '_' . $this->environment; + $account_conf_dir = self::ACME_BASE_ACCOUNT_DIR . '/' . $this->account_id . '_' . $this->ca_compat; $account_conf_file = $account_conf_dir . '/account.conf'; // Preparation to run acme client diff --git a/security/acme-client/src/opnsense/mvc/app/library/OPNsense/AcmeClient/LeCommon.php b/security/acme-client/src/opnsense/mvc/app/library/OPNsense/AcmeClient/LeCommon.php index 151445d0c..422a82508 100644 --- a/security/acme-client/src/opnsense/mvc/app/library/OPNsense/AcmeClient/LeCommon.php +++ b/security/acme-client/src/opnsense/mvc/app/library/OPNsense/AcmeClient/LeCommon.php @@ -83,7 +83,8 @@ abstract class LeCommon protected $cron; # Run from cron job protected $config; # AcmeClient config object protected $debug; # Debug logging (bool) - protected $environment; # Let's Encrypt environment (uses shortnames) + protected $ca; # ACME CA + protected $ca_compat; # ACME CA for compat with old LE CA names protected $force; # Force operation protected $model; # AcmeClient model object protected $uuid; # AcmeClient config object uuid @@ -136,12 +137,29 @@ abstract class LeCommon } /** - * set Let's Encrypt environment for acme.sh + * set ACME CA for acme.sh */ - public function setEnvironment() + public function setCa() { - $this->environment = (string)$this->model->getNodeByReference('settings.environment'); - $this->acme_args[] = $this->environment == 'stg' ? '--staging' : null; + $this->ca = (string)$this->model->getNodeByReference('settings.ca'); + $this->acme_args[] = LeUtils::execSafe('--server %s', $this->ca); + + // Evaluate how the CA should be represented in filenames. + // This is a compatibility layer. It ensures that old files that + // were generated for the Let's Encrypt Production/Staging CA + // can still be used. + switch ($this->ca) { + case 'letsencrypt': + $ca_compat = 'prod'; + break; + case 'letsencrypt_test': + $ca_compat = 'stg'; + break; + default: + $ca_compat = $this->ca; + break; + } + $this->ca_compat = $ca_compat; } /** diff --git a/security/acme-client/src/opnsense/mvc/app/library/OPNsense/AcmeClient/LeValidation/Base.php b/security/acme-client/src/opnsense/mvc/app/library/OPNsense/AcmeClient/LeValidation/Base.php index a69443228..0c2dcb317 100644 --- a/security/acme-client/src/opnsense/mvc/app/library/OPNsense/AcmeClient/LeValidation/Base.php +++ b/security/acme-client/src/opnsense/mvc/app/library/OPNsense/AcmeClient/LeValidation/Base.php @@ -1,7 +1,7 @@ * All rights reserved. @@ -73,8 +73,8 @@ abstract class Base extends \OPNsense\AcmeClient\LeCommon // Set log level $this->setLoglevel(); - // Set Let's Encrypt environment - $this->setEnvironment(); + // Set ACME CA + $this->setCa(); // Store acme hook switch ((string)$this->config->method) { @@ -141,8 +141,8 @@ abstract class Base extends \OPNsense\AcmeClient\LeCommon } } - // Use individual account config for each environment - $account_conf_dir = self::ACME_BASE_ACCOUNT_DIR . '/' . $this->account_id . '_' . $this->environment; + // Use individual account config for each CA + $account_conf_dir = self::ACME_BASE_ACCOUNT_DIR . '/' . $this->account_id . '_' . $this->ca_compat; $account_conf_file = $account_conf_dir . '/account.conf'; // Preparation to run acme client diff --git a/security/acme-client/src/opnsense/mvc/app/models/OPNsense/AcmeClient/AcmeClient.xml b/security/acme-client/src/opnsense/mvc/app/models/OPNsense/AcmeClient/AcmeClient.xml index 29a998e7b..a105ce598 100644 --- a/security/acme-client/src/opnsense/mvc/app/models/OPNsense/AcmeClient/AcmeClient.xml +++ b/security/acme-client/src/opnsense/mvc/app/models/OPNsense/AcmeClient/AcmeClient.xml @@ -1,6 +1,6 @@ //OPNsense/AcmeClient - 2.1.0 + 3.0.0 A secure Let's Encrypt plugin @@ -27,13 +27,25 @@ N - Y + N prod Production Environment [default] Staging Environment + + Y + + + Buypass + Buypass Test CA + Let's Encrypt [default] + Let's Encrypt Test CA + SSL.com + ZeroSSL + + 43580 1024 diff --git a/security/acme-client/src/opnsense/mvc/app/models/OPNsense/AcmeClient/Migrations/M3_0_0.php b/security/acme-client/src/opnsense/mvc/app/models/OPNsense/AcmeClient/Migrations/M3_0_0.php new file mode 100644 index 000000000..a2f0262e5 --- /dev/null +++ b/security/acme-client/src/opnsense/mvc/app/models/OPNsense/AcmeClient/Migrations/M3_0_0.php @@ -0,0 +1,54 @@ +settings->environment; + switch ($env) { + case 'prod': + $new_ca = 'letsencrypt'; + break; + case 'stg': + $new_ca = 'letsencrypt_test'; + break; + } + + // Set new CA + $model->settings->ca = $new_ca; + $model->settings->environment = null; // clear old value + } +} diff --git a/security/acme-client/src/opnsense/mvc/app/views/OPNsense/AcmeClient/settings.volt b/security/acme-client/src/opnsense/mvc/app/views/OPNsense/AcmeClient/settings.volt index 2d1b034e7..a77378f43 100644 --- a/security/acme-client/src/opnsense/mvc/app/views/OPNsense/AcmeClient/settings.volt +++ b/security/acme-client/src/opnsense/mvc/app/views/OPNsense/AcmeClient/settings.volt @@ -1,6 +1,6 @@ {# -Copyright (C) 2017-2019 Frank Wall +Copyright (C) 2017-2021 Frank Wall OPNsense® is Copyright © 2014-2015 by Deciso B.V. All rights reserved. @@ -247,7 +247,7 @@ POSSIBILITY OF SUCH DAMAGE.
- {{ lang._("Please read the official %sLet's Encrypt documentation%s before using this plugin. Otherwise you will easily hit its %srate limits%s and thus all your attempts to issue a certificate will fail.") | format('', '', '', '') }}{{ lang._("Please use Let's Encrypt's %sstaging servers%s when using this plugin for the first time or while testing a new challenge type. You will have to reissue your certificates when switching from staging to production servers to get valid certificates.") | format('', '') }} + {{ lang._("Please read the official %sLet's Encrypt documentation%s before using this plugin. It should give you a good overview about how the various ACME CAs work, so you do not hit their %srate limits%s and avoid common misconfigurations, which would let all your attempts to issue a certificate fail.") | format('', '', '', '') }}{{ lang._("Please use a %stest CA%s when using this plugin for the first time or while testing a new challenge type. Note that you will have to reissue your certificates when switching from a test to a production CA to get valid certificates.") | format('', '') }}
{{ lang._('Please use the %sissue tracker%s to report bugs or request new features.') | format('', '') }}