Compare commits

...
8 Commits
Author SHA1 Message Date
HemachandarandGitHub 51628f7753 Merge branch '1.8.x' into ser-1092 2026-02-03 13:39:30 +05:30
Hemachandar d3b8bb9833 default false 2026-02-03 02:16:54 +05:30
HemachandarandGitHub 19afa7eafd Merge branch '1.8.x' into ser-1092 2026-02-03 02:07:55 +05:30
Hemachandar f549c5ceb0 rename to checkRule 2026-02-03 02:07:06 +05:30
Hemachandar b011291b8d simplify 2026-02-02 22:59:19 +05:30
HemachandarandGitHub 73624c6e74 Merge branch '1.8.x' into ser-1092 2026-02-02 22:58:47 +05:30
HemachandarandGitHub 6a3f0fd45c Merge branch '1.8.x' into ser-1092 2026-02-02 20:42:02 +05:30
HemachandarandClaude Opus 4.5 554cb61c08 Add skipRule support for certificate generation without DB rule
This allows certificate generation to proceed for domains that don't
have a corresponding rule in the database (e.g., _APP_DOMAIN). When
skipRule is true, the worker looks up certificates by domain name
instead of rule's certificateId, and skips all rule status updates.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-02 10:49:54 +05:30
3 changed files with 63 additions and 17 deletions
+25
View File
@@ -11,6 +11,7 @@ class Certificate extends Event
public const string ACTION_DOMAIN_VERIFICATION = 'verification';
public const string ACTION_GENERATION = 'generation';
protected bool $skipRenewCheck = false;
protected bool $checkRule = true;
protected string $action = self::ACTION_GENERATION;
protected ?Document $domain = null;
protected ?string $validationDomain = null;
@@ -94,6 +95,29 @@ class Certificate extends Event
return $this->skipRenewCheck;
}
/**
* Set if rule lookup and updates should be checked.
*
* @param bool $checkRule
* @return self
*/
public function setCheckRule(bool $checkRule): self
{
$this->checkRule = $checkRule;
return $this;
}
/**
* Return if rule lookup and updates should be checked.
*
* @return bool
*/
public function getCheckRule(): bool
{
return $this->checkRule;
}
/**
* Set action for this certificate event.
*
@@ -128,6 +152,7 @@ class Certificate extends Event
'project' => $this->project,
'domain' => $this->domain,
'skipRenewCheck' => $this->skipRenewCheck,
'checkRule' => $this->checkRule,
'validationDomain' => $this->validationDomain,
'action' => $this->action
];
+4 -1
View File
@@ -23,13 +23,15 @@ class SSL extends Action
->desc('Validate server certificates')
->param('domain', System::getEnv('_APP_DOMAIN', ''), new Hostname(), 'Domain to generate certificate for. If empty, main domain will be used.', true)
->param('skip-check', true, new Boolean(true), 'If DNS and renew check should be skipped. Defaults to true, and when true, all jobs will result in certificate generation attempt.', true)
->param('check-rule', false, new Boolean(true), 'If rule lookup and updates should be checked. Defaults to false. Set to true for domains with a rule in DB.', true)
->inject('queueForCertificates')
->callback($this->action(...));
}
public function action(string $domain, bool|string $skipCheck, Certificate $queueForCertificates): void
public function action(string $domain, bool|string $skipCheck, bool|string $checkRule, Certificate $queueForCertificates): void
{
$skipCheck = \strval($skipCheck) === 'true';
$checkRule = \strval($checkRule) === 'true';
Console::success('Scheduling a job to issue a TLS certificate for domain: ' . $domain);
@@ -38,6 +40,7 @@ class SSL extends Action
'domain' => $domain
]))
->setSkipRenewCheck($skipCheck)
->setCheckRule($checkRule)
->trigger();
}
}
+34 -16
View File
@@ -104,6 +104,7 @@ class Certificates extends Action
$domain = new Domain($document->getAttribute('domain', ''));
$domainType = $document->getAttribute('domainType');
$skipRenewCheck = $payload['skipRenewCheck'] ?? false;
$checkRule = $payload['checkRule'] ?? true;
$validationDomain = $payload['validationDomain'] ?? null;
$action = $payload['action'] ?? Certificate::ACTION_GENERATION;
@@ -115,7 +116,7 @@ class Certificates extends Action
break;
case Certificate::ACTION_GENERATION:
$this->handleCertificateGenerationAction($domain, $domainType, $dbForPlatform, $queueForMails, $queueForEvents, $queueForWebhooks, $queueForFunctions, $queueForRealtime, $log, $certificates, $authorization, $skipRenewCheck, $plan, $validationDomain);
$this->handleCertificateGenerationAction($domain, $domainType, $dbForPlatform, $queueForMails, $queueForEvents, $queueForWebhooks, $queueForFunctions, $queueForRealtime, $log, $certificates, $authorization, $skipRenewCheck, $checkRule, $plan, $validationDomain);
break;
default:
@@ -210,6 +211,7 @@ class Certificates extends Action
* @param CertificatesAdapter $certificates
* @param ValidatorAuthorization $authorization
* @param bool $skipRenewCheck
* @param bool $checkRule Check rule is present for certificate and update it if needed
* @param array $plan
* @param string|null $validationDomain
* @return void
@@ -234,6 +236,7 @@ class Certificates extends Action
CertificatesAdapter $certificates,
ValidatorAuthorization $authorization,
bool $skipRenewCheck = false,
bool $checkRule = true,
array $plan = [],
?string $validationDomain = null
): void {
@@ -266,25 +269,35 @@ class Certificates extends Action
* Note: Renewals are checked and scheduled from maintenance worker
*/
// Get rule document for domain
// TODO: (@Meldiron) Remove after 1.7.x migration
$rule = System::getEnv('_APP_RULES_FORMAT') === 'md5'
? $authorization->skip(fn () => $dbForPlatform->getDocument('rules', md5($domain->get())))
: $authorization->skip(fn () => $dbForPlatform->findOne('rules', [
Query::equal('domain', [$domain->get()]),
Query::limit(1),
]));
$rule = new Document();
// Rule not found (or) not in the expected state
if ($rule->isEmpty() || !\in_array($rule->getAttribute('status'), [RULE_STATUS_CERTIFICATE_GENERATING, RULE_STATUS_VERIFIED])) {
Console::warning('Certificate generation for ' . $domain->get() . ' is skipped as the associated rule is either empty or not in the expected state.');
return;
if ($checkRule) {
// Get rule document for domain
// TODO: (@Meldiron) Remove after 1.7.x migration
$rule = System::getEnv('_APP_RULES_FORMAT') === 'md5'
? $authorization->skip(fn () => $dbForPlatform->getDocument('rules', md5($domain->get())))
: $authorization->skip(fn () => $dbForPlatform->findOne('rules', [
Query::equal('domain', [$domain->get()]),
Query::limit(1),
]));
// Rule not found (or) not in the expected state
if ($rule->isEmpty() || !\in_array($rule->getAttribute('status'), [RULE_STATUS_CERTIFICATE_GENERATING, RULE_STATUS_VERIFIED])) {
Console::warning('Certificate generation for ' . $domain->get() . ' is skipped as the associated rule is either empty or not in the expected state.');
return;
}
}
// Get associated certificate for the rule
$certificate = $dbForPlatform->getDocument('certificates', $rule->getAttribute('certificateId') ?? '');
// Get associated certificate for the rule (or by domain if skipRule is true)
$certificate = match ($checkRule) {
true => $dbForPlatform->getDocument('certificates', $rule->getAttribute('certificateId') ?? ''),
false => $dbForPlatform->findOne('certificates', [
Query::equal('domain', [$domain->get()]),
Query::limit(1),
]),
};
// If we don't have certificate for the rule yet, let's create one.
// If we don't have certificate yet, let's create one.
if ($certificate->isEmpty()) {
$certificate = new Document();
$certificate->setAttribute('domain', $domain->get());
@@ -353,6 +366,11 @@ class Certificates extends Action
// Save certificate document to database
$this->upsertCertificate($rule, $certificate, $dbForPlatform);
// Skip rule update when rule is not required to be associated with certificate (e.g., for _APP_DOMAIN)
if (!$checkRule) {
return;
}
// Ensure certificate is associated with the rule
$rule->setAttribute('certificateId', $certificate->getId());
// Update rule and emit events