diff --git a/security/acme-client/Makefile b/security/acme-client/Makefile index 1f3eaf6ce..d9e7b6a6a 100644 --- a/security/acme-client/Makefile +++ b/security/acme-client/Makefile @@ -1,6 +1,5 @@ PLUGIN_NAME= acme-client -PLUGIN_VERSION= 3.19 -PLUGIN_REVISION= 1 +PLUGIN_VERSION= 3.20 PLUGIN_COMMENT= ACME Client PLUGIN_MAINTAINER= opnsense@moov.de PLUGIN_DEPENDS= acme.sh py${PLUGIN_PYTHON}-dns-lexicon diff --git a/security/acme-client/pkg-descr b/security/acme-client/pkg-descr index 11a6d4150..f9bc03d72 100644 --- a/security/acme-client/pkg-descr +++ b/security/acme-client/pkg-descr @@ -9,9 +9,17 @@ Plugin Changelog ================ 3.20 + Added: -* add Bunny DNS API -* add support for DNSExit +* add Bunny DNS API (#3715) +* add DNSExit DNS API (#3724) +* add World4You DNS API (#3722) + +Fixed: +* fix 2FA support in Synology automation (#3627) + +Removed: +* remove automation: Highwinds CDN (#3626) 3.19 diff --git a/security/acme-client/src/opnsense/mvc/app/controllers/OPNsense/AcmeClient/forms/dialogAction.xml b/security/acme-client/src/opnsense/mvc/app/controllers/OPNsense/AcmeClient/forms/dialogAction.xml index 905f1d49f..5fa9e700d 100644 --- a/security/acme-client/src/opnsense/mvc/app/controllers/OPNsense/AcmeClient/forms/dialogAction.xml +++ b/security/acme-client/src/opnsense/mvc/app/controllers/OPNsense/AcmeClient/forms/dialogAction.xml @@ -23,23 +23,6 @@ dropdown Pre-defined commands for this automation. - - - header - - - - action.highwinds_account_hash - - text - Account hash for Highwinds API. - - - action.highwinds_access_token - - text - Access token for Highwinds API. - header @@ -236,6 +219,12 @@ text If Synology DSM has OTP enabled, then the device ID has to be provided so that no OTP is required when running the automation. + + action.acme_synology_dsm_devicename + + text + If Synology DSM has OTP enabled, then the device name has to be provided so that no OTP is required when running the automation. + action.acme_synology_dsm_create 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 9eecd5f2e..382086eca 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 @@ -1656,4 +1656,19 @@ password + + + header + + + + validation.dns_world4you_username + + text + + + validation.dns_world4you_password + + password + diff --git a/security/acme-client/src/opnsense/mvc/app/library/OPNsense/AcmeClient/LeAutomation/AcmeSynologyDsm.php b/security/acme-client/src/opnsense/mvc/app/library/OPNsense/AcmeClient/LeAutomation/AcmeSynologyDsm.php index c1fb58a0a..3194f5745 100644 --- a/security/acme-client/src/opnsense/mvc/app/library/OPNsense/AcmeClient/LeAutomation/AcmeSynologyDsm.php +++ b/security/acme-client/src/opnsense/mvc/app/library/OPNsense/AcmeClient/LeAutomation/AcmeSynologyDsm.php @@ -48,7 +48,10 @@ class AcmeSynologyDsm extends Base implements LeAutomationInterface $this->acme_env['SYNO_Create'] = (string)$this->config->acme_synology_dsm_create; } if (!empty((string)$this->config->acme_synology_dsm_deviceid)) { - $this->acme_env['SYNO_DID'] = (string)$this->config->acme_synology_dsm_deviceid; + $this->acme_env['SYNO_Device_ID'] = (string)$this->config->acme_synology_dsm_deviceid; + } + if (!empty((string)$this->config->acme_synology_dsm_devicename)) { + $this->acme_env['SYNO_Device_Name'] = (string)$this->config->acme_synology_dsm_devicename; } $this->acme_args[] = '--deploy-hook synology_dsm'; return true; diff --git a/security/acme-client/src/opnsense/mvc/app/library/OPNsense/AcmeClient/LeAutomation/ConfigdUploadHighwinds.php b/security/acme-client/src/opnsense/mvc/app/library/OPNsense/AcmeClient/LeValidation/DnsWorld4you.php similarity index 75% rename from security/acme-client/src/opnsense/mvc/app/library/OPNsense/AcmeClient/LeAutomation/ConfigdUploadHighwinds.php rename to security/acme-client/src/opnsense/mvc/app/library/OPNsense/AcmeClient/LeValidation/DnsWorld4you.php index a17197815..192c8d63e 100644 --- a/security/acme-client/src/opnsense/mvc/app/library/OPNsense/AcmeClient/LeAutomation/ConfigdUploadHighwinds.php +++ b/security/acme-client/src/opnsense/mvc/app/library/OPNsense/AcmeClient/LeValidation/DnsWorld4you.php @@ -1,8 +1,7 @@ cert_id . ' ' . $this->config->id; - $this->command = $command; - return true; + $this->acme_env['WORLD4YOU_USERNAME'] = (string)$this->config->dns_world4you_username; + $this->acme_env['WORLD4YOU_PASSWORD'] = (string)$this->config->dns_world4you_password; } } 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 65adfcef4..b5339d938 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 - 3.4.0 + 3.5.0 A secure ACME Client plugin @@ -509,6 +509,7 @@ Variomedia.de Vscale Vultr + World4You Yandex PDD Zilore Zone.eu @@ -1172,6 +1173,12 @@ N + + N + + + N + @@ -1199,7 +1206,6 @@ Restart OPNsense Web UI Restart HAProxy (OPNsense plugin) Restart Nginx (OPNsense plugin) - Upload certificate to Highwinds CDN Upload certificate via SFTP Remote Command via SSH Upload certificate to FRITZ!Box router @@ -1212,16 +1218,6 @@ System or Plugin Command - - N - /^.{1,1024}$/u - Should be a string between 1 and 1024 characters. - - - N - /^.{1,1024}$/u - Should be a string between 1 and 1024 characters. - N /^.{1,255}$/u @@ -1384,6 +1380,11 @@ /^.{1,1024}$/u Should be a string between 1 and 1024 characters. + + N + /^.{1,1024}$/u + Should be a string between 1 and 1024 characters. + N /^.{1,1024}$/u diff --git a/security/acme-client/src/opnsense/scripts/OPNsense/AcmeClient/upload_highwinds.php b/security/acme-client/src/opnsense/scripts/OPNsense/AcmeClient/upload_highwinds.php deleted file mode 100755 index 2819626a4..000000000 --- a/security/acme-client/src/opnsense/scripts/OPNsense/AcmeClient/upload_highwinds.php +++ /dev/null @@ -1,254 +0,0 @@ -#!/usr/local/bin/php -object(); - if (isset($configObj->OPNsense->AcmeClient->certificates) && $configObj->OPNsense->AcmeClient->certificates->count() > 0) { - foreach ($configObj->OPNsense->AcmeClient->certificates->children() as $certObj) { - $cert_id = (string)$certObj->id; - $cert_name = (string)$certObj->name; - if ($cert_id == $acme_cert_id) { - if ($certObj->enabled == 0) { - log_error("AcmeClient: certificate ${cert_name} is disabled, ignoring upload request"); - return 'None'; - } - if (isset($certObj->certRefId)) { - $data = array(); - $data['name'] = $cert_name; - $data['refid'] = (string)$certObj->certRefId; - return $data; - } else { - log_error("AcmeClient: certificate ${cert_name} could not be found in trust storage, ignoring upload request"); - break; - } - } - } - return 'None'; - } -} - -function export_certificate($cert_refid) -{ - $configObj = Config::getInstance()->object(); - foreach ($configObj->cert as $cert) { - if ($cert_refid == (string)$cert->refid) { - $cert_content = str_replace("\n\n", "\n", str_replace("\r", "", base64_decode((string)$cert->crt))); - $key_content = str_replace("\n\n", "\n", str_replace("\r", "", base64_decode((string)$cert->prv))); - // check if a CA is linked - if (!empty((string)$cert->caref)) { - $cert = (array)$cert; - $ca = ca_chain($cert); - $ca_content = $ca; - } - $result = array(); - $result['cert'] = $cert_content; - $result['key'] = $key_content; - $result['ca'] = $ca_content; - return $result; - } - } - log_error("AcmeClient: cert with refid ${cert_refid} not found in trust storage"); - return 'None'; -} - -function upload_certificate($cert_name, $cert_refid, $acme_cert_id, $acme_automation_id) -{ - $modelObj = new OPNsense\AcmeClient\AcmeClient(); - $configObj = Config::getInstance()->object(); - if (isset($configObj->OPNsense->AcmeClient->actions) && $configObj->OPNsense->AcmeClient->actions->count() > 0) { - foreach ($configObj->OPNsense->AcmeClient->actions->children() as $automObj) { - $autom_id = (string)$automObj->id; - if ($autom_id == $acme_automation_id) { - if ($automObj->enabled == 0) { - log_error("AcmeClient: ignoring disabled upload job for cert ${cert_name}"); - return 'None'; - } - if (isset($automObj->highwinds_account_hash) && isset($automObj->highwinds_access_token)) { - $hw_account_hash = (string)$automObj->highwinds_account_hash; - $hw_access_token = (string)$automObj->highwinds_access_token; - $cert_data = export_certificate($cert_refid); - if ($cert_data !== 'None') { - $hw_result = hw_upload_certificate($hw_account_hash, $hw_access_token, $cert_name, $cert_data); - if ($hw_result !== 'None') { - return true; - } - } - } else { - log_error("AcmeClient: upload job for cert ${cert_name} is incomplete, missing Highwinds configuration"); - return 'None'; - } - } - } - return 'None'; - } -} - -function hw_list_certificates($account_hash, $access_token) -{ - global $HIGHWINDS_API_URL; - $curl = curl_init(); - curl_setopt_array($curl, array( - CURLOPT_URL => "${HIGHWINDS_API_URL}/${account_hash}/certificates", - CURLOPT_CUSTOMREQUEST => 'GET', - CURLOPT_RETURNTRANSFER => true, - CURLOPT_MAXREDIRS => 1, - CURLOPT_TIMEOUT => 10, - CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, - CURLOPT_HTTPHEADER => array( - "Authorization: Bearer ${access_token}", - "Content-Type: application/json", - "User-Agent: OPNsense Firewall", - "X-Application-Id: OPNsense Firewall" - ) - )); - $response = curl_exec($curl); - $err = curl_error($curl); - $info = curl_getinfo($curl); - curl_close($curl); - $http_code = $info['http_code']; - if ($http_code != 200 || $err) { - log_error("AcmeClient: failed to access Highwinds API, HTTP Code: ${http_code}, error ${err}"); - return 'None'; - } - return json_decode($response); -} - -function hw_get_certificate($account_hash, $access_token, $cert_name) -{ - $certificates = hw_list_certificates($account_hash, $access_token); - if ($certificates !== 'None') { - foreach ($certificates->list as $cert) { - if ($cert->commonName == $cert_name) { - return $cert; - } - } - } - return 'None'; -} - -function hw_upload_certificate($account_hash, $access_token, $cert_name, $cert_data) -{ - global $HIGHWINDS_API_URL; - // Check current status of certificate at Highwinds - $hw_cert = hw_get_certificate($account_hash, $access_token, $cert_name); - $hw_url = 'certificates'; - $hw_method = 'POST'; - if ($hw_cert == 'None') { - log_error("AcmeClient: cert for ${cert_name} not found in Highwinds API, starting upload..."); - } else { - log_error("AcmeClient: cert for ${cert_name} found in Highwinds API"); - $hw_method = 'PUT'; - - // Extract certificate details - $cert = openssl_x509_parse($cert_data['cert']); - $cert_sn = (string)$cert['serialNumber']; - $hw_cert_sn = (string)$hw_cert->certificateInformation->serialNumber; - $hw_cert_id = $hw_cert->id; - - // Compare local and remote certificates - if ($cert_sn == $hw_cert_sn) { - log_error("AcmeClient: cert ${cert_name} has same serial in Highwinds API, not updating (${cert_sn})"); - return 'None'; - } - log_error("AcmeClient: cert serial is different in Highwinds API, updating..."); - $hw_url = "${hw_url}/${hw_cert_id}"; - } - - // adjust data format for Highwinds API - $cert_post = json_encode(array('certificate' => $cert_data['cert'], 'key' => $cert_data['key'], 'caBundle' => $cert_data['ca'])); - - $curl = curl_init(); - curl_setopt_array($curl, array( - CURLOPT_URL => "${HIGHWINDS_API_URL}/${account_hash}/${hw_url}", - CURLOPT_CUSTOMREQUEST => $hw_method, - CURLOPT_POSTFIELDS => (string)$cert_post, - CURLOPT_RETURNTRANSFER => true, - CURLOPT_MAXREDIRS => 1, - CURLOPT_TIMEOUT => 10, - CURLOPT_SAFE_UPLOAD => true, - CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, - CURLOPT_HTTPHEADER => array( - "Authorization: Bearer ${access_token}", - "Content-Type: application/json", - "User-Agent: OPNsense Firewall", - "X-Application-Id: OPNsense Firewall", - "Expect:" - ) - )); - $response = curl_exec($curl); - $err = curl_error($curl); - $info = curl_getinfo($curl); - curl_close($curl); - $http_code = $info['http_code']; - if ($http_code != 200 || $err) { - log_error("AcmeClient: Failed to upload cert ${cert_name} to Highwinds API, HTTP Code: ${http_code}, error ${err}"); - return 'None'; - } - return json_decode($response); -} - -// Evaluate CLI arguments -$options = getopt("a:c:"); -if (!isset($options["a"]) or !isset($options["c"])) { - print "ERROR: not enough arguments\n"; - exit(1); -} -$acme_cert_id = $options["c"]; -$acme_automation_id = $options["a"]; - -// Search certificate in configuration -$cert_data = find_certificate($acme_cert_id); -if ($cert_data == 'None') { - log_error("AcmeClient: ignoring cert ID ${acme_cert_id}"); - exit(1); -} else { - // Upload certificate (if required) - $upload_result = upload_certificate($cert_data['name'], $cert_data['refid'], $acme_cert_id, $acme_automation_id); - if ($upload_result === 'None') { - log_error("AcmeClient: cert ID ${acme_cert_id} was neither uploaded nor updated"); - } else { - log_error("AcmeClient: cert ID ${acme_cert_id} was uploaded or updated"); - } -} -exit(0); 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 7c47bdf85..c58df0bef 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 @@ -91,12 +91,6 @@ parameters:%s type:script message:registering an account -[upload_highwinds] -command:/usr/local/opnsense/scripts/OPNsense/AcmeClient/upload_highwinds.php -parameters:-c %s -a %s -type:script -message:uploading a certificate to highwinds - [upload-sftp] command:/usr/local/opnsense/scripts/OPNsense/AcmeClient/upload_sftp.php parameters:--certificates=%s --automation-id=%s