Jump to content
Froxlor Forum
  • 0

How to trigger renewal of certificate?


peterpan
 Share

Question

Hi,

I have a domain equipped with a certificate from LE. The cert is valid another 2 months. Now I added a domain as an alias of the existing domain, but the certificate isn't updated to have the new domain as its SAN.

How do I trigger getting a new and updated certificate? Should I delete the existing one?

Thanks for helping out.

 

Peter

Link to comment
Share on other sites

Recommended Posts

  • 0

This doesn't seem to work. I deleted it from the SSL certificates page, but with the next cronjob, it came back exactly as before, with same domains, same creation date and same expiration date.

I even deleted the certificate file from disk in /etc/ssl/froxlor-custom/, but that didn't make any difference as well.

Link to comment
Share on other sites

  • 0

This is what I see:

[information] Adding SAN entry: xxx.yyy
[information] Updated Let's Encrypt certificate for xxx.zzz
[information] Let's Encrypt certificates have been updated

The date of the certificate on disk has changed to the current time, but not its size, and not its content. openssl x509 -in xxx.crt -text -noout does not show the new domains.

Link to comment
Share on other sites

  • 0
2 hours ago, peterpan said:

This is what I see:

[information] Adding SAN entry: xxx.yyy
[information] Updated Let's Encrypt certificate for xxx.zzz
[information] Let's Encrypt certificates have been updated

that means nothing happened (or you forget the --debug switch)

Link to comment
Share on other sites

  • 0

I put an echo on line 298 in froxlor/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php to see what acme.sh does. When deleting the certificate from the list in Froxlor, it says "Domains not changed" and does nothing. The existing certificate is then copied from /root/.acme.sh to /etc/ssl/froxlor-custom.

When adding a domain (as an alias of the existing domain), the command looks like this:

```

/root/.acme.sh/acme.sh --auto-upgrade 0 --server https://acme-v01.api.letsencrypt.org/directory --renew -d existing_domain.net -d new_domain.net --keylength 4096

```

Since it says '--renew', the new domain is not added to the certificate. The correct switch is '--issue'.

 

It would be helpful to see the output of the acme script when using the --debug switch on the cronjob.

Link to comment
Share on other sites

  • 0
4 minutes ago, peterpan said:

When deleting the certificate from the list in Froxlor, it says "Domains not changed" and does nothing.

hm...okay, interesting, I'll dig into that

4 minutes ago, peterpan said:

Since it says '--renew', the new domain is not added to the certificate. The correct switch is '--issue'.

sure it tries a --renew when nothing changed :)

4 minutes ago, peterpan said:

It would be helpful to see the output of the acme script when using the --debug switch on the cronjob.

definetly a good idea, I'll check what I can do

Link to comment
Share on other sites

  • 0
1 minute ago, d00p said:

sure it tries a --renew when nothing changed :)

 

Actually, something did change: I added the new domain as an alias of an existing domain. In the acme.sh command it says '-d new_domain' (correct), so the '--renew' switch is probably not the right choice by your script.

Link to comment
Share on other sites

  • 0

Ah okay, so it did recognize the additional alias....also i think in any case when a certificate gets deleted it should do an --issue and not try a --renew - need to check whether this is froxlor logic or acme.sh - did you - after deletion of the certificate - wait for the cron to remove the certificate from acme-sh itself? see https://github.com/Froxlor/Froxlor/blob/master/lib/Froxlor/Domain/Domain.php#L294

Link to comment
Share on other sites

  • 0

'tasks' outputs nothing about removing the certificate. I can't get my finger behind it, but in some situations the 'renew' switch is used, where it should be 'issue'. In other situations, 'issue' is used correctly.

Also interesting: if an error occurs when getting the certificate (e.g. the domain validation fails), there is no retry for the certificate. At the next run, it says "No new certificates or certificates due for renewal found".

Link to comment
Share on other sites

  • 0
3 hours ago, peterpan said:

Also interesting: if an error occurs when getting the certificate (e.g. the domain validation fails),

domain validation should be done way before trying to get a certificate (when adding the domain)

Link to comment
Share on other sites

  • 0
On 9/9/2019 at 4:58 PM, d00p said:

domain validation should be done way before trying to get a certificate (when adding the domain)

Yes, sure, but there are situations where the domain is not available afterwards, such as not-responsive DNS or a domain that doesn't exist anymore. Not always sure that the domain is removed from Froxlor in that case.

Link to comment
Share on other sites

  • 0

Ok, so I debugged a bit. Changes to domains/aliases/etc. set the expiration-date to NULL which in the former let's encrypt implementation was enough to trigger a re-issue. Acme.sh on the other side displays an error:

Quote

Domain key exists, do you want to overwrite the key?
Add '--force', and try again.
Create domain key error.

Could you test the following changes to see if the certificate issue is now done properly when changing a domain alias?

diff --git a/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php b/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php
index e0967ca0..32d7fae1 100644
--- a/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php
+++ b/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php
@@ -62,7 +62,7 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron
                        SELECT
                                domssl.`id`,
                                domssl.`domainid`,
-                               domssl.expirationdate,
+                               domssl.`expirationdate`,
                                domssl.`ssl_cert_file`,
                                domssl.`ssl_key_file`,
                                domssl.`ssl_ca_file`,
@@ -221,9 +221,14 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron
                        // Only renew let's encrypt certificate if no broken ssl_redirect is enabled
                        if ($certrow['ssl_redirect'] != 2) {
 
-                               if (! empty($certrow['ssl_cert_file'])) {
+                               $do_force = false;
+                               if (! empty($certrow['ssl_cert_file']) && !empty($certrow['expirationdate'])) {
                                        $cert_mode = 'renew';
                                        $cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Updating certificate for " . $certrow['domain']);
+                               } else if (! empty($certrow['ssl_cert_file']) && empty($certrow['expirationdate'])) {
+                                       // domain changed (SAN or similar)
+                                       $do_force = true;
+                                       $cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Re-creating certificate for " . $certrow['domain']);
                                } else {
                                        $cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Creating certificate for " . $certrow['domain']);
                                }
@@ -252,7 +257,7 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron
                                        }
                                }
 
-                               self::runAcmeSh($certrow, $domains, $cert_mode, $cronlog, $changedetected);
+                               self::runAcmeSh($certrow, $domains, $cert_mode, $cronlog, $changedetected, $do_force);
                        } else {
                                $cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_WARNING, "Skipping Let's Encrypt generation for " . $certrow['domain'] . " due to an enabled ssl_redirect");
                        }
@@ -270,7 +275,7 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron
                }
        }
 
-       private static function runAcmeSh($certrow = array(), $domains = array(), $cert_mode = 'issue', &$cronlog = null, &$changedetected = 0)
+       private static function runAcmeSh($certrow = array(), $domains = array(), $cert_mode = 'issue', &$cronlog = null, &$changedetected = 0, $force = false)
        {
                if (! empty($domains)) {
 
@@ -295,6 +300,9 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron
                        if (Settings::Get('system.letsencryptca') == 'testing') {
                                $acmesh_cmd .= " --staging";
                        }
+                       if ($force) {
+                               $acmesh_cmd .= " --force";
+                       }
 
                        $acme_result = \Froxlor\FileDir::safe_exec($acmesh_cmd);
 

 

Link to comment
Share on other sites

  • 0

When I run 'git apply' on this, it says:

Quote

error: patch failed: lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php:62
error: lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php: patch does not apply

although it says "SELECT" at line 62.

I am on the latest version:

Quote

 

# git status

On branch master

Your branch is up-to-date with 'origin/master'.

nothing to commit, working tree clean

 

 

Link to comment
Share on other sites

  • 0

Hm, I cant seem to find the proper configuration. Accessing attachments should be allowed for the members group. But the file is basically the same as the diff I've sent you, here the contents:

From 6ebb8dabc448a692c591c4286a5a39eae13c275b Mon Sep 17 00:00:00 2001
From: Michael Kaufmann <d00p@froxlor.org>
Date: Thu, 12 Sep 2019 12:30:47 +0200
Subject: [PATCH] re-create certificate if SAN list or domain changes

Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
---
 lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php | 16 ++++++++++++----
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php b/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php
index e0967ca0..32d7fae1 100644
--- a/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php
+++ b/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php
@@ -62,7 +62,7 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron
 			SELECT
 				domssl.`id`,
 				domssl.`domainid`,
-				domssl.expirationdate,
+				domssl.`expirationdate`,
 				domssl.`ssl_cert_file`,
 				domssl.`ssl_key_file`,
 				domssl.`ssl_ca_file`,
@@ -221,9 +221,14 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron
 			// Only renew let's encrypt certificate if no broken ssl_redirect is enabled
 			if ($certrow['ssl_redirect'] != 2) {
 
-				if (! empty($certrow['ssl_cert_file'])) {
+				$do_force = false;
+				if (! empty($certrow['ssl_cert_file']) && !empty($certrow['expirationdate'])) {
 					$cert_mode = 'renew';
 					$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Updating certificate for " . $certrow['domain']);
+				} else if (! empty($certrow['ssl_cert_file']) && empty($certrow['expirationdate'])) {
+					// domain changed (SAN or similar)
+					$do_force = true;
+					$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Re-creating certificate for " . $certrow['domain']);
 				} else {
 					$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Creating certificate for " . $certrow['domain']);
 				}
@@ -252,7 +257,7 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron
 					}
 				}
 
-				self::runAcmeSh($certrow, $domains, $cert_mode, $cronlog, $changedetected);
+				self::runAcmeSh($certrow, $domains, $cert_mode, $cronlog, $changedetected, $do_force);
 			} else {
 				$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_WARNING, "Skipping Let's Encrypt generation for " . $certrow['domain'] . " due to an enabled ssl_redirect");
 			}
@@ -270,7 +275,7 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron
 		}
 	}
 
-	private static function runAcmeSh($certrow = array(), $domains = array(), $cert_mode = 'issue', &$cronlog = null, &$changedetected = 0)
+	private static function runAcmeSh($certrow = array(), $domains = array(), $cert_mode = 'issue', &$cronlog = null, &$changedetected = 0, $force = false)
 	{
 		if (! empty($domains)) {
 
@@ -295,6 +300,9 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron
 			if (Settings::Get('system.letsencryptca') == 'testing') {
 				$acmesh_cmd .= " --staging";
 			}
+			if ($force) {
+				$acmesh_cmd .= " --force";
+			}
 
 			$acme_result = \Froxlor\FileDir::safe_exec($acmesh_cmd);
 
-- 
2.20.1

 

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...