mirror of
https://github.com/fosrl/pangolin.git
synced 2025-12-13 11:36:04 +00:00
100 lines
3.1 KiB
TypeScript
100 lines
3.1 KiB
TypeScript
/*
|
|
* This file is part of a proprietary work.
|
|
*
|
|
* Copyright (c) 2025 Fossorial, Inc.
|
|
* All rights reserved.
|
|
*
|
|
* This file is licensed under the Fossorial Commercial License.
|
|
* You may not use this file except in compliance with the License.
|
|
* Unauthorized use, copying, modification, or distribution is strictly prohibited.
|
|
*
|
|
* This file is not licensed under the AGPLv3.
|
|
*/
|
|
|
|
import config from "./config";
|
|
import { certificates, db } from "@server/db";
|
|
import { and, eq, isNotNull } from "drizzle-orm";
|
|
import { decryptData } from "@server/lib/encryption";
|
|
import * as fs from "fs";
|
|
|
|
export async function getValidCertificatesForDomains(
|
|
domains: Set<string>
|
|
): Promise<
|
|
Array<{
|
|
id: number;
|
|
domain: string;
|
|
wildcard: boolean | null;
|
|
certFile: string | null;
|
|
keyFile: string | null;
|
|
expiresAt: number | null;
|
|
updatedAt?: number | null;
|
|
}>
|
|
> {
|
|
if (domains.size === 0) {
|
|
return [];
|
|
}
|
|
|
|
const domainArray = Array.from(domains);
|
|
|
|
// TODO: add more foreign keys to make this query more efficient - we dont need to keep getting every certificate
|
|
const validCerts = await db
|
|
.select({
|
|
id: certificates.certId,
|
|
domain: certificates.domain,
|
|
certFile: certificates.certFile,
|
|
keyFile: certificates.keyFile,
|
|
expiresAt: certificates.expiresAt,
|
|
updatedAt: certificates.updatedAt,
|
|
wildcard: certificates.wildcard
|
|
})
|
|
.from(certificates)
|
|
.where(
|
|
and(
|
|
eq(certificates.status, "valid"),
|
|
isNotNull(certificates.certFile),
|
|
isNotNull(certificates.keyFile)
|
|
)
|
|
);
|
|
|
|
// Filter certificates for the specified domains and if it is a wildcard then you can match on everything up to the first dot
|
|
const validCertsFiltered = validCerts.filter((cert) => {
|
|
return (
|
|
domainArray.includes(cert.domain) ||
|
|
(cert.wildcard &&
|
|
domainArray.some((domain) =>
|
|
domain.endsWith(`.${cert.domain}`)
|
|
))
|
|
);
|
|
});
|
|
|
|
const encryptionKeyPath = config.getRawPrivateConfig().server.encryption_key_path;
|
|
|
|
if (!fs.existsSync(encryptionKeyPath)) {
|
|
throw new Error(
|
|
"Encryption key file not found. Please generate one first."
|
|
);
|
|
}
|
|
|
|
const encryptionKeyHex = fs.readFileSync(encryptionKeyPath, "utf8").trim();
|
|
const encryptionKey = Buffer.from(encryptionKeyHex, "hex");
|
|
|
|
const validCertsDecrypted = validCertsFiltered.map((cert) => {
|
|
// Decrypt and save certificate file
|
|
const decryptedCert = decryptData(
|
|
cert.certFile!, // is not null from query
|
|
encryptionKey
|
|
);
|
|
|
|
// Decrypt and save key file
|
|
const decryptedKey = decryptData(cert.keyFile!, encryptionKey);
|
|
|
|
// Return only the certificate data without org information
|
|
return {
|
|
...cert,
|
|
certFile: decryptedCert,
|
|
keyFile: decryptedKey
|
|
};
|
|
});
|
|
|
|
return validCertsDecrypted;
|
|
} |