From e96cb2b6b94418e175e96b44d9131f985d25ed6d Mon Sep 17 00:00:00 2001 From: Frank Wall Date: Tue, 10 Sep 2019 22:17:20 +0200 Subject: [PATCH 1/7] security/acme-client: check if BIND plugin is installed, refs #1491 --- .../AcmeClient/Api/SettingsController.php | 18 ++++++++++++++++++ .../AcmeClient/forms/dialogValidation.xml | 15 ++++++++++----- .../models/OPNsense/AcmeClient/AcmeClient.xml | 2 +- .../views/OPNsense/AcmeClient/validations.volt | 6 ++++++ .../scripts/OPNsense/AcmeClient/certhelper.php | 5 +++++ 5 files changed, 40 insertions(+), 6 deletions(-) diff --git a/security/acme-client/src/opnsense/mvc/app/controllers/OPNsense/AcmeClient/Api/SettingsController.php b/security/acme-client/src/opnsense/mvc/app/controllers/OPNsense/AcmeClient/Api/SettingsController.php index f78611844..307c98229 100644 --- a/security/acme-client/src/opnsense/mvc/app/controllers/OPNsense/AcmeClient/Api/SettingsController.php +++ b/security/acme-client/src/opnsense/mvc/app/controllers/OPNsense/AcmeClient/Api/SettingsController.php @@ -390,4 +390,22 @@ class SettingsController extends ApiMutableModelControllerBase return $result; } + + /** + * Check wether the BIND plugin is installed. + * @return array status action + */ + public function getBindPluginStatusAction() + { + $result = array("result" => "0"); + + $mdlAcme = $this->getModel(); + + // Check if the required plugin is installed + if ((string)$mdlAcme->isPluginInstalled('bind') == "1") { + $result['result'] = "1"; + } + + return $result; + } } diff --git a/security/acme-client/src/opnsense/mvc/app/controllers/OPNsense/AcmeClient/forms/dialogValidation.xml b/security/acme-client/src/opnsense/mvc/app/controllers/OPNsense/AcmeClient/forms/dialogValidation.xml index 727abe3a9..27a097063 100644 --- a/security/acme-client/src/opnsense/mvc/app/controllers/OPNsense/AcmeClient/forms/dialogValidation.xml +++ b/security/acme-client/src/opnsense/mvc/app/controllers/OPNsense/AcmeClient/forms/dialogValidation.xml @@ -717,10 +717,6 @@ header - - - info - validation.dns_opnsense_host @@ -730,7 +726,7 @@ validation.dns_opnsense_port text - + validation.dns_opnsense_key @@ -747,6 +743,15 @@ checkbox Uncheck this box if you have a valid certificate for your OPNsense interface. + + + header + + + + + info + header 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 f03201ef4..5733ea91d 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 @@ -381,7 +381,7 @@ netcup DNS API NS1.com API nsupdate (RFC 2136) - OPNsense Bind Plugin + OPNsense BIND Plugin OVH, kimsufi, soyoustart and runabove API PowerDNS.com API selectel.com / selectel.ru domain API diff --git a/security/acme-client/src/opnsense/mvc/app/views/OPNsense/AcmeClient/validations.volt b/security/acme-client/src/opnsense/mvc/app/views/OPNsense/AcmeClient/validations.volt index fe51b231e..cb94acec0 100644 --- a/security/acme-client/src/opnsense/mvc/app/views/OPNsense/AcmeClient/validations.volt +++ b/security/acme-client/src/opnsense/mvc/app/views/OPNsense/AcmeClient/validations.volt @@ -62,6 +62,12 @@ POSSIBILITY OF SUCH DAMAGE. $(".gcloud_plugin_warning").hide(); } }); + // Show a warning if the BIND plugin is missing. + ajaxCall(url="/api/acmeclient/settings/getBindPluginStatus", sendData={}, callback=function(data,status) { + if (data['result'] != 0) { + $(".bind_plugin_warning").hide(); + } + }); }); $("#validation\\.http_service").change(function(){ var service_id = 'table_http_' + $(this).val(); diff --git a/security/acme-client/src/opnsense/scripts/OPNsense/AcmeClient/certhelper.php b/security/acme-client/src/opnsense/scripts/OPNsense/AcmeClient/certhelper.php index dfba36492..1ae9639ae 100755 --- a/security/acme-client/src/opnsense/scripts/OPNsense/AcmeClient/certhelper.php +++ b/security/acme-client/src/opnsense/scripts/OPNsense/AcmeClient/certhelper.php @@ -829,6 +829,11 @@ function run_acme_validation($certObj, $valObj, $acctObj) $proc_env['NSUPDATE_SERVER'] = (string)$valObj->dns_nsupdate_server; break; case 'dns_opnsense': + # BIND plugin must be installed. + if ((string)$modelObj->isPluginInstalled('bind') != "1") { + log_error("AcmeClient: BIND plugin is NOT installed. Please install os-bind."); + return(1); + } $proc_env['OPNs_Host'] = (string)$valObj->dns_opnsense_host; $proc_env['OPNs_Port'] = (string)$valObj->dns_opnsense_port; $proc_env['OPNs_Key'] = (string)$valObj->dns_opnsense_key; From aea217b56af1ef37d5c7f070a4a4a7184d24e7a7 Mon Sep 17 00:00:00 2001 From: Frank Wall Date: Tue, 10 Sep 2019 22:17:35 +0200 Subject: [PATCH 2/7] security/acme-client: style fixes, refs #1491 --- .../OPNsense/AcmeClient/dns_opnsense.sh | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/security/acme-client/src/opnsense/scripts/OPNsense/AcmeClient/dns_opnsense.sh b/security/acme-client/src/opnsense/scripts/OPNsense/AcmeClient/dns_opnsense.sh index 1c1f463d6..80b5f40e8 100755 --- a/security/acme-client/src/opnsense/scripts/OPNsense/AcmeClient/dns_opnsense.sh +++ b/security/acme-client/src/opnsense/scripts/OPNsense/AcmeClient/dns_opnsense.sh @@ -1,6 +1,6 @@ #!/usr/bin/env sh -#OPNsense Bind API +#OPNsense Bind API #https://docs.opnsense.org/development/api.html # #OPNs_Host="opnsense.example.com" @@ -61,21 +61,19 @@ set_record() { # Update if _opns_rest "POST" "/record/setRecord/${_uuid}" "$_record_string"; then _return_str="$response" - else return 1 fi - + else #create if _opns_rest "POST" "/record/addRecord" "$_record_string"; then _return_str="$response" - else return 1 fi - fi + if echo "$_return_str" | _egrep_o "\"result\":\"saved\"" >/dev/null then _opns_rest "POST" "/service/reconfigure" "{}" @@ -85,7 +83,6 @@ set_record() { return 1 fi - return 0 } @@ -117,14 +114,12 @@ rm_record() { else _err "Error delteting record $fulldomain" return 1 - fi + fi else _info "Record not found, nothing to remove" - fi return 0 - } #################### Private functions below ################################## @@ -199,7 +194,6 @@ _build_record_string() { } _existingchallenge() { - if _opns_rest "GET" "/record/searchRecord"; then _record_response="$response" else @@ -218,8 +212,6 @@ _existingchallenge() { } _opns_check_auth() { - - OPNs_Host="${OPNs_Host:-$(_readaccountconf_mutable OPNs_Host)}" OPNs_Port="${OPNs_Port:-$(_readaccountconf_mutable OPNs_Port)}" OPNs_Key="${OPNs_Key:-$(_readaccountconf_mutable OPNs_Key)}" @@ -267,5 +259,4 @@ _opns_check_auth() { return 1 fi return 0 - -} \ No newline at end of file +} From 4a1c11b314f6652633a6137418e5c26bcfd8b620 Mon Sep 17 00:00:00 2001 From: Frank Wall Date: Tue, 10 Sep 2019 22:18:04 +0200 Subject: [PATCH 3/7] security/acme-client: bump version --- security/acme-client/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/security/acme-client/Makefile b/security/acme-client/Makefile index 3b0807121..f61c388d5 100644 --- a/security/acme-client/Makefile +++ b/security/acme-client/Makefile @@ -1,5 +1,5 @@ PLUGIN_NAME= acme-client -PLUGIN_VERSION= 1.25 +PLUGIN_VERSION= 1.26 PLUGIN_COMMENT= Let's Encrypt client PLUGIN_MAINTAINER= opnsense@moov.de PLUGIN_DEPENDS= acme.sh From 174e536effac7a2fa6cc3607a87b2dbb7a6bed09 Mon Sep 17 00:00:00 2001 From: Jesai Langenbach Date: Wed, 4 Sep 2019 14:32:01 +0200 Subject: [PATCH 4/7] Detect DNS alias domain --- .../scripts/OPNsense/AcmeClient/certhelper.php | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/security/acme-client/src/opnsense/scripts/OPNsense/AcmeClient/certhelper.php b/security/acme-client/src/opnsense/scripts/OPNsense/AcmeClient/certhelper.php index 1ae9639ae..d8c96b5df 100755 --- a/security/acme-client/src/opnsense/scripts/OPNsense/AcmeClient/certhelper.php +++ b/security/acme-client/src/opnsense/scripts/OPNsense/AcmeClient/certhelper.php @@ -892,10 +892,25 @@ function run_acme_validation($certObj, $valObj, $acctObj) // Prepare altNames $altnames = ""; + + //Find Alias for main domain + // https://github.com/Neilpang/acme.sh/wiki/DNS-alias-mode + $name = "_acme-challenge." . ltrim((string)$certObj->name, '*.'); + if ($dst = dns_get_record($name, DNS_CNAME )) { + $altnames .= "--domain-alias " .$dst[0]['target'] . " "; + } + if (!empty((string)$certObj->altNames)) { $_altnames = explode(",", (string)$certObj->altNames); foreach (explode(",", (string)$certObj->altNames) as $altname) { $altnames .= "--domain ${altname} "; + //Find Alias + // https://github.com/Neilpang/acme.sh/wiki/DNS-alias-mode + $name="_acme-challenge." . ltrim($altname, '*.'); + + if ($dst = dns_get_record($name, DNS_CNAME )) { + $altnames .= "--domain-alias " .$dst[0]['target'] . " "; + } } } From 4fd4c77bdf3ac399b6a69c20ee56e63a5e662e37 Mon Sep 17 00:00:00 2001 From: Frank Wall Date: Tue, 10 Sep 2019 23:34:07 +0200 Subject: [PATCH 5/7] security/acme-client: make DNS alias mode configurable, refs #1301 --- .../AcmeClient/forms/dialogCertificate.xml | 28 ++++++++++++ .../models/OPNsense/AcmeClient/AcmeClient.xml | 16 +++++++ .../OPNsense/AcmeClient/certificates.volt | 10 +++++ .../OPNsense/AcmeClient/certhelper.php | 43 +++++++++++++++---- 4 files changed, 88 insertions(+), 9 deletions(-) diff --git a/security/acme-client/src/opnsense/mvc/app/controllers/OPNsense/AcmeClient/forms/dialogCertificate.xml b/security/acme-client/src/opnsense/mvc/app/controllers/OPNsense/AcmeClient/forms/dialogCertificate.xml index 4e6292142..4673272f2 100644 --- a/security/acme-client/src/opnsense/mvc/app/controllers/OPNsense/AcmeClient/forms/dialogCertificate.xml +++ b/security/acme-client/src/opnsense/mvc/app/controllers/OPNsense/AcmeClient/forms/dialogCertificate.xml @@ -70,4 +70,32 @@ text + + certificate.aliasmode + + dropdown + + + + + header + + + + certificate.domainalias + + text + acme.sh documentation for further information.]]> + + + + header + + + + certificate.challengealias + + text + acme.sh documentation for further information.]]> + 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 5733ea91d..1afa9d4f8 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 @@ -243,6 +243,22 @@ 60 60 + + Y + none + + Not using DNS alias mode + Automatic Mode (uses DNS lookups) + Domain alias mode + Challenge alias mode + + + + N + + + N + N diff --git a/security/acme-client/src/opnsense/mvc/app/views/OPNsense/AcmeClient/certificates.volt b/security/acme-client/src/opnsense/mvc/app/views/OPNsense/AcmeClient/certificates.volt index 0c7c34e1a..c2e206bd6 100644 --- a/security/acme-client/src/opnsense/mvc/app/views/OPNsense/AcmeClient/certificates.volt +++ b/security/acme-client/src/opnsense/mvc/app/views/OPNsense/AcmeClient/certificates.volt @@ -379,6 +379,16 @@ POSSIBILITY OF SUCH DAMAGE. }); + // Hide options that are irrelevant in this context. + $('#DialogCertificate').on('shown.bs.modal', function (e) { + $("#certificate\\.aliasmode").change(function(){ + $(".aliasmode").hide(); + $(".aliasmode_"+$(this).val()).show(); + }); + $("#certificate\\.aliasmode").change(); + }) + + /*********************************************************************** * Commands **********************************************************************/ diff --git a/security/acme-client/src/opnsense/scripts/OPNsense/AcmeClient/certhelper.php b/security/acme-client/src/opnsense/scripts/OPNsense/AcmeClient/certhelper.php index d8c96b5df..0524053e8 100755 --- a/security/acme-client/src/opnsense/scripts/OPNsense/AcmeClient/certhelper.php +++ b/security/acme-client/src/opnsense/scripts/OPNsense/AcmeClient/certhelper.php @@ -893,24 +893,49 @@ function run_acme_validation($certObj, $valObj, $acctObj) // Prepare altNames $altnames = ""; - //Find Alias for main domain + // Main domain: Use DNS alias mode for domain validation? // https://github.com/Neilpang/acme.sh/wiki/DNS-alias-mode - $name = "_acme-challenge." . ltrim((string)$certObj->name, '*.'); - if ($dst = dns_get_record($name, DNS_CNAME )) { - $altnames .= "--domain-alias " .$dst[0]['target'] . " "; + if ($val_method == 'dns01') { + switch ((string)$valObj->aliasmode) { + case 'automatic': + $name = "_acme-challenge." . ltrim((string)$certObj->name, '*.'); + if ($dst = dns_get_record($name, DNS_CNAME )) { + $altnames .= "--domain-alias " . $dst[0]['target'] . " "; + } + break; + case 'domain': + $altnames .= "--domain-alias " . (string)$certObj->domainalias . " "; + break; + case 'challenge': + $altnames .= "--challenge-alias " . (string)$certObj->challengealias . " "; + break; + } } if (!empty((string)$certObj->altNames)) { $_altnames = explode(",", (string)$certObj->altNames); foreach (explode(",", (string)$certObj->altNames) as $altname) { $altnames .= "--domain ${altname} "; - //Find Alias - // https://github.com/Neilpang/acme.sh/wiki/DNS-alias-mode - $name="_acme-challenge." . ltrim($altname, '*.'); - if ($dst = dns_get_record($name, DNS_CNAME )) { - $altnames .= "--domain-alias " .$dst[0]['target'] . " "; + // altNames: Use DNS alias mode for domain validation? + // https://github.com/Neilpang/acme.sh/wiki/DNS-alias-mode + if ($val_method == 'dns01') { + switch ((string)$valObj->aliasmode) { + case 'automatic': + $name = "_acme-challenge." . ltrim($altname, '*.'); + if ($dst = dns_get_record($name, DNS_CNAME )) { + $altnames .= "--domain-alias " . $dst[0]['target'] . " "; + } + break; + case 'domain': + $altnames .= "--domain-alias " . (string)$certObj->domainalias . " "; + break; + case 'challenge': + $altnames .= "--challenge-alias " . (string)$certObj->challengealias . " "; + break; + } } + } } From bd26e6e22a755bc6645f37d8c8a29fa16704f0d6 Mon Sep 17 00:00:00 2001 From: Frank Wall Date: Tue, 10 Sep 2019 23:45:43 +0200 Subject: [PATCH 6/7] security/acme-client: run setup more often, refs #1491 This is required to ensure that the symlink for dns_opsense.sh exists before running acme.sh. Otherwise acme.sh would complain that it cannot find the API hook. --- .../opnsense/service/conf/actions.d/actions_acmeclient.conf | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/security/acme-client/src/opnsense/service/conf/actions.d/actions_acmeclient.conf b/security/acme-client/src/opnsense/service/conf/actions.d/actions_acmeclient.conf index 7c53c1cfd..1a335c89f 100644 --- a/security/acme-client/src/opnsense/service/conf/actions.d/actions_acmeclient.conf +++ b/security/acme-client/src/opnsense/service/conf/actions.d/actions_acmeclient.conf @@ -42,7 +42,7 @@ message:testing acme_http_challenge configuration ########################################## [sign-cert] -command:/usr/sbin/daemon -f /usr/local/opnsense/scripts/OPNsense/AcmeClient/certhelper.php -F -a sign -c +command:/usr/local/opnsense/scripts/OPNsense/AcmeClient/setup.sh; /usr/sbin/daemon -f /usr/local/opnsense/scripts/OPNsense/AcmeClient/certhelper.php -F -a sign -c parameters:%s type:script message:signing or renewing a certificate @@ -66,13 +66,13 @@ type:script message:removing a certificate private key [sign-all-certs] -command:/usr/sbin/daemon -f /usr/local/opnsense/scripts/OPNsense/AcmeClient/certhelper.php -a sign -A +command:/usr/local/opnsense/scripts/OPNsense/AcmeClient/setup.sh; /usr/sbin/daemon -f /usr/local/opnsense/scripts/OPNsense/AcmeClient/certhelper.php -a sign -A parameters: type:script message:signing or renewing a certificate [cron-auto-renew] -command:/usr/sbin/daemon -f /usr/local/opnsense/scripts/OPNsense/AcmeClient/certhelper.php -a sign -A -C +command:/usr/local/opnsense/scripts/OPNsense/AcmeClient/setup.sh; /usr/sbin/daemon -f /usr/local/opnsense/scripts/OPNsense/AcmeClient/certhelper.php -a sign -A -C parameters: type:script message:cronjob running to sign or renew certificates From 44ee1732f4ec5f70262b75fa6dd0ecd08ff026eb Mon Sep 17 00:00:00 2001 From: Frank Wall Date: Wed, 11 Sep 2019 00:07:16 +0200 Subject: [PATCH 7/7] security/acme-client: add headers for certificate options --- .../AcmeClient/forms/dialogCertificate.xml | 40 +++++++++++++------ 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/security/acme-client/src/opnsense/mvc/app/controllers/OPNsense/AcmeClient/forms/dialogCertificate.xml b/security/acme-client/src/opnsense/mvc/app/controllers/OPNsense/AcmeClient/forms/dialogCertificate.xml index 4673272f2..8ec38a0c7 100644 --- a/security/acme-client/src/opnsense/mvc/app/controllers/OPNsense/AcmeClient/forms/dialogCertificate.xml +++ b/security/acme-client/src/opnsense/mvc/app/controllers/OPNsense/AcmeClient/forms/dialogCertificate.xml @@ -1,4 +1,8 @@
+ + + header + certificate.enabled @@ -26,6 +30,10 @@
NOTE:You need to forcefully re-issue the certificate if you change "Alt Names" after the certificate was signed by the Let's Encrypt Authority! Use the "issue" button in the Commands column in this case.
]]>
Enter FQDN here. Finish with TAB.
+ + + header + certificate.account @@ -38,6 +46,22 @@ dropdown + + certificate.autoRenewal + + checkbox + Enable automatic renewal for this certificate to prevent expiration. + + + certificate.renewInterval + + text + + + + + header + certificate.keyLength @@ -50,6 +74,10 @@ checkbox Generate and add OCSP Must Staple extension to the certificate. + + + header + certificate.restartActions @@ -58,18 +86,6 @@ true Choose the automations that should be run after certificate creation and renewal. Basically every application requires a quick restart to reload the updated certificate. If you don't configure an automation, the in-memory certificate may expire and cause security warnings and other issues. - - certificate.autoRenewal - - checkbox - Enable automatic renewal for this certificate to prevent expiration. - - - certificate.renewInterval - - text - - certificate.aliasmode