mirror of
https://github.com/netbirdio/plugins.git
synced 2026-05-22 18:44:07 -07:00
Merge pull request #1318 from fraenki/acme_124
security/acme-client: release 1.24
This commit is contained in:
+18
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
+56
-1
@@ -282,7 +282,17 @@
|
||||
<help>Note that this is the account token not the user token.</help>
|
||||
</field>
|
||||
<field>
|
||||
<label>Domain-Offensive</label>
|
||||
<label>Domain-Offensive LetsEncrypt</label>
|
||||
<type>header</type>
|
||||
<style>table_dns table_dns_doapi</style>
|
||||
</field>
|
||||
<field>
|
||||
<id>validation.dns_doapi_token</id>
|
||||
<label>API Token</label>
|
||||
<type>text</type>
|
||||
</field>
|
||||
<field>
|
||||
<label>Domain-Offensive Resellerinterface</label>
|
||||
<type>header</type>
|
||||
<style>table_dns table_dns_do</style>
|
||||
</field>
|
||||
@@ -391,6 +401,30 @@
|
||||
<label>Key</label>
|
||||
<type>text</type>
|
||||
</field>
|
||||
<field>
|
||||
<label>Google Cloud DNS</label>
|
||||
<type>header</type>
|
||||
<style>table_dns table_dns_gcloud</style>
|
||||
</field>
|
||||
<field>
|
||||
<label><![CDATA[NOTE: First you must create a <a target="_blank" href="https://cloud.google.com/iam/docs/creating-managing-service-account-keys">service account key</a> using the GCP Console and enable the <a target="_blank" href="https://console.developers.google.com/apis/api/cloudresourcemanager.googleapis.com/overview">Cloud Resource Manager API</a>. Afterwards paste the full JSON key in the textbox below.]]></label>
|
||||
<type>info</type>
|
||||
</field>
|
||||
<field>
|
||||
<id>validation.dns_gcloud_key</id>
|
||||
<label>JSON Key</label>
|
||||
<type>textbox</type>
|
||||
<help>Provide a service account key in JSON format for your Google Cloud account.</help>
|
||||
</field>
|
||||
<field>
|
||||
<label>Action required</label>
|
||||
<type>header</type>
|
||||
<style>table_dns table_dns_gcloud gcloud_plugin_warning</style>
|
||||
</field>
|
||||
<field>
|
||||
<label><![CDATA[Please manually install the plugin "os-google-cloud-sdk" to enable support for Google Cloud DNS.]]></label>
|
||||
<type>info</type>
|
||||
</field>
|
||||
<field>
|
||||
<label>GoDaddy</label>
|
||||
<type>header</type>
|
||||
@@ -586,6 +620,27 @@
|
||||
<label>Secret</label>
|
||||
<type>text</type>
|
||||
</field>
|
||||
<field>
|
||||
<label>Namecheap</label>
|
||||
<type>header</type>
|
||||
<style>table_dns table_dns_namecheap</style>
|
||||
</field>
|
||||
<field>
|
||||
<id>validation.dns_namecheap_user</id>
|
||||
<label>User</label>
|
||||
<type>text</type>
|
||||
</field>
|
||||
<field>
|
||||
<id>validation.dns_namecheap_api</id>
|
||||
<label>API Key</label>
|
||||
<type>text</type>
|
||||
</field>
|
||||
<field>
|
||||
<id>validation.dns_namecheap_sourceip</id>
|
||||
<label>Source IP</label>
|
||||
<type>text</type>
|
||||
<advanced>true</advanced>
|
||||
</field>
|
||||
<field>
|
||||
<label>Name.com</label>
|
||||
<type>header</type>
|
||||
|
||||
+20
-2
@@ -342,7 +342,7 @@
|
||||
<dns_acmedns>ACME DNS API</dns_acmedns>
|
||||
<dns_ad>Alwaysdata.com API</dns_ad>
|
||||
<dns_ali>aliyun.com API</dns_ali>
|
||||
<dns_autodns>autoDNS (InternetX) API</dns_autodns>
|
||||
<dns_autodns>AutoDNS (InterNetX) API</dns_autodns>
|
||||
<dns_aws>AWS Route 53</dns_aws>
|
||||
<dns_azure>Azure DNS API</dns_azure>
|
||||
<dns_cf>CloudFlare.com API</dns_cf>
|
||||
@@ -354,7 +354,8 @@
|
||||
<dns_dnsimple>DNSimple API</dns_dnsimple>
|
||||
<dns_me>DNSMadeEasy.com API</dns_me>
|
||||
<dns_dp>DNSPod.cn API</dns_dp>
|
||||
<dns_do>Domain-Offensive/Resellerinterface/Domainrobot API</dns_do>
|
||||
<dns_doapi>Domain-Offensive LetsEncrypt API</dns_doapi>
|
||||
<dns_do>Domain-Offensive Resellerinterface/Domainrobot API</dns_do>
|
||||
<dns_dreamhost>DreamHost DNS API</dns_dreamhost>
|
||||
<dns_duckdns>DuckDNS API</dns_duckdns>
|
||||
<dns_dyn>Dyn Managed DNS API</dns_dyn>
|
||||
@@ -362,6 +363,7 @@
|
||||
<dns_freedns>FreeDNS API</dns_freedns>
|
||||
<dns_gandi_livedns>Gandi LiveDNS API</dns_gandi_livedns>
|
||||
<dns_gd>GoDaddy.com API</dns_gd>
|
||||
<dns_gcloud>Google Cloud DNS API</dns_gcloud>
|
||||
<dns_gdnsdk>GratisDNS.dk</dns_gdnsdk>
|
||||
<dns_hostingde>hosting.de API</dns_hostingde>
|
||||
<dns_he>Hurricane Electric</dns_he>
|
||||
@@ -374,6 +376,7 @@
|
||||
<dns_linode>Linode API</dns_linode>
|
||||
<dns_lua>LuaDNS.com API</dns_lua>
|
||||
<dns_namecom>Name.com API</dns_namecom>
|
||||
<dns_namecheap>Namecheap API</dns_namecheap>
|
||||
<dns_namesilo>Namesilo.com API</dns_namesilo>
|
||||
<dns_nsone>NS1.com API</dns_nsone>
|
||||
<dns_nsupdate>nsupdate (RFC 2136)</dns_nsupdate>
|
||||
@@ -471,6 +474,9 @@
|
||||
<dns_dnsimple_token type="TextField">
|
||||
<Required>N</Required>
|
||||
</dns_dnsimple_token>
|
||||
<dns_doapi_token type="TextField">
|
||||
<Required>N</Required>
|
||||
</dns_doapi_token>
|
||||
<dns_do_pid type="TextField">
|
||||
<Required>N</Required>
|
||||
</dns_do_pid>
|
||||
@@ -513,6 +519,9 @@
|
||||
<dns_gandi_livedns_key type="TextField">
|
||||
<Required>N</Required>
|
||||
</dns_gandi_livedns_key>
|
||||
<dns_gcloud_key type="TextField">
|
||||
<Required>N</Required>
|
||||
</dns_gcloud_key>
|
||||
<dns_gd_key type="TextField">
|
||||
<Required>N</Required>
|
||||
</dns_gd_key>
|
||||
@@ -597,6 +606,15 @@
|
||||
<dns_me_secret type="TextField">
|
||||
<Required>N</Required>
|
||||
</dns_me_secret>
|
||||
<dns_namecheap_user type="TextField">
|
||||
<Required>N</Required>
|
||||
</dns_namecheap_user>
|
||||
<dns_namecheap_api type="TextField">
|
||||
<Required>N</Required>
|
||||
</dns_namecheap_api>
|
||||
<dns_namecheap_sourceip type="TextField">
|
||||
<Required>N</Required>
|
||||
</dns_namecheap_sourceip>
|
||||
<dns_namecom_user type="TextField">
|
||||
<Required>N</Required>
|
||||
</dns_namecom_user>
|
||||
|
||||
@@ -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();
|
||||
|
||||
})
|
||||
});
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2017-2018 Frank Wall
|
||||
* Copyright (C) 2017-2019 Frank Wall
|
||||
* Copyright (C) 2015 Deciso B.V.
|
||||
* Copyright (C) 2010 Jim Pingle <jimp@pfsense.org>
|
||||
* Copyright (C) 2008 Shrew Soft Inc. <mgrooms@shrew.net>
|
||||
@@ -206,7 +206,7 @@ function cert_action_validator($opt_cert_id)
|
||||
// Start acme client to issue or renew certificate
|
||||
$val_result = run_acme_validation($certObj, $valObj, $acctObj);
|
||||
if (!$val_result) {
|
||||
log_error("AcmeClient: issued/renewed certificate: " . (string)$certObj->name);
|
||||
log_error("AcmeClient: successfully issued/renewed certificate: " . (string)$certObj->name);
|
||||
// Import certificate to Cert Manager
|
||||
if (!import_certificate($certObj, $modelObj)) {
|
||||
// Prepare certificate for automation
|
||||
@@ -371,6 +371,7 @@ function run_acme_account_registration($acctObj, $certObj, $modelObj)
|
||||
// serialize to config and save
|
||||
$modelObj->serializeToConfig();
|
||||
Config::getInstance()->save();
|
||||
Config::getInstance()->forceReload();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -405,6 +406,7 @@ function run_acme_account_registration($acctObj, $certObj, $modelObj)
|
||||
// serialize to config and save
|
||||
$modelObj->serializeToConfig();
|
||||
Config::getInstance()->save();
|
||||
Config::getInstance()->forceReload();
|
||||
}
|
||||
|
||||
return;
|
||||
@@ -417,6 +419,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 +570,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;
|
||||
|
||||
@@ -626,6 +630,9 @@ function run_acme_validation($certObj, $valObj, $acctObj)
|
||||
$proc_env['DO_PID'] = (string)$valObj->dns_do_pid;
|
||||
$proc_env['DO_PW'] = (string)$valObj->dns_do_password;
|
||||
break;
|
||||
case 'dns_doapi':
|
||||
$proc_env['DO_LETOKEN'] = (string)$valObj->dns_doapi_token;
|
||||
break;
|
||||
case 'dns_dp':
|
||||
$proc_env['DP_Id'] = (string)$valObj->dns_dp_id;
|
||||
$proc_env['DP_Key'] = (string)$valObj->dns_dp_key;
|
||||
@@ -652,6 +659,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;
|
||||
@@ -709,6 +752,16 @@ function run_acme_validation($certObj, $valObj, $acctObj)
|
||||
$proc_env['ME_Key'] = (string)$valObj->dns_me_key;
|
||||
$proc_env['ME_Secret'] = (string)$valObj->dns_me_secret;
|
||||
break;
|
||||
case 'dns_namecheap':
|
||||
$proc_env['NAMECHEAP_USERNAME'] = (string)$valObj->dns_namecheap_user;
|
||||
$proc_env['NAMECHEAP_API_KEY'] = (string)$valObj->dns_namecheap_api;
|
||||
if (!empty((string)$valObj->dns_namecheap_sourceip)) {
|
||||
$proc_env['NAMECHEAP_SOURCEIP'] = (string)$valObj->dns_namecheap_sourceip;
|
||||
} else {
|
||||
// Use a public service to get our source IP for Namecheap API
|
||||
$proc_env['NAMECHEAP_SOURCEIP'] = 'https://ifconfig.co/ip';
|
||||
}
|
||||
break;
|
||||
case 'dns_namecom':
|
||||
$proc_env['Namecom_Username'] = (string)$valObj->dns_namecom_user;
|
||||
$proc_env['Namecom_Token'] = (string)$valObj->dns_namecom_token;
|
||||
@@ -1069,6 +1122,7 @@ function import_certificate($certObj, $modelObj)
|
||||
// if node was found, serialize to config and save
|
||||
$modelObj->serializeToConfig();
|
||||
Config::getInstance()->save();
|
||||
Config::getInstance()->forceReload();
|
||||
} else {
|
||||
log_error("AcmeClient: unable to update LE certificate object");
|
||||
return(1);
|
||||
@@ -1203,20 +1257,62 @@ function log_cert_acme_status($certObj, $modelObj, $statusCode)
|
||||
function dump_postponed_updates()
|
||||
{
|
||||
global $postponed_updates;
|
||||
|
||||
$status_descr = [
|
||||
100 => 'unknown',
|
||||
200 => 'OK',
|
||||
250 => 'cert revoked',
|
||||
300 => 'configuration error',
|
||||
400 => 'validation failed',
|
||||
500 => 'internal error',
|
||||
];
|
||||
|
||||
$modelObj = new OPNsense\AcmeClient\AcmeClient;
|
||||
|
||||
foreach ($postponed_updates as $pupdate) {
|
||||
$node = $modelObj->getNodeByReference('certificates.certificate.' . $pupdate['uuid']);
|
||||
$_statusCode = $pupdate['statusCode'];
|
||||
$_uuid = $pupdate['uuid'];
|
||||
$node = $modelObj->getNodeByReference('certificates.certificate.'.$_uuid);
|
||||
if ($node != null) {
|
||||
$node->statusCode = $pupdate['statusCode'];
|
||||
log_error("AcmeClient: storing status '" . $status_descr[$_statusCode] . "' for cert " . (string)$node->name);
|
||||
$node->statusCode = $_statusCode;
|
||||
$node->statusLastUpdate = $pupdate['statusLastUpdate'];
|
||||
// serialize to config and save
|
||||
$modelObj->serializeToConfig();
|
||||
Config::getInstance()->save();
|
||||
Config::getInstance()->forceReload();
|
||||
} else {
|
||||
log_error(sprintf("AcmeClient: failed to store status '%s' for cert %s: node not found",$status_descr[$_statusCode],$_uuid));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user