mirror of
https://github.com/fosrl/pangolin.git
synced 2026-05-27 19:22:50 +00:00
Handle *. wildcard domains in the db
This commit is contained in:
@@ -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`);
|
||||||
|
|||||||
@@ -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)) {
|
||||||
|
|||||||
Reference in New Issue
Block a user