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 edc5de0c4..f78611844 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
@@ -372,4 +372,22 @@ class SettingsController extends ApiMutableModelControllerBase
return $result;
}
+
+ /**
+ * Check wether the Google Cloud plugin is installed.
+ * @return array status action
+ */
+ public function getGcloudPluginStatusAction()
+ {
+ $result = array("result" => "0");
+
+ $mdlAcme = $this->getModel();
+
+ // Check if the required plugin is installed
+ if ((string)$mdlAcme->isPluginInstalled('google-cloud-sdk') == "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 77078e9e9..7da76ac8d 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
@@ -401,6 +401,30 @@
text
+
+
+ header
+
+
+
+
+ info
+
+
+ validation.dns_gcloud_key
+
+ textbox
+ Provide a service account key in JSON format for your Google Cloud account.
+
+
+
+ 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 91046d2d4..e8cdb2877 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
@@ -363,6 +363,7 @@
FreeDNS API
Gandi LiveDNS API
GoDaddy.com API
+ Google Cloud DNS API
GratisDNS.dk
hosting.de API
Hurricane Electric
@@ -518,6 +519,9 @@
N
+
+ N
+
N
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 7c5d762d8..fe51b231e 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
@@ -56,6 +56,12 @@ POSSIBILITY OF SUCH DAMAGE.
if ($("#validation\\.method").val() == 'dns01') {
$("."+service_id).show();
}
+ // Show a warning if the Google Cloud SDK plugin is missing.
+ ajaxCall(url="/api/acmeclient/settings/getGcloudPluginStatus", sendData={}, callback=function(data,status) {
+ if (data['result'] != 0) {
+ $(".gcloud_plugin_warning").hide();
+ }
+ });
});
$("#validation\\.http_service").change(function(){
var service_id = 'table_http_' + $(this).val();
@@ -72,6 +78,7 @@ POSSIBILITY OF SUCH DAMAGE.
$("#validation\\.http_service").change();
});
$("#validation\\.method").change();
+
})
});
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 d1a1bd6ee..328900d0a 100755
--- a/security/acme-client/src/opnsense/scripts/OPNsense/AcmeClient/certhelper.php
+++ b/security/acme-client/src/opnsense/scripts/OPNsense/AcmeClient/certhelper.php
@@ -417,6 +417,7 @@ function run_acme_validation($certObj, $valObj, $acctObj)
// Required to run pre-defined commands.
$backend = new Backend();
+ $modelObj = new OPNsense\AcmeClient\AcmeClient;
// Collect account information
$account_conf_dir = "/var/etc/acme-client/accounts/" . $acctObj->id;
@@ -567,6 +568,7 @@ function run_acme_validation($certObj, $valObj, $acctObj)
// Prepare DNS-01 hooks
if ($val_method == 'dns01') {
// Some common stuff
+ $val_id = preg_replace("/[^a-zA-Z0-9]/", "", (string)$valObj->id);
$secret_key_filename = "${configdir}/secret.key";
$acme_args[] = '--dnssleep ' . $valObj->dns_sleep;
@@ -655,6 +657,42 @@ function run_acme_validation($certObj, $valObj, $acctObj)
case 'dns_gandi_livedns':
$proc_env['GANDI_LIVEDNS_KEY'] = (string)$valObj->dns_gandi_livedns_key;
break;
+ case 'dns_gcloud':
+ # Google Cloud SDK must be installed.
+ if ((string)$modelObj->isPluginInstalled('google-cloud-sdk') != "1") {
+ log_error("AcmeClient: Google Cloud SDK plugin is NOT installed. Please install os-google-cloud-sdk.");
+ return(1);
+ }
+ # We need a valid Google Cloud JSON key.
+ if (!empty((string)$valObj->dns_gcloud_key)) {
+ # Extract the gcloud project from the key data.
+ $_gcloud_data = json_decode((string)$valObj->dns_gcloud_key);
+ $gcloud_project = $_gcloud_data->project_id;
+ $gcloud_account = $_gcloud_data->client_email;
+ if (empty($gcloud_project)) {
+ log_error("AcmeClient: unable to extract project name from Google Cloud DNS JSON key");
+ return(1);
+ } else {
+ log_error("AcmeClient: Google Cloud DNS project name: ${gcloud_project}");
+ }
+ } else {
+ log_error("AcmeClient: no key for Google Cloud DNS was specified");
+ return(1);
+ }
+ # Preparations for gcloud CLI.
+ $gcloud_config = "acme-${val_id}";
+ $gcloud_key_file = "/tmp/acme_" . (string)$valObj->dns_service . "_${val_id}.json";
+ file_put_contents($gcloud_key_file, (string)$valObj->dns_gcloud_key);
+ chmod($gcloud_key_file, 0600);
+ $proc_env['CLOUDSDK_ACTIVE_CONFIG_NAME'] = $gcloud_config;
+ $proc_env['CLOUDSDK_CORE_PROJECT'] = $gcloud_project;
+ # Ensure that a working gcloud config exists.
+ run_shell_command("/usr/local/bin/gcloud config configurations create ${gcloud_config}",$proc_env);
+ run_shell_command("/usr/local/bin/gcloud config configurations activate ${gcloud_config}",$proc_env);
+ run_shell_command("/usr/local/bin/gcloud auth activate-service-account --key-file=${gcloud_key_file}",$proc_env);
+ run_shell_command("/usr/local/bin/gcloud config set account ${gcloud_account}",$proc_env);
+ run_shell_command("/usr/local/bin/gcloud config set project ${gcloud_project}",$proc_env);
+ break;
case 'dns_gd':
$proc_env['GD_Key'] = (string)$valObj->dns_gd_key;
$proc_env['GD_Secret'] = (string)$valObj->dns_gd_secret;
@@ -1244,6 +1282,32 @@ function dump_postponed_updates()
}
}
+function run_shell_command($proc_cmd, $proc_env = array())
+{
+ $proc_desc = array( // descriptor array for proc_open()
+ 0 => array("pipe", "r"), // stdin
+ 1 => array("pipe", "w"), // stdout
+ 2 => array("pipe", "w") // stderr
+ );
+ $proc_pipes = array();
+ $proc = proc_open($proc_cmd, $proc_desc, $proc_pipes, null, $proc_env);
+
+ // Make sure the resource could be setup properly
+ if (is_resource($proc)) {
+ // Close all pipes
+ fclose($proc_pipes[0]);
+ fclose($proc_pipes[1]);
+ fclose($proc_pipes[2]);
+ // Get exit code
+ $result = proc_close($proc);
+ log_error(sprintf("AcmeClient: The shell command '%s' returned exit code '%d'", $proc_cmd, $result));
+ return($result);
+ } else {
+ log_error(sprintf("AcmeClient: Unable to prepare shell command '%s'",$proc_cmd));
+ return(1);
+ }
+}
+
// taken from certs.inc
function local_cert_get_subject_array($str_crt, $decode = true)
{