diff --git a/App/FeatureSet/Workers/Jobs/StatusPageCerts/StatusPageCerts.ts b/App/FeatureSet/Workers/Jobs/StatusPageCerts/StatusPageCerts.ts index e4980839b7..e0f98997d1 100644 --- a/App/FeatureSet/Workers/Jobs/StatusPageCerts/StatusPageCerts.ts +++ b/App/FeatureSet/Workers/Jobs/StatusPageCerts/StatusPageCerts.ts @@ -50,7 +50,7 @@ RunCron( }, fn: async (span: Span): Promise => { try { - logger.info("Ordering SSL for domains which are not ordered yet"); + logger.debug("Ordering SSL for domains which are not ordered yet"); await StatusPageDomainService.orderSSLForDomainsWhichAreNotOrderedYet(); Telemetry.endSpan(span); diff --git a/Common/Server/Services/StatusPageDomainService.ts b/Common/Server/Services/StatusPageDomainService.ts index 0e2610cc2f..a1660208e8 100644 --- a/Common/Server/Services/StatusPageDomainService.ts +++ b/Common/Server/Services/StatusPageDomainService.ts @@ -125,6 +125,10 @@ export class Service extends DatabaseService { ); } + logger.debug( + "Ordering SSL for domain: " + statusPageDomain.fullDomain, + ); + await GreenlockUtil.orderCert({ domain: statusPageDomain.fullDomain as string, validateCname: async (fullDomain: string) => { @@ -132,6 +136,10 @@ export class Service extends DatabaseService { }, }); + logger.debug( + "SSL ordered for domain: " + statusPageDomain.fullDomain, + ); + // update the order. await this.updateOneById({ id: statusPageDomain.id!, @@ -238,6 +246,8 @@ export class Service extends DatabaseService { try { // get the token from the domain. + logger.debug("Checking for CNAME " + fullDomain); + const statusPageDomain: StatusPageDomain | null = await this.findOneBy({ query: { fullDomain: fullDomain, @@ -257,6 +267,8 @@ export class Service extends DatabaseService { const token: string = statusPageDomain.cnameVerificationToken!; + logger.debug("Checking for CNAME " + fullDomain + " with token " + token); + const result: HTTPErrorResponse | HTTPResponse = await API.get( URL.fromString( @@ -267,6 +279,9 @@ export class Service extends DatabaseService { ), ); + logger.debug("CNAME verification result"); + logger.debug(result); + if (result.isSuccess()) { await this.updateCnameStatusForStatusPageDomain({ domain: fullDomain, @@ -275,8 +290,6 @@ export class Service extends DatabaseService { return true; } - logger.debug("CNAME verification failed for http endpoint"); - logger.debug(result); // try with https @@ -290,6 +303,9 @@ export class Service extends DatabaseService { ), ); + logger.debug("CNAME verification result for https"); + logger.debug(resultHttps); + if (resultHttps.isSuccess()) { await this.updateCnameStatusForStatusPageDomain({ domain: fullDomain, @@ -298,8 +314,6 @@ export class Service extends DatabaseService { return true; } - logger.debug("CNAME verification fails for https endpoint"); - logger.debug(resultHttps); await this.updateCnameStatusForStatusPageDomain({ domain: fullDomain, @@ -419,6 +433,7 @@ export class Service extends DatabaseService { for (const domain of domains) { try { + logger.debug("Ordering SSL for domain: " + domain.fullDomain); await this.orderCert(domain); } catch (e) { logger.error(e); diff --git a/Common/Server/Utils/Greenlock/Greenlock.ts b/Common/Server/Utils/Greenlock/Greenlock.ts index 66f7faed79..1e5142d46d 100644 --- a/Common/Server/Utils/Greenlock/Greenlock.ts +++ b/Common/Server/Utils/Greenlock/Greenlock.ts @@ -24,64 +24,107 @@ export default class GreenlockUtil { validateCname: (domain: string) => Promise; notifyDomainRemoved: (domain: string) => Promise; }): Promise { - logger.debug("Renewing all certificates"); + return await Telemetry.startActiveSpan>({ + name: "GreenlockUtil.renewAllCertsWhichAreExpiringSoon", + fn: async (span: Span): Promise => { + try { + logger.debug("Renewing all certificates"); - // get all certificates which are expiring soon + // get all certificates which are expiring soon - const certificates: AcmeCertificate[] = await AcmeCertificateService.findBy( - { - query: { - expiresAt: QueryHelper.lessThanEqualTo( - OneUptimeDate.addRemoveDays( - OneUptimeDate.getCurrentDate(), - 40, // 40 days before expiry - ), - ), - }, - limit: LIMIT_MAX, - skip: 0, - select: { - domain: true, - }, - sort: { - expiresAt: SortOrder.Ascending, - }, - props: { - isRoot: true, - }, - }, - ); + const certificates: AcmeCertificate[] = + await AcmeCertificateService.findBy({ + query: { + expiresAt: QueryHelper.lessThanEqualTo( + OneUptimeDate.addRemoveDays( + OneUptimeDate.getCurrentDate(), + 40, // 40 days before expiry + ), + ), + }, + limit: LIMIT_MAX, + skip: 0, + select: { + domain: true, + }, + sort: { + expiresAt: SortOrder.Ascending, + }, + props: { + isRoot: true, + }, + }); - // order certificate for each domain + logger.debug( + `Found ${certificates.length} certificates which are expiring soon`, + ); - for (const certificate of certificates) { - if (!certificate.domain) { - continue; - } + // order certificate for each domain - try { - //validate cname - const isValidCname: boolean = await data.validateCname( - certificate.domain, - ); + for (const certificate of certificates) { + if (!certificate.domain) { + continue; + } - if (!isValidCname) { - // if cname is not valid then remove the domain - await GreenlockUtil.removeDomain(certificate.domain); - await data.notifyDomainRemoved(certificate.domain); - } else { - await GreenlockUtil.orderCert({ - domain: certificate.domain, - validateCname: data.validateCname, + logger.debug( + `Renewing certificate for domain: ${certificate.domain}`, + ); + + try { + //validate cname + const isValidCname: boolean = await data.validateCname( + certificate.domain, + ); + + if (!isValidCname) { + logger.debug( + `CNAME is not valid for domain: ${certificate.domain}`, + ); + + // if cname is not valid then remove the domain + await GreenlockUtil.removeDomain(certificate.domain); + await data.notifyDomainRemoved(certificate.domain); + + logger.error( + `Cname is not valid for domain: ${certificate.domain}`, + ); + } else { + logger.debug( + `CNAME is valid for domain: ${certificate.domain}`, + ); + + await GreenlockUtil.orderCert({ + domain: certificate.domain, + validateCname: data.validateCname, + }); + + logger.debug( + `Certificate renewed for domain: ${certificate.domain}`, + ); + } + } catch (e) { + logger.error( + `Error renewing certificate for domain: ${certificate.domain}`, + ); + logger.error(e); + } + } + + Telemetry.endSpan(span); + } catch (e) { + logger.error("Error renewing all certificates"); + logger.error(e); + + // record exception + Telemetry.recordExceptionMarkSpanAsErrorAndEndSpan({ + span, + exception: e, }); + + throw e; } - } catch (e) { - logger.error( - `Error renewing certificate for domain: ${certificate.domain}`, - ); - logger.error(e); - } - } + }, + }); } public static async removeDomain(domain: string): Promise { @@ -134,6 +177,10 @@ export default class GreenlockUtil { }, fn: async (span: Span): Promise => { try { + logger.debug( + `GreenlockUtil - Ordering certificate for domain: ${data.domain}`, + ); + let { domain } = data; domain = domain.trim().toLowerCase(); @@ -155,9 +202,14 @@ export default class GreenlockUtil { //validate cname + logger.debug(`Validating cname for domain: ${domain}`); + const isValidCname: boolean = await data.validateCname(domain); if (!isValidCname) { + logger.debug(`CNAME is not valid for domain: ${domain}`); + logger.debug(`Removing domain: ${domain}`); + await GreenlockUtil.removeDomain(domain); logger.error(`Cname is not valid for domain: ${domain}`); throw new BadDataException( @@ -165,6 +217,8 @@ export default class GreenlockUtil { ); } + logger.debug(`Cname is valid for domain: ${domain}`); + const client: acme.Client = new acme.Client({ directoryUrl: acme.directory.letsencrypt.production, accountKey: acmeAccountKey, @@ -175,6 +229,8 @@ export default class GreenlockUtil { commonName: domain, }); + logger.debug(`Ordering certificate for domain: ${domain}`); + const certificate: string = await client.auto({ csr: certificateRequest, email: LetsEncryptNotificationEmail.toString(), @@ -188,6 +244,10 @@ export default class GreenlockUtil { // Satisfy challenge here /* http-01 */ if (challenge.type === "http-01") { + logger.debug( + `Creating challenge for domain: ${authz.identifier.value}`, + ); + const acmeChallenge: AcmeChallenge = new AcmeChallenge(); acmeChallenge.challenge = keyAuthorization; acmeChallenge.token = challenge.token; @@ -199,6 +259,10 @@ export default class GreenlockUtil { isRoot: true, }, }); + + logger.debug( + `Challenge created for domain: ${authz.identifier.value}`, + ); } }, challengeRemoveFn: async ( @@ -207,6 +271,10 @@ export default class GreenlockUtil { ) => { // Clean up challenge here + logger.debug( + `Removing challenge for domain: ${authz.identifier.value}`, + ); + if (challenge.type === "http-01") { await AcmeChallengeService.deleteBy({ query: { @@ -219,15 +287,24 @@ export default class GreenlockUtil { }, }); } + + logger.debug( + `Challenge removed for domain: ${authz.identifier.value}`, + ); }, }); + logger.debug(`Certificate ordered for domain: ${domain}`); + // get expires at date from certificate const cert: acme.CertificateInfo = acme.crypto.readCertificateInfo(certificate); const issuedAt: Date = cert.notBefore; const expiresAt: Date = cert.notAfter; + logger.debug(`Certificate expires at: ${expiresAt}`); + logger.debug(`Certificate issued at: ${issuedAt}`); + // check if the certificate is already in the database. const existingCertificate: AcmeCertificate | null = await AcmeCertificateService.findOneBy({ @@ -243,6 +320,8 @@ export default class GreenlockUtil { }); if (existingCertificate) { + logger.debug(`Updating certificate for domain: ${domain}`); + // update the certificate await AcmeCertificateService.updateBy({ query: { @@ -260,7 +339,10 @@ export default class GreenlockUtil { isRoot: true, }, }); + + logger.debug(`Certificate updated for domain: ${domain}`); } else { + logger.debug(`Creating certificate for domain: ${domain}`); // create the certificate const acmeCertificate: AcmeCertificate = new AcmeCertificate(); @@ -276,6 +358,8 @@ export default class GreenlockUtil { isRoot: true, }, }); + + logger.debug(`Certificate created for domain: ${domain}`); } Telemetry.endSpan(span); diff --git a/Common/UI/Components/GanttChart/Row/Row.tsx b/Common/UI/Components/GanttChart/Row/Row.tsx index 499d366ee1..b8ee062ce1 100644 --- a/Common/UI/Components/GanttChart/Row/Row.tsx +++ b/Common/UI/Components/GanttChart/Row/Row.tsx @@ -50,8 +50,10 @@ const Row: FunctionComponent = (
-
-
+
+
{hasChildRows && ( = ( return ( // rectangle div with curved corners and text inside in tailwindcss -
-
{props.title}
-
{props.description}
+
+
+ {props.title} +
+
+ {props.description} +
); }; diff --git a/Dashboard/src/Components/Traces/TraceExplorer.tsx b/Dashboard/src/Components/Traces/TraceExplorer.tsx index f12c2b0446..4a95e92f6d 100644 --- a/Dashboard/src/Components/Traces/TraceExplorer.tsx +++ b/Dashboard/src/Components/Traces/TraceExplorer.tsx @@ -319,7 +319,7 @@ const TraceExplorer: FunctionComponent = ( const rootRow: GanttChartRow = { rowInfo: { - title:
{rootSpan.name!}
, + title:
{rootSpan.name!}
, description: telemetryService ? ( getRowDescription({ telemetryService,