2023-01-02 11:34:11 +00:00
|
|
|
import {
|
|
|
|
EVERY_FIVE_MINUTE,
|
|
|
|
EVERY_HOUR,
|
|
|
|
EVERY_MINUTE,
|
|
|
|
} from '../../Utils/CronTime';
|
2022-11-27 20:10:55 +00:00
|
|
|
import RunCron from '../../Utils/Cron';
|
|
|
|
import { IsDevelopment } from 'CommonServer/Config';
|
|
|
|
import StatusPageDomain from 'Model/Models/StatusPageDomain';
|
|
|
|
import StatusPageDomainService from 'CommonServer/Services/StatusPageDomainService';
|
2022-11-28 18:26:07 +00:00
|
|
|
// @ts-ignore
|
2022-11-27 20:10:55 +00:00
|
|
|
import Greenlock from 'greenlock';
|
2022-11-28 18:26:07 +00:00
|
|
|
import logger from 'CommonServer/Utils/Logger';
|
|
|
|
import BadDataException from 'Common/Types/Exception/BadDataException';
|
|
|
|
import Express, {
|
|
|
|
ExpressRequest,
|
|
|
|
ExpressResponse,
|
|
|
|
ExpressRouter,
|
|
|
|
NextFunction,
|
|
|
|
} from 'CommonServer/Utils/Express';
|
|
|
|
import ClusterKeyAuthorization from 'CommonServer/Middleware/ClusterKeyAuthorization';
|
|
|
|
import { JSONObject } from 'Common/Types/JSON';
|
|
|
|
import Response from 'CommonServer/Utils/Response';
|
2022-12-05 10:40:28 +00:00
|
|
|
import LIMIT_MAX from 'Common/Types/Database/LimitMax';
|
2022-12-11 09:10:17 +00:00
|
|
|
import axios, { AxiosResponse } from 'axios';
|
2022-12-11 08:02:56 +00:00
|
|
|
import GreenlockCertificate from 'Model/Models/GreenlockCertificate';
|
|
|
|
import GreenlockCertificateService from 'CommonServer/Services/GreenlockCertificateService';
|
|
|
|
import fs from 'fs';
|
2023-01-02 11:31:50 +00:00
|
|
|
import SelfSignedSSL from '../../Utils/SelfSignedSSL';
|
2022-11-27 20:10:55 +00:00
|
|
|
|
2022-11-28 18:26:07 +00:00
|
|
|
const router: ExpressRouter = Express.getRouter();
|
|
|
|
|
2022-12-07 06:44:17 +00:00
|
|
|
const greenlock: any = Greenlock.create({
|
2022-12-05 10:40:28 +00:00
|
|
|
configFile: '/greenlockrc',
|
|
|
|
packageRoot: `/usr/src/app`,
|
2022-12-07 06:44:17 +00:00
|
|
|
manager: '/usr/src/app/Utils/Greenlock/Manager.ts',
|
2022-11-28 18:26:07 +00:00
|
|
|
approveDomains: async (opts: any) => {
|
2022-12-07 06:44:17 +00:00
|
|
|
const domain: StatusPageDomain | null =
|
|
|
|
await StatusPageDomainService.findOneBy({
|
|
|
|
query: {
|
|
|
|
fullDomain: opts.domain,
|
|
|
|
},
|
|
|
|
select: {
|
|
|
|
_id: true,
|
|
|
|
fullDomain: true,
|
|
|
|
},
|
|
|
|
props: {
|
|
|
|
isRoot: true,
|
|
|
|
},
|
|
|
|
});
|
2022-11-28 18:26:07 +00:00
|
|
|
|
|
|
|
if (!domain) {
|
2022-12-07 06:44:17 +00:00
|
|
|
throw new BadDataException(
|
|
|
|
`Domain ${opts.domain} does not exist in StatusPageDomain`
|
|
|
|
);
|
2022-11-28 18:26:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return opts; // or Promise.resolve(opts);
|
2022-11-27 20:10:55 +00:00
|
|
|
},
|
2022-12-05 18:05:47 +00:00
|
|
|
store: {
|
2022-12-07 06:44:17 +00:00
|
|
|
module: '/usr/src/app/Utils/Greenlock/Store.ts',
|
2022-12-05 18:05:47 +00:00
|
|
|
},
|
2022-11-27 20:10:55 +00:00
|
|
|
// Staging for testing environments
|
2022-12-08 16:23:21 +00:00
|
|
|
// staging: IsDevelopment,
|
2022-11-27 20:10:55 +00:00
|
|
|
|
|
|
|
// This should be the contact who receives critical bug and security notifications
|
|
|
|
// Optionally, you may receive other (very few) updates, such as important new features
|
2022-11-28 18:26:07 +00:00
|
|
|
maintainerEmail: 'lets-encrypt@oneuptime.com',
|
2022-11-27 20:10:55 +00:00
|
|
|
|
|
|
|
// for an RFC 8555 / RFC 7231 ACME client user agent
|
2022-12-07 06:44:17 +00:00
|
|
|
packageAgent: 'oneuptime/1.0.0',
|
2022-12-08 16:23:21 +00:00
|
|
|
|
2022-11-28 18:26:07 +00:00
|
|
|
notify: function (event: string, details: any) {
|
|
|
|
if ('error' === event) {
|
2022-12-09 08:19:51 +00:00
|
|
|
logger.error('Greenlock Notify: ' + event);
|
2022-11-28 18:26:07 +00:00
|
|
|
logger.error(details);
|
|
|
|
}
|
2022-12-09 08:19:51 +00:00
|
|
|
logger.info('Greenlock Notify: ' + event);
|
2022-12-08 16:23:21 +00:00
|
|
|
logger.info(details);
|
2022-11-28 18:26:07 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
agreeToTerms: true,
|
|
|
|
challenges: {
|
2022-12-05 18:05:47 +00:00
|
|
|
'http-01': {
|
2022-12-07 06:44:17 +00:00
|
|
|
module: '/usr/src/app/Utils/Greenlock/HttpChallenge.ts',
|
|
|
|
},
|
2022-11-28 18:26:07 +00:00
|
|
|
},
|
2022-11-27 20:10:55 +00:00
|
|
|
});
|
|
|
|
|
2022-11-28 18:26:07 +00:00
|
|
|
// Delete
|
|
|
|
router.delete(
|
|
|
|
`/certs`,
|
|
|
|
ClusterKeyAuthorization.isAuthorizedServiceMiddleware,
|
2022-12-07 06:44:17 +00:00
|
|
|
async (req: ExpressRequest, res: ExpressResponse, next: NextFunction) => {
|
2022-11-28 18:26:07 +00:00
|
|
|
try {
|
|
|
|
const body: JSONObject = req.body;
|
2022-12-05 10:40:28 +00:00
|
|
|
|
2022-11-28 18:26:07 +00:00
|
|
|
if (!body['domain']) {
|
2022-12-07 06:44:17 +00:00
|
|
|
throw new BadDataException('Domain is required');
|
2022-11-28 18:26:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
await greenlock.remove({
|
2022-12-09 08:19:51 +00:00
|
|
|
subject: body['domain'],
|
2022-11-28 18:26:07 +00:00
|
|
|
});
|
2022-11-27 20:10:55 +00:00
|
|
|
|
2022-11-28 18:26:07 +00:00
|
|
|
return Response.sendEmptyResponse(req, res);
|
|
|
|
} catch (err) {
|
|
|
|
next(err);
|
2022-11-27 20:10:55 +00:00
|
|
|
}
|
2022-11-28 18:26:07 +00:00
|
|
|
}
|
|
|
|
);
|
2022-11-27 20:10:55 +00:00
|
|
|
|
2022-11-28 18:26:07 +00:00
|
|
|
// Create
|
|
|
|
router.post(
|
|
|
|
`/certs`,
|
|
|
|
ClusterKeyAuthorization.isAuthorizedServiceMiddleware,
|
2022-12-07 06:44:17 +00:00
|
|
|
async (req: ExpressRequest, res: ExpressResponse, next: NextFunction) => {
|
2022-11-28 18:26:07 +00:00
|
|
|
try {
|
|
|
|
const body: JSONObject = req.body;
|
2022-12-05 10:40:28 +00:00
|
|
|
|
2022-11-28 18:26:07 +00:00
|
|
|
if (!body['domain']) {
|
2022-12-07 06:44:17 +00:00
|
|
|
throw new BadDataException('Domain is required');
|
2022-11-28 18:26:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
await greenlock.add({
|
2022-12-07 06:44:17 +00:00
|
|
|
subject: body['domain'],
|
2022-12-09 08:19:51 +00:00
|
|
|
altnames: [body['domain']],
|
2022-11-28 18:26:07 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
return Response.sendEmptyResponse(req, res);
|
|
|
|
} catch (err) {
|
|
|
|
next(err);
|
|
|
|
}
|
2022-11-27 20:10:55 +00:00
|
|
|
}
|
2022-11-28 18:26:07 +00:00
|
|
|
);
|
|
|
|
|
|
|
|
// Create
|
|
|
|
router.get(
|
|
|
|
`/certs`,
|
|
|
|
ClusterKeyAuthorization.isAuthorizedServiceMiddleware,
|
2022-12-07 06:44:17 +00:00
|
|
|
async (req: ExpressRequest, res: ExpressResponse, next: NextFunction) => {
|
2022-11-28 18:26:07 +00:00
|
|
|
try {
|
|
|
|
const body: JSONObject = req.body;
|
2022-12-05 10:40:28 +00:00
|
|
|
|
2022-11-28 18:26:07 +00:00
|
|
|
if (!body['domain']) {
|
2022-12-07 06:44:17 +00:00
|
|
|
throw new BadDataException('Domain is required');
|
2022-11-28 18:26:07 +00:00
|
|
|
}
|
|
|
|
|
2022-12-07 06:44:17 +00:00
|
|
|
const site: JSONObject = await greenlock.get({
|
|
|
|
servername: body['domain'] as string,
|
|
|
|
});
|
2022-11-28 18:26:07 +00:00
|
|
|
|
|
|
|
return Response.sendJsonObjectResponse(req, res, site);
|
|
|
|
} catch (err) {
|
|
|
|
next(err);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|
|
|
|
|
2022-12-08 16:23:21 +00:00
|
|
|
RunCron(
|
|
|
|
'StatusPageCerts:OrderCerts',
|
2023-03-02 19:23:03 +00:00
|
|
|
{ schedule: IsDevelopment ? EVERY_MINUTE : EVERY_HOUR, runOnStartup: true },
|
2022-12-08 16:23:21 +00:00
|
|
|
async () => {
|
|
|
|
// Fetch all domains where certs are added to greenlock.
|
|
|
|
|
|
|
|
const domains: Array<StatusPageDomain> =
|
|
|
|
await StatusPageDomainService.findBy({
|
|
|
|
query: {
|
|
|
|
isAddedtoGreenlock: true,
|
2022-12-09 08:19:51 +00:00
|
|
|
isSslProvisioned: false,
|
2022-12-08 16:23:21 +00:00
|
|
|
},
|
|
|
|
select: {
|
|
|
|
_id: true,
|
|
|
|
greenlockConfig: true,
|
2022-12-09 08:19:51 +00:00
|
|
|
fullDomain: true,
|
2022-12-08 16:23:21 +00:00
|
|
|
},
|
|
|
|
limit: LIMIT_MAX,
|
|
|
|
skip: 0,
|
|
|
|
props: {
|
|
|
|
isRoot: true,
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
for (const domain of domains) {
|
|
|
|
logger.info(
|
|
|
|
`StatusPageCerts:OrderCerts - Checking CNAME ${domain.fullDomain}`
|
|
|
|
);
|
|
|
|
|
|
|
|
await greenlock.order(domain.greenlockConfig);
|
|
|
|
}
|
2022-12-07 06:44:17 +00:00
|
|
|
}
|
|
|
|
);
|
2022-11-28 18:26:07 +00:00
|
|
|
|
2022-12-07 06:44:17 +00:00
|
|
|
RunCron(
|
|
|
|
'StatusPageCerts:AddCerts',
|
2023-03-02 19:23:03 +00:00
|
|
|
{ schedule: IsDevelopment ? EVERY_MINUTE : EVERY_HOUR, runOnStartup: true },
|
2022-12-07 06:44:17 +00:00
|
|
|
async () => {
|
|
|
|
const domains: Array<StatusPageDomain> =
|
|
|
|
await StatusPageDomainService.findBy({
|
|
|
|
query: {
|
|
|
|
isAddedtoGreenlock: false,
|
2022-12-05 10:40:28 +00:00
|
|
|
},
|
2022-12-07 06:44:17 +00:00
|
|
|
select: {
|
|
|
|
_id: true,
|
|
|
|
fullDomain: true,
|
|
|
|
cnameVerificationToken: true,
|
|
|
|
},
|
|
|
|
limit: LIMIT_MAX,
|
|
|
|
skip: 0,
|
2022-12-05 10:40:28 +00:00
|
|
|
props: {
|
2022-12-07 06:44:17 +00:00
|
|
|
isRoot: true,
|
|
|
|
},
|
|
|
|
});
|
2022-12-05 10:40:28 +00:00
|
|
|
|
2022-12-07 06:44:17 +00:00
|
|
|
for (const domain of domains) {
|
|
|
|
logger.info(
|
|
|
|
`StatusPageCerts:AddCerts - Checking CNAME ${domain.fullDomain}`
|
|
|
|
);
|
|
|
|
|
|
|
|
// Check CNAME validation and if that fails. Remove certs from Greenlock.
|
|
|
|
const isValid: boolean = await checkCnameValidation(
|
|
|
|
domain.fullDomain!,
|
|
|
|
domain.cnameVerificationToken!
|
|
|
|
);
|
|
|
|
|
|
|
|
if (isValid) {
|
|
|
|
logger.info(
|
|
|
|
`StatusPageCerts:AddCerts - CNAME for ${domain.fullDomain} is valid. Adding domain to greenlock.`
|
|
|
|
);
|
|
|
|
|
2022-12-08 16:23:21 +00:00
|
|
|
await StatusPageDomainService.updateOneById({
|
|
|
|
id: domain.id!,
|
|
|
|
data: {
|
|
|
|
isCnameVerified: true,
|
|
|
|
},
|
|
|
|
props: {
|
|
|
|
isRoot: true,
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
2022-12-07 06:44:17 +00:00
|
|
|
await greenlock.add({
|
|
|
|
subject: domain.fullDomain,
|
2022-12-09 08:19:51 +00:00
|
|
|
altnames: [domain.fullDomain],
|
2022-12-07 06:44:17 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
await StatusPageDomainService.updateOneById({
|
|
|
|
id: domain.id!,
|
|
|
|
data: {
|
|
|
|
isAddedtoGreenlock: true,
|
|
|
|
},
|
|
|
|
props: {
|
|
|
|
isRoot: true,
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
logger.info(
|
|
|
|
`StatusPageCerts:AddCerts - ${domain.fullDomain} added to greenlock.`
|
|
|
|
);
|
|
|
|
} else {
|
|
|
|
logger.info(
|
|
|
|
`StatusPageCerts:AddCerts - CNAME for ${domain.fullDomain} is invalid. Removing cert`
|
|
|
|
);
|
|
|
|
}
|
2022-12-05 10:40:28 +00:00
|
|
|
}
|
|
|
|
}
|
2022-12-07 06:44:17 +00:00
|
|
|
);
|
2022-12-05 10:40:28 +00:00
|
|
|
|
2022-12-07 06:44:17 +00:00
|
|
|
RunCron(
|
|
|
|
'StatusPageCerts:RemoveCerts',
|
2023-03-02 19:23:03 +00:00
|
|
|
{ schedule: IsDevelopment ? EVERY_MINUTE : EVERY_HOUR, runOnStartup: true },
|
2022-12-07 06:44:17 +00:00
|
|
|
async () => {
|
|
|
|
// Fetch all domains where certs are added to greenlock.
|
2022-12-05 10:40:28 +00:00
|
|
|
|
2022-12-07 06:44:17 +00:00
|
|
|
const domains: Array<StatusPageDomain> =
|
|
|
|
await StatusPageDomainService.findBy({
|
|
|
|
query: {
|
|
|
|
isAddedtoGreenlock: true,
|
2022-12-05 10:40:28 +00:00
|
|
|
},
|
2022-12-07 06:44:17 +00:00
|
|
|
select: {
|
|
|
|
_id: true,
|
|
|
|
fullDomain: true,
|
|
|
|
cnameVerificationToken: true,
|
|
|
|
},
|
|
|
|
limit: LIMIT_MAX,
|
|
|
|
skip: 0,
|
2022-12-05 10:40:28 +00:00
|
|
|
props: {
|
2022-12-07 06:44:17 +00:00
|
|
|
isRoot: true,
|
|
|
|
},
|
|
|
|
});
|
2022-12-05 10:40:28 +00:00
|
|
|
|
2022-12-07 06:44:17 +00:00
|
|
|
for (const domain of domains) {
|
|
|
|
logger.info(
|
|
|
|
`StatusPageCerts:RemoveCerts - Checking CNAME ${domain.fullDomain}`
|
|
|
|
);
|
|
|
|
|
|
|
|
// Check CNAME validation and if that fails. Remove certs from Greenlock.
|
|
|
|
const isValid: boolean = await checkCnameValidation(
|
|
|
|
domain.fullDomain!,
|
|
|
|
domain.cnameVerificationToken!
|
|
|
|
);
|
|
|
|
|
|
|
|
if (!isValid) {
|
|
|
|
logger.info(
|
|
|
|
`StatusPageCerts:RemoveCerts - CNAME for ${domain.fullDomain} is invalid. Removing domain from greenlock.`
|
|
|
|
);
|
|
|
|
|
|
|
|
await greenlock.remove({
|
|
|
|
subject: domain.fullDomain,
|
|
|
|
});
|
|
|
|
|
|
|
|
await StatusPageDomainService.updateOneById({
|
|
|
|
id: domain.id!,
|
|
|
|
data: {
|
|
|
|
isAddedtoGreenlock: false,
|
|
|
|
isCnameVerified: false,
|
|
|
|
},
|
|
|
|
props: {
|
|
|
|
isRoot: true,
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
logger.info(
|
|
|
|
`StatusPageCerts:RemoveCerts - ${domain.fullDomain} removed from greenlock.`
|
|
|
|
);
|
|
|
|
} else {
|
|
|
|
logger.info(
|
|
|
|
`StatusPageCerts:RemoveCerts - CNAME for ${domain.fullDomain} is valid`
|
|
|
|
);
|
|
|
|
}
|
2022-12-05 10:40:28 +00:00
|
|
|
}
|
|
|
|
}
|
2022-12-07 06:44:17 +00:00
|
|
|
);
|
2022-12-05 10:40:28 +00:00
|
|
|
|
2023-01-02 11:31:50 +00:00
|
|
|
RunCron(
|
|
|
|
'StatusPageCerts:WriteSelfSignedCertsToDisk',
|
|
|
|
EVERY_FIVE_MINUTE,
|
|
|
|
async () => {
|
|
|
|
// Fetch all domains where certs are added to greenlock.
|
|
|
|
|
|
|
|
const certs: Array<GreenlockCertificate> =
|
|
|
|
await GreenlockCertificateService.findBy({
|
|
|
|
query: {},
|
|
|
|
select: {
|
|
|
|
key: true,
|
|
|
|
},
|
|
|
|
limit: LIMIT_MAX,
|
|
|
|
skip: 0,
|
|
|
|
props: {
|
|
|
|
isRoot: true,
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
const stausPageDomains: Array<StatusPageDomain> =
|
|
|
|
await StatusPageDomainService.findBy({
|
|
|
|
query: {
|
|
|
|
isSelfSignedSslGenerated: false,
|
|
|
|
},
|
|
|
|
select: {
|
|
|
|
fullDomain: true,
|
|
|
|
_id: true,
|
|
|
|
},
|
|
|
|
limit: LIMIT_MAX,
|
|
|
|
skip: 0,
|
|
|
|
props: {
|
|
|
|
isRoot: true,
|
|
|
|
ignoreHooks: true,
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
const greenlockCertDomains: Array<string | undefined> = certs.map(
|
2023-01-02 11:34:11 +00:00
|
|
|
(cert: GreenlockCertificate) => {
|
2023-01-02 11:31:50 +00:00
|
|
|
return cert.key;
|
|
|
|
}
|
|
|
|
);
|
|
|
|
|
|
|
|
// Generate self signed certs
|
|
|
|
for (const domain of stausPageDomains) {
|
|
|
|
if (greenlockCertDomains.includes(domain.fullDomain)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!domain.fullDomain) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
await SelfSignedSSL.generate(
|
|
|
|
'/usr/src/Certs/StatusPageCerts',
|
|
|
|
domain.fullDomain
|
|
|
|
);
|
|
|
|
|
|
|
|
await StatusPageDomainService.updateOneById({
|
|
|
|
id: domain.id!,
|
|
|
|
data: {
|
|
|
|
isSelfSignedSslGenerated: true,
|
|
|
|
},
|
|
|
|
props: {
|
|
|
|
ignoreHooks: true,
|
|
|
|
isRoot: true,
|
2023-01-02 11:34:11 +00:00
|
|
|
},
|
2023-01-02 11:31:50 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|
|
|
|
|
2022-12-11 08:02:56 +00:00
|
|
|
RunCron(
|
2023-01-02 11:31:50 +00:00
|
|
|
'StatusPageCerts:WriteGreelockCertsToDisk',
|
2023-03-02 19:23:03 +00:00
|
|
|
{ schedule: IsDevelopment ? EVERY_MINUTE : EVERY_HOUR, runOnStartup: true },
|
2022-12-11 08:02:56 +00:00
|
|
|
async () => {
|
|
|
|
// Fetch all domains where certs are added to greenlock.
|
|
|
|
|
|
|
|
const certs: Array<GreenlockCertificate> =
|
|
|
|
await GreenlockCertificateService.findBy({
|
2022-12-11 09:10:17 +00:00
|
|
|
query: {},
|
2022-12-11 08:02:56 +00:00
|
|
|
select: {
|
|
|
|
isKeyPair: true,
|
2022-12-11 09:10:17 +00:00
|
|
|
key: true,
|
2022-12-11 08:02:56 +00:00
|
|
|
blob: true,
|
|
|
|
},
|
|
|
|
limit: LIMIT_MAX,
|
|
|
|
skip: 0,
|
|
|
|
props: {
|
|
|
|
isRoot: true,
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
for (const cert of certs) {
|
|
|
|
if (!cert.isKeyPair) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2022-12-11 09:10:17 +00:00
|
|
|
const certBlob: GreenlockCertificate | undefined = certs.find(
|
|
|
|
(i: GreenlockCertificate) => {
|
|
|
|
return i.key === cert.key && !i.isKeyPair;
|
|
|
|
}
|
|
|
|
);
|
|
|
|
|
2022-12-11 08:02:56 +00:00
|
|
|
if (!certBlob) {
|
2022-12-11 09:10:17 +00:00
|
|
|
continue;
|
2022-12-11 08:02:56 +00:00
|
|
|
}
|
|
|
|
|
2022-12-11 09:10:17 +00:00
|
|
|
const key: string = JSON.parse(cert.blob || '{}').privateKeyPem;
|
2022-12-14 08:27:34 +00:00
|
|
|
let crt: string = JSON.parse(certBlob.blob || '{}').cert;
|
|
|
|
|
|
|
|
if (JSON.parse(certBlob.blob || '{}').chain) {
|
2022-12-15 06:37:15 +00:00
|
|
|
crt += '\n' + '\n' + JSON.parse(certBlob.blob || '{}').chain;
|
2022-12-14 08:27:34 +00:00
|
|
|
}
|
2022-12-11 08:02:56 +00:00
|
|
|
|
2022-12-11 09:10:17 +00:00
|
|
|
// Write to disk.
|
|
|
|
fs.writeFileSync(
|
|
|
|
`/usr/src/Certs/StatusPageCerts/${cert.key}.crt`,
|
2022-12-15 06:37:15 +00:00
|
|
|
crt
|
2022-12-11 09:10:17 +00:00
|
|
|
);
|
|
|
|
fs.writeFileSync(
|
|
|
|
`/usr/src/Certs/StatusPageCerts/${cert.key}.key`,
|
2022-12-15 06:37:15 +00:00
|
|
|
key
|
2022-12-11 09:10:17 +00:00
|
|
|
);
|
2022-12-11 08:02:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|
|
|
|
|
2022-12-08 16:23:21 +00:00
|
|
|
RunCron(
|
|
|
|
'StatusPageCerts:CheckSslProvisioningStatus',
|
2023-03-02 19:23:03 +00:00
|
|
|
{ schedule: IsDevelopment ? EVERY_MINUTE : EVERY_HOUR, runOnStartup: true },
|
2022-12-08 16:23:21 +00:00
|
|
|
async () => {
|
|
|
|
// Fetch all domains where certs are added to greenlock.
|
|
|
|
|
|
|
|
const domains: Array<StatusPageDomain> =
|
|
|
|
await StatusPageDomainService.findBy({
|
|
|
|
query: {
|
|
|
|
isAddedtoGreenlock: true,
|
|
|
|
},
|
|
|
|
select: {
|
|
|
|
_id: true,
|
|
|
|
fullDomain: true,
|
|
|
|
cnameVerificationToken: true,
|
|
|
|
},
|
|
|
|
limit: LIMIT_MAX,
|
|
|
|
skip: 0,
|
|
|
|
props: {
|
|
|
|
isRoot: true,
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
for (const domain of domains) {
|
|
|
|
logger.info(
|
|
|
|
`StatusPageCerts:RemoveCerts - Checking CNAME ${domain.fullDomain}`
|
|
|
|
);
|
|
|
|
|
|
|
|
// Check CNAME validation and if that fails. Remove certs from Greenlock.
|
|
|
|
const isValid: boolean = await isSslProvisioned(
|
|
|
|
domain.fullDomain!,
|
|
|
|
domain.cnameVerificationToken!
|
|
|
|
);
|
|
|
|
|
|
|
|
if (!isValid) {
|
|
|
|
await StatusPageDomainService.updateOneById({
|
|
|
|
id: domain.id!,
|
|
|
|
data: {
|
|
|
|
isSslProvisioned: false,
|
|
|
|
},
|
|
|
|
props: {
|
|
|
|
isRoot: true,
|
|
|
|
},
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
await StatusPageDomainService.updateOneById({
|
|
|
|
id: domain.id!,
|
|
|
|
data: {
|
|
|
|
isSslProvisioned: true,
|
|
|
|
},
|
|
|
|
props: {
|
|
|
|
isRoot: true,
|
|
|
|
},
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|
|
|
|
|
2022-12-08 14:52:17 +00:00
|
|
|
const checkCnameValidation: Function = async (
|
2022-12-07 06:44:17 +00:00
|
|
|
fulldomain: string,
|
|
|
|
token: string
|
|
|
|
): Promise<boolean> => {
|
2022-12-08 14:52:17 +00:00
|
|
|
try {
|
2022-12-11 09:10:17 +00:00
|
|
|
const result: AxiosResponse = await axios.get(
|
2023-01-02 08:26:51 +00:00
|
|
|
'http://' +
|
2023-03-02 19:36:06 +00:00
|
|
|
fulldomain +
|
|
|
|
'/status-page-api/cname-verification/' +
|
|
|
|
token
|
2022-12-09 08:19:51 +00:00
|
|
|
);
|
|
|
|
|
2022-12-08 14:52:17 +00:00
|
|
|
if (result.status === 200) {
|
|
|
|
return true;
|
2022-12-05 10:40:28 +00:00
|
|
|
}
|
2022-12-09 08:19:51 +00:00
|
|
|
return false;
|
2022-12-08 14:52:17 +00:00
|
|
|
} catch (err) {
|
2023-01-03 09:49:41 +00:00
|
|
|
logger.info('Failed checking for CNAME ' + fulldomain);
|
|
|
|
logger.info('Token: ' + token);
|
|
|
|
logger.info(err);
|
2022-12-09 08:19:51 +00:00
|
|
|
return false;
|
2022-12-08 14:52:17 +00:00
|
|
|
}
|
2022-12-07 06:44:17 +00:00
|
|
|
};
|
2022-12-05 10:40:28 +00:00
|
|
|
|
2022-12-08 16:23:21 +00:00
|
|
|
const isSslProvisioned: Function = async (
|
|
|
|
fulldomain: string,
|
|
|
|
token: string
|
|
|
|
): Promise<boolean> => {
|
|
|
|
try {
|
2022-12-11 09:10:17 +00:00
|
|
|
const result: AxiosResponse = await axios.get(
|
2022-12-09 08:19:51 +00:00
|
|
|
'https://' +
|
2023-03-02 19:36:06 +00:00
|
|
|
fulldomain +
|
|
|
|
'/status-page-api/cname-verification/' +
|
|
|
|
token
|
2022-12-09 08:19:51 +00:00
|
|
|
);
|
2022-12-08 16:23:21 +00:00
|
|
|
|
|
|
|
if (result.status === 200) {
|
|
|
|
return true;
|
|
|
|
}
|
2022-12-09 08:19:51 +00:00
|
|
|
return false;
|
2022-12-08 16:23:21 +00:00
|
|
|
} catch (err) {
|
2022-12-09 08:19:51 +00:00
|
|
|
return false;
|
2022-12-08 16:23:21 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2022-12-07 06:44:17 +00:00
|
|
|
export default router;
|