mirror of
https://github.com/netbirdio/plugins.git
synced 2026-05-22 18:44:07 -07:00
security/acme-client: add support for duplicate common names, fixes #3127
This commit is contained in:
@@ -8,8 +8,18 @@ WWW: https://github.com/acmesh-official/acme.sh
|
||||
Plugin Changelog
|
||||
================
|
||||
|
||||
4.0
|
||||
|
||||
NOTE: This is a new major release with backwards-incompatible changes.
|
||||
Downgrade to older releases is not supported. Be sure to create a
|
||||
full backup and include /var/etc/acme-client.
|
||||
|
||||
Changed:
|
||||
* use a dedicated acme.sh runtime directory for every cert (#3127)
|
||||
|
||||
Fixed:
|
||||
* fix sporadic command failure with gcloud DNS API (#3745)
|
||||
* fix errors when the same Common Name is used multiple times (#3127)
|
||||
|
||||
3.20
|
||||
|
||||
|
||||
@@ -224,6 +224,9 @@ class LeAccount extends LeCommon
|
||||
return false;
|
||||
}
|
||||
|
||||
// Fix account config
|
||||
$this->fixConfig();
|
||||
|
||||
// Update account status.
|
||||
LeUtils::log_error('account registration successful for ' . $this->config->name);
|
||||
$this->setStatus(200);
|
||||
@@ -233,4 +236,34 @@ class LeAccount extends LeCommon
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove CERT_HOME property from account config,
|
||||
* otherwise --cert-home will be ignored by acme.sh.
|
||||
*/
|
||||
public function fixConfig()
|
||||
{
|
||||
$account_conf_dir = self::ACME_BASE_ACCOUNT_DIR . '/' . (string)$this->config->id . '_' . $this->ca_compat;
|
||||
$account_conf_file = $account_conf_dir . '/account.conf';
|
||||
|
||||
if (is_dir($account_conf_dir)) {
|
||||
if (is_file($account_conf_file)) {
|
||||
// Parse config file and remove property
|
||||
$account_conf = parse_ini_file($account_conf_file);
|
||||
if (isset($account_conf['CERT_HOME'])) {
|
||||
unset($account_conf['CERT_HOME']);
|
||||
}
|
||||
|
||||
// Convert array back to ini file format
|
||||
$new_account_conf = array();
|
||||
foreach ($account_conf as $key => $value) {
|
||||
$new_account_conf[] = "${key}='${value}'";
|
||||
}
|
||||
|
||||
// Write changes back to file
|
||||
file_put_contents($account_conf_file, implode("\n", $new_account_conf) . "\n");
|
||||
chmod($account_conf_file, 0600);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
@@ -71,6 +71,7 @@ abstract class Base extends \OPNsense\AcmeClient\LeCommon
|
||||
|
||||
// Store acme filenames
|
||||
$this->acme_args[] = LeUtils::execSafe('--home %s', self::ACME_HOME_DIR);
|
||||
$this->acme_args[] = LeUtils::execSafe('--cert-home %s', sprintf(self::ACME_CERT_HOME_DIR, $this->cert_id));
|
||||
$this->acme_args[] = LeUtils::execSafe('--certpath %s', sprintf(self::ACME_CERT_FILE, $this->cert_id));
|
||||
$this->acme_args[] = LeUtils::execSafe('--keypath %s', sprintf(self::ACME_KEY_FILE, $this->cert_id));
|
||||
$this->acme_args[] = LeUtils::execSafe('--capath %s', sprintf(self::ACME_CHAIN_FILE, $this->cert_id));
|
||||
|
||||
+1
@@ -95,6 +95,7 @@ class LeCertificate extends LeCommon
|
||||
|
||||
// Store acme filenames
|
||||
$this->acme_args[] = LeUtils::execSafe('--home %s', self::ACME_HOME_DIR);
|
||||
$this->acme_args[] = LeUtils::execSafe('--cert-home %s', sprintf(self::ACME_CERT_HOME_DIR, $this->config->id));
|
||||
$this->acme_args[] = LeUtils::execSafe('--certpath %s', $this->cert_file);
|
||||
$this->acme_args[] = LeUtils::execSafe('--keypath %s', $this->cert_key_file);
|
||||
$this->acme_args[] = LeUtils::execSafe('--capath %s', $this->cert_chain_file);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2020-2021 Frank Wall
|
||||
* Copyright (C) 2020-2024 Frank Wall
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -53,6 +53,7 @@ abstract class LeCommon
|
||||
// Filenames for certs, configs, ...
|
||||
public const ACME_CERT_DIR = '/var/etc/acme-client/certs/%s/';
|
||||
public const ACME_CERT_FILE = '/var/etc/acme-client/certs/%s/cert.pem';
|
||||
public const ACME_CERT_HOME_DIR = '/var/etc/acme-client/cert-home/%s';
|
||||
public const ACME_CHAIN_FILE = '/var/etc/acme-client/certs/%s/chain.pem';
|
||||
public const ACME_CONFIG_DIR = '/var/etc/acme-client/configs/%s/';
|
||||
public const ACME_FULLCHAIN_FILE = '/var/etc/acme-client/certs/%s/fullchain.pem';
|
||||
|
||||
+1
@@ -94,6 +94,7 @@ abstract class Base extends \OPNsense\AcmeClient\LeCommon
|
||||
|
||||
// Store acme filenames
|
||||
$this->acme_args[] = LeUtils::execSafe('--home %s', self::ACME_HOME_DIR);
|
||||
$this->acme_args[] = LeUtils::execSafe('--cert-home %s', sprintf(self::ACME_CERT_HOME_DIR, $this->cert_id));
|
||||
$this->acme_args[] = LeUtils::execSafe('--certpath %s', sprintf(self::ACME_CERT_FILE, $this->cert_id));
|
||||
$this->acme_args[] = LeUtils::execSafe('--keypath %s', sprintf(self::ACME_KEY_FILE, $this->cert_id));
|
||||
$this->acme_args[] = LeUtils::execSafe('--capath %s', sprintf(self::ACME_CHAIN_FILE, $this->cert_id));
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<model>
|
||||
<mount>//OPNsense/AcmeClient</mount>
|
||||
<version>3.5.0</version>
|
||||
<version>4.0.0</version>
|
||||
<description>A secure ACME Client plugin</description>
|
||||
<items>
|
||||
<settings>
|
||||
|
||||
+1
-1
@@ -75,7 +75,7 @@ class M1_6_0 extends BaseModelMigration
|
||||
}
|
||||
|
||||
// Write changes back to file
|
||||
file_put_contents($account_file, implode("\r\n", $new_account_conf) . "\n");
|
||||
file_put_contents($account_file, implode("\n", $new_account_conf) . "\n");
|
||||
chmod($account_file, 0600);
|
||||
|
||||
// Finally, rename account directory
|
||||
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (C) 2024 Frank Wall
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace OPNsense\AcmeClient\Migrations;
|
||||
|
||||
use OPNsense\Base\BaseModelMigration;
|
||||
|
||||
class M4_0_0 extends BaseModelMigration
|
||||
{
|
||||
public function run($model)
|
||||
{
|
||||
$acme_account_dir = '/var/etc/acme-client/accounts/';
|
||||
$old_acme_home = '/var/etc/acme-client/home/';
|
||||
$new_acme_home = '/var/etc/acme-client/cert-home/';
|
||||
|
||||
// Remove CERT_HOME property from all account configs
|
||||
if (is_dir($acme_account_dir)) {
|
||||
$account_files = glob($acme_account_dir . '*/account.conf');
|
||||
foreach ($account_files as $account_file) {
|
||||
if (is_file($account_file)) {
|
||||
// Parse config file and remove property
|
||||
$account_conf = parse_ini_file($account_file);
|
||||
if (isset($account_conf['CERT_HOME'])) {
|
||||
unset($account_conf['CERT_HOME']);
|
||||
}
|
||||
|
||||
// Convert array back to ini file format
|
||||
$new_account_conf = array();
|
||||
foreach ($account_conf as $key => $value) {
|
||||
$new_account_conf[] = "${key}='${value}'";
|
||||
}
|
||||
|
||||
// Write changes back to file
|
||||
file_put_contents($account_file, implode("\n", $new_account_conf) . "\n");
|
||||
chmod($account_file, 0600);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create new acme home directory
|
||||
if (!is_dir($new_acme_home)) {
|
||||
mkdir($new_acme_home, 0750);
|
||||
}
|
||||
|
||||
// Migrate all certificates to new directory
|
||||
// OLD: /var/etc/acme-client/home/opnsense.example.com
|
||||
// NEW: /var/etc/acme-client/cert-home/659971be677b69.19708532/opnsense.example.com
|
||||
foreach ($model->getNodeByReference('certificates.certificate')->iterateItems() as $cert) {
|
||||
$cert_id = (string)$cert->id;
|
||||
$cert_name = (string)$cert->name;
|
||||
|
||||
$old_cert_home = $old_acme_home . $cert_name;
|
||||
$new_cert_home = $new_acme_home . $cert_id . '/' . $cert_name;
|
||||
$old_cert_home_ecc = $old_acme_home . $cert_name . '_ecc';
|
||||
$new_cert_home_ecc = $new_acme_home . $cert_id . '/' . $cert_name . '_ecc';
|
||||
$_parent_dir = $new_acme_home . $cert_id;
|
||||
|
||||
// Check if cert home directory exists
|
||||
// Certs that haven't been issued yet don't need to be migrated.
|
||||
if (is_dir($old_cert_home)) {
|
||||
// Create parent directory
|
||||
if (!is_dir($_parent_dir)) {
|
||||
mkdir($_parent_dir, 0750);
|
||||
}
|
||||
// Rename cert home directory
|
||||
rename($old_cert_home, $new_cert_home);
|
||||
}
|
||||
|
||||
// Migrate ECC certs
|
||||
if (is_dir($old_cert_home_ecc)) {
|
||||
// Create parent directory
|
||||
if (!is_dir($_parent_dir)) {
|
||||
mkdir($_parent_dir, 0750);
|
||||
}
|
||||
// Rename cert home directory
|
||||
rename($old_cert_home_ecc, $new_cert_home_ecc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
#!/bin/sh
|
||||
|
||||
ACME_BASE="/var/etc/acme-client"
|
||||
ACME_DIRS="/var/etc/acme-client/certs /var/etc/acme-client/keys /var/etc/acme-client/configs /var/etc/acme-client/challenges /var/etc/acme-client/home"
|
||||
ACME_DIRS="/var/etc/acme-client/certs /var/etc/acme-client/keys /var/etc/acme-client/configs /var/etc/acme-client/challenges /var/etc/acme-client/home /var/etc/acme-client/cert-home"
|
||||
|
||||
# Generate required directories and set owner/mode recursively.
|
||||
# Create required directories and set owner/mode recursively.
|
||||
for directory in ${ACME_DIRS}; do
|
||||
mkdir -p ${directory}
|
||||
chown -R root:wheel ${directory}
|
||||
|
||||
Reference in New Issue
Block a user