Handle *. wildcard domains in the db

This commit is contained in:
Owen
2026-04-22 17:06:22 -07:00
parent 9d0a8ecb09
commit d463a578c2
2 changed files with 21 additions and 14 deletions

View File

@@ -279,11 +279,8 @@ async function syncAcmeCerts(
} }
for (const cert of resolverData.Certificates) { for (const cert of resolverData.Certificates) {
const rawDomain = cert.domain?.main; const domain = cert.domain?.main;
const domain = rawDomain.startsWith("*.") const wildcard = domain.startsWith("*.");
? rawDomain.slice(2)
: rawDomain;
const wildcard = rawDomain.startsWith("*.");
if (!domain) { if (!domain) {
logger.debug(`acmeCertSync: skipping cert with missing domain`); logger.debug(`acmeCertSync: skipping cert with missing domain`);

View File

@@ -19,8 +19,6 @@ import { decrypt } from "@server/lib/crypto";
import logger from "@server/logger"; import logger from "@server/logger";
import cache from "#private/lib/cache"; import cache from "#private/lib/cache";
// Define the return type for clarity and type safety // Define the return type for clarity and type safety
export type CertificateResult = { export type CertificateResult = {
id: number; id: number;
@@ -78,6 +76,9 @@ export async function getValidCertificatesForDomains(
const parentDomainsArray = Array.from(parentDomainsToQuery); const parentDomainsArray = Array.from(parentDomainsToQuery);
// Build wildcard variants: for each parent domain "example.com", also query "*.example.com"
const wildcardPrefixedArray = build != "saas" ? parentDomainsArray.map((d) => `*.${d}`) : [];
// 4. Build and execute a single, efficient Drizzle query // 4. Build and execute a single, efficient Drizzle query
// This query fetches all potential exact and wildcard matches in one database round-trip. // This query fetches all potential exact and wildcard matches in one database round-trip.
const potentialCerts = await db const potentialCerts = await db
@@ -91,10 +92,13 @@ export async function getValidCertificatesForDomains(
or( or(
// Condition for exact matches on the requested domains // Condition for exact matches on the requested domains
inArray(certificates.domain, domainsToQueryArray), inArray(certificates.domain, domainsToQueryArray),
// Condition for wildcard matches on the parent domains // Condition for wildcard matches on the parent domains (stored as "example.com" or "*.example.com")
parentDomainsArray.length > 0 parentDomainsArray.length > 0
? and( ? and(
inArray(certificates.domain, parentDomainsArray), inArray(certificates.domain, [
...parentDomainsArray,
...wildcardPrefixedArray
]),
eq(certificates.wildcard, true) eq(certificates.wildcard, true)
) )
: // If there are no possible parent domains, this condition is false : // If there are no possible parent domains, this condition is false
@@ -103,13 +107,18 @@ export async function getValidCertificatesForDomains(
) )
); );
// Helper to normalize a wildcard cert's domain to its bare parent domain (strips leading "*.")
const normalizeWildcardDomain = (domain: string): string =>
domain.startsWith("*.") ? domain.slice(2) : domain;
// 5. Process the database results, prioritizing exact matches over wildcards // 5. Process the database results, prioritizing exact matches over wildcards
const exactMatches = new Map<string, (typeof potentialCerts)[0]>(); const exactMatches = new Map<string, (typeof potentialCerts)[0]>();
const wildcardMatches = new Map<string, (typeof potentialCerts)[0]>(); const wildcardMatches = new Map<string, (typeof potentialCerts)[0]>();
for (const cert of potentialCerts) { for (const cert of potentialCerts) {
if (cert.wildcard) { if (cert.wildcard) {
wildcardMatches.set(cert.domain, cert); // Normalize to bare parent domain so lookups are consistent regardless of storage format
wildcardMatches.set(normalizeWildcardDomain(cert.domain), cert);
} else { } else {
exactMatches.set(cert.domain, cert); exactMatches.set(cert.domain, cert);
} }
@@ -122,14 +131,15 @@ export async function getValidCertificatesForDomains(
if (exactMatches.has(domain)) { if (exactMatches.has(domain)) {
foundCert = exactMatches.get(domain); foundCert = exactMatches.get(domain);
} }
// Priority 2: Check for a wildcard certificate that matches the exact domain // Priority 2: Check for a wildcard certificate whose normalized domain equals the queried domain
else { else {
if (wildcardMatches.has(domain)) { const normalizedDomain = normalizeWildcardDomain(domain);
foundCert = wildcardMatches.get(domain); if (wildcardMatches.has(normalizedDomain)) {
foundCert = wildcardMatches.get(normalizedDomain);
} }
// Priority 3: Check for a wildcard match on the parent domain // Priority 3: Check for a wildcard match on the parent domain
else { else {
const parts = domain.split("."); const parts = normalizedDomain.split(".");
if (parts.length > 1) { if (parts.length > 1) {
const parentDomain = parts.slice(1).join("."); const parentDomain = parts.slice(1).join(".");
if (wildcardMatches.has(parentDomain)) { if (wildcardMatches.has(parentDomain)) {