add certificate metadata to db table
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
This commit is contained in:
@@ -983,7 +983,9 @@ CREATE TABLE IF NOT EXISTS `domain_ssl_settings` (
|
||||
`ssl_cert_chainfile` mediumtext,
|
||||
`ssl_csr_file` mediumtext,
|
||||
`ssl_fullchain_file` mediumtext,
|
||||
`expirationdate` datetime DEFAULT NULL,
|
||||
`validfromdate` datetime DEFAULT NULL,
|
||||
`validtodate` datetime DEFAULT NULL,
|
||||
`issuer` varchar(255) NOT NULL default '',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY (`domainid`)
|
||||
) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci;
|
||||
|
||||
@@ -429,5 +429,27 @@ if (Froxlor::isDatabaseVersion('202302030')) {
|
||||
}
|
||||
Update::lastStepStatus(0);
|
||||
|
||||
Update::showUpdateStep("Enhancing ssl data table");
|
||||
Database::query("ALTER TABLE `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` RENAME COLUMN `expirationdate` TO `validtodate`;");
|
||||
Database::query("ALTER TABLE `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` ADD `validfromdate` datetime DEFAULT NULL AFTER `ssl_fullchain_file`;");
|
||||
Database::query("ALTER TABLE `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` ADD `issuer` varchar(255) NOT NULL default '' AFTER `validtodate`;");
|
||||
Update::lastStepStatus(0);
|
||||
|
||||
Update::showUpdateStep("Filling new ssl data fields with existing certificate data");
|
||||
$crt_upd_stmt = Database::prepare("UPDATE `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` SET `validfromdate` = :validfromdate, `issuer` = :issuer WHERE `id` = :id");
|
||||
$crt_stmt = Database::prepare("SELECT * FROM `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "`");
|
||||
Database::pexecute($crt_stmt);
|
||||
while ($cert = $crt_stmt->fetch(\PDO::FETCH_ASSOC)) {
|
||||
$cert_content = openssl_x509_parse($cert['ssl_cert_file']);
|
||||
if (is_array($cert_content)) {
|
||||
$validfromdate = empty($cert_content['validFrom_time_t']) ? null : date("Y-m-d H:i:s", $cert_content['validFrom_time_t']);
|
||||
$issuer = $cert_content['issuer']['O'] ?? "";
|
||||
Database::pexecute($crt_upd_stmt, ['validfromdate' => $validfromdate, 'issuer' => $issuer, 'id' => $cert['id']]);
|
||||
}
|
||||
}
|
||||
// clear possible user customized columns
|
||||
Database::query("DELETE FROM `" . TABLE_PANEL_USERCOLUMNS . "` WHERE `section` = 'sslcertificates_list'");
|
||||
Update::lastStepStatus(0);
|
||||
|
||||
Froxlor::updateToDbVersion('202303150');
|
||||
}
|
||||
|
||||
@@ -127,7 +127,9 @@ class Certificates extends ApiCommand implements ResourceEntity
|
||||
}
|
||||
|
||||
$do_verify = true;
|
||||
$expirationdate = null;
|
||||
$validtodate = null;
|
||||
$validtodate = null;
|
||||
$issuer = "";
|
||||
// no cert-file given -> forget everything
|
||||
if ($ssl_cert_file == '') {
|
||||
$ssl_key_file = '';
|
||||
@@ -168,7 +170,10 @@ class Certificates extends ApiCommand implements ResourceEntity
|
||||
} else {
|
||||
Response::standardError('sslcertificateinvalidcert', '', true);
|
||||
}
|
||||
$expirationdate = empty($cert_content['validTo_time_t']) ? null : date("Y-m-d H:i:s", $cert_content['validTo_time_t']);
|
||||
// get data from certificate to store in the table
|
||||
$validfromdate = empty($cert_content['validFrom_time_t']) ? null : date("Y-m-d H:i:s", $cert_content['validFrom_time_t']);
|
||||
$validtodate = empty($cert_content['validTo_time_t']) ? null : date("Y-m-d H:i:s", $cert_content['validTo_time_t']);
|
||||
$issuer = $cert_content['issuer']['O'] ?? "";
|
||||
}
|
||||
|
||||
// Add/Update database entry
|
||||
@@ -183,7 +188,9 @@ class Certificates extends ApiCommand implements ResourceEntity
|
||||
`ssl_key_file` = :ssl_key_file,
|
||||
`ssl_ca_file` = :ssl_ca_file,
|
||||
`ssl_cert_chainfile` = :ssl_cert_chainfile,
|
||||
`expirationdate` = :expirationdate
|
||||
`validfromdate` = :validfromdate,
|
||||
`validtodate` = :validtodate,
|
||||
`issuer` = :issuer
|
||||
" . $qrywhere . " `domainid`= :domainid
|
||||
");
|
||||
$params = [
|
||||
@@ -191,7 +198,9 @@ class Certificates extends ApiCommand implements ResourceEntity
|
||||
"ssl_key_file" => $ssl_key_file,
|
||||
"ssl_ca_file" => $ssl_ca_file,
|
||||
"ssl_cert_chainfile" => $ssl_cert_chainfile,
|
||||
"expirationdate" => $expirationdate,
|
||||
"validfromdate" => $validfromdate,
|
||||
"validtodate" => $validtodate,
|
||||
"issuer" => $issuer,
|
||||
"domainid" => $domainid
|
||||
];
|
||||
Database::pexecute($stmt, $params, true, true);
|
||||
@@ -299,16 +308,12 @@ class Certificates extends ApiCommand implements ResourceEntity
|
||||
}
|
||||
|
||||
// Set data from certificate
|
||||
$cert['isvalid'] = false;
|
||||
$cert['san'] = null;
|
||||
$cert_data = openssl_x509_parse($cert['ssl_cert_file']);
|
||||
if ($cert_data) {
|
||||
$cert['validfromdate'] = date('Y-m-d H:i:s', $cert_data['validFrom_time_t']);
|
||||
$cert['validtodate'] = date('Y-m-d H:i:s', $cert_data['validTo_time_t']);
|
||||
$cert['isvalid'] = (bool)$cert_data['validTo_time_t'] > time();
|
||||
$cert['issuer'] = $cert_data['issuer']['O'] ?? null;
|
||||
}
|
||||
|
||||
// Set subject alt names from certificate
|
||||
$cert['san'] = null;
|
||||
if (isset($cert_data['extensions']['subjectAltName']) && !empty($cert_data['extensions']['subjectAltName'])) {
|
||||
$SANs = explode(",", $cert_data['extensions']['subjectAltName']);
|
||||
$SANs = array_map('trim', $SANs);
|
||||
@@ -319,7 +324,7 @@ class Certificates extends ApiCommand implements ResourceEntity
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
$result[] = $cert;
|
||||
}
|
||||
return $this->response([
|
||||
|
||||
@@ -76,7 +76,7 @@ final class ValidateAcmeWebroot extends CliCommand
|
||||
'domain' => Settings::Get('system.hostname')
|
||||
];
|
||||
}
|
||||
$upd_stmt = Database::prepare("UPDATE domain_ssl_settings SET expirationdate=NULL WHERE `domainid` = :did");
|
||||
$upd_stmt = Database::prepare("UPDATE domain_ssl_settings SET `validtodate`=NULL WHERE `domainid` = :did");
|
||||
$acmesh_dir = dirname(Settings::Get('system.acmeshpath'));
|
||||
$acmesh_challenge_dir = rtrim(FileDir::makeCorrectDir(Settings::Get('system.letsencryptchallengepath')), "/");
|
||||
$recommended = rtrim(FileDir::makeCorrectDir(Froxlor::getInstallDir()), "/");
|
||||
|
||||
@@ -179,7 +179,7 @@ class HttpConfigBase
|
||||
$froxlor_ssl_settings_stmt = Database::prepare("
|
||||
SELECT * FROM `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "`
|
||||
WHERE `domainid` = '0' AND
|
||||
(`expirationdate` < DATE_ADD(NOW(), INTERVAL 30 DAY) OR `expirationdate` IS NULL)
|
||||
(`validtodate` < DATE_ADD(NOW(), INTERVAL 30 DAY) OR `validtodate` IS NULL)
|
||||
");
|
||||
$froxlor_ssl = Database::pexecute_first($froxlor_ssl_settings_stmt);
|
||||
if ($froxlor_ssl && !empty($froxlor_ssl['ssl_cert_file'])) {
|
||||
|
||||
@@ -114,7 +114,9 @@ class AcmeSh extends FroxlorCron
|
||||
`ssl_cert_chainfile` = :chain,
|
||||
`ssl_csr_file` = :csr,
|
||||
`ssl_fullchain_file` = :fullchain,
|
||||
`expirationdate` = :expirationdate
|
||||
`validfromdate` = :validfromdate,
|
||||
`validtodate` = :validtodate,
|
||||
`issuer` = :issuer
|
||||
");
|
||||
|
||||
// prepare domain update sql
|
||||
@@ -136,7 +138,9 @@ class AcmeSh extends FroxlorCron
|
||||
'lepublickey' => Settings::Get('system.lepublickey'),
|
||||
'leregistered' => Settings::Get('system.leregistered'),
|
||||
'ssl_redirect' => Settings::Get('system.le_froxlor_redirect'),
|
||||
'expirationdate' => null,
|
||||
'validfromdate' => null,
|
||||
'validtodate' => null,
|
||||
'issuer' => "",
|
||||
'ssl_cert_file' => null,
|
||||
'ssl_key_file' => null,
|
||||
'ssl_ca_file' => null,
|
||||
@@ -171,7 +175,9 @@ class AcmeSh extends FroxlorCron
|
||||
'lepublickey' => Settings::Get('system.lepublickey'),
|
||||
'leregistered' => Settings::Get('system.leregistered'),
|
||||
'ssl_redirect' => Settings::Get('system.le_froxlor_redirect'),
|
||||
'expirationdate' => is_array($renew_froxlor) ? $renew_froxlor['expirationdate'] : date('Y-m-d H:i:s', 0),
|
||||
'validfromdate' => is_array($renew_froxlor) ? $renew_froxlor['validfromdate'] : date('Y-m-d H:i:s', 0),
|
||||
'validtodate' => is_array($renew_froxlor) ? $renew_froxlor['validtodate'] : date('Y-m-d H:i:s', 0),
|
||||
'issuer' => is_array($renew_froxlor) ? $renew_froxlor['issuer'] : "",
|
||||
'ssl_cert_file' => is_array($renew_froxlor) ? $renew_froxlor['ssl_cert_file'] : null,
|
||||
'ssl_key_file' => is_array($renew_froxlor) ? $renew_froxlor['ssl_key_file'] : null,
|
||||
'ssl_ca_file' => is_array($renew_froxlor) ? $renew_froxlor['ssl_ca_file'] : null,
|
||||
@@ -187,7 +193,7 @@ class AcmeSh extends FroxlorCron
|
||||
'loginname' => $domain['loginname'],
|
||||
'adminsession' => 0
|
||||
]);
|
||||
if (defined('CRON_IS_FORCED') || self::checkFsFilesAreNewer($domain['domain'], $domain['expirationdate'])) {
|
||||
if (defined('CRON_IS_FORCED') || self::checkFsFilesAreNewer($domain['domain'], $domain['validtodate'])) {
|
||||
self::certToDb($domain, $cronlog, []);
|
||||
$changedetected = 1;
|
||||
}
|
||||
@@ -279,7 +285,9 @@ EOC;
|
||||
SELECT
|
||||
domssl.`id`,
|
||||
domssl.`domainid`,
|
||||
domssl.`expirationdate`,
|
||||
domssl.`validfromdate`,
|
||||
domssl.`validtodate`,
|
||||
domssl.`issuer`,
|
||||
domssl.`ssl_cert_file`,
|
||||
domssl.`ssl_key_file`,
|
||||
domssl.`ssl_ca_file`,
|
||||
@@ -306,7 +314,7 @@ EOC;
|
||||
AND dom.`letsencrypt` = 1
|
||||
AND dom.`aliasdomain` IS NULL
|
||||
AND dom.`iswildcarddomain` = 0
|
||||
AND domssl.`expirationdate` IS NULL
|
||||
AND domssl.`validtodate` IS NULL
|
||||
");
|
||||
$customer_ssl = $certificates_stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
if ($customer_ssl) {
|
||||
@@ -330,7 +338,7 @@ EOC;
|
||||
");
|
||||
$froxlor_ssl = Database::pexecute_first($froxlor_ssl_settings_stmt);
|
||||
// also check for possible existing certificate
|
||||
if ($froxlor_ssl && self::checkFsFilesAreNewer(Settings::Get('system.hostname'), $froxlor_ssl['expirationdate'])) {
|
||||
if ($froxlor_ssl && self::checkFsFilesAreNewer(Settings::Get('system.hostname'), $froxlor_ssl['validtodate'])) {
|
||||
return $froxlor_ssl;
|
||||
}
|
||||
}
|
||||
@@ -346,7 +354,9 @@ EOC;
|
||||
SELECT
|
||||
domssl.`id`,
|
||||
domssl.`domainid`,
|
||||
domssl.`expirationdate`,
|
||||
domssl.`validfromdate`,
|
||||
domssl.`validtodate`,
|
||||
domssl.`issuer`,
|
||||
domssl.`ssl_cert_file`,
|
||||
domssl.`ssl_key_file`,
|
||||
dom.`domain`,
|
||||
@@ -370,7 +380,7 @@ EOC;
|
||||
if ($renew_certs) {
|
||||
if ($check) {
|
||||
foreach ($renew_certs as $cert) {
|
||||
if (self::checkFsFilesAreNewer($cert['domain'], $cert['expirationdate'])) {
|
||||
if (self::checkFsFilesAreNewer($cert['domain'], $cert['validtodate'])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -453,7 +463,7 @@ EOC;
|
||||
// Only issue let's encrypt certificate if no broken ssl_redirect is enabled
|
||||
if ($certrow['ssl_redirect'] != 2) {
|
||||
$do_force = false;
|
||||
if (!empty($certrow['ssl_cert_file']) && empty($certrow['expirationdate'])) {
|
||||
if (!empty($certrow['ssl_cert_file']) && empty($certrow['validtodate'])) {
|
||||
// domain changed (SAN or similar)
|
||||
$do_force = true;
|
||||
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Re-creating certificate for " . $certrow['domain']);
|
||||
@@ -594,7 +604,9 @@ EOC;
|
||||
'chain' => $return['chain'],
|
||||
'csr' => $return['csr'],
|
||||
'fullchain' => $return['fullchain'],
|
||||
'expirationdate' => date('Y-m-d H:i:s', $newcert['validTo_time_t'])
|
||||
'validfromdate' => date('Y-m-d H:i:s', $newcert['validFrom_time_t']),
|
||||
'validtodate' => date('Y-m-d H:i:s', $newcert['validTo_time_t']),
|
||||
'issuer' => $newcert['issuer']['O'] ?? ""
|
||||
]);
|
||||
|
||||
if ($certrow['ssl_redirect'] == 3) {
|
||||
|
||||
@@ -350,7 +350,7 @@ class Domain
|
||||
$upd_stmt = Database::prepare("UPDATE
|
||||
`" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "`
|
||||
SET
|
||||
`expirationdate` = null
|
||||
`validtodate` = null
|
||||
WHERE
|
||||
domainid = :domainid
|
||||
");
|
||||
|
||||
@@ -45,31 +45,27 @@ return [
|
||||
'callback' => [SSLCertificate::class, 'domainWithSan'],
|
||||
'searchable' => false,
|
||||
],
|
||||
'c.issuer' => [
|
||||
's.issuer' => [
|
||||
'label' => lng('ssl_certificates.issuer'),
|
||||
'field' => 'issuer',
|
||||
'searchable' => false,
|
||||
'sortable' => false,
|
||||
],
|
||||
'c.validfromdate' => [
|
||||
's.validfromdate' => [
|
||||
'label' => lng('ssl_certificates.valid_from'),
|
||||
'field' => 'validfromdate',
|
||||
'searchable' => false,
|
||||
'sortable' => false,
|
||||
],
|
||||
'c.validtodate' => [
|
||||
's.validtodate' => [
|
||||
'label' => lng('ssl_certificates.valid_until'),
|
||||
'field' => 'validtodate',
|
||||
'searchable' => false,
|
||||
'sortable' => false,
|
||||
],
|
||||
],
|
||||
'visible_columns' => Listing::getVisibleColumnsForListing('sslcertificates_list', [
|
||||
'd.domain',
|
||||
'c.domain',
|
||||
'c.issuer',
|
||||
'c.validfromdate',
|
||||
'c.validtodate',
|
||||
's.issuer',
|
||||
's.validfromdate',
|
||||
's.validtodate',
|
||||
]),
|
||||
'actions' => [
|
||||
'edit' => [
|
||||
|
||||
Reference in New Issue
Block a user