Add ssl-checker, refactor fetchMonitorCertificate
This commit is contained in:
1 parent
d8e2b06eca
commit
79cf169ede
5 files changed
+42
-114
No files matched your search
@@ -12,32 +12,15 @@ const handleError = (error, serviceName, method, status = 500) => {
|
||||
return error;
|
||||
};
|
||||
|
||||
const fetchMonitorCertificate = async (tls, monitor) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const fetchMonitorCertificate = async (sslChecker, monitor) => {
|
||||
try {
|
||||
const monitorUrl = new URL(monitor.url);
|
||||
const hostname = monitorUrl.hostname;
|
||||
try {
|
||||
let socket = tls.connect(
|
||||
{
|
||||
port: 443,
|
||||
host: hostname,
|
||||
servername: hostname, // this is required in case the server enabled SNI
|
||||
},
|
||||
() => {
|
||||
try {
|
||||
let x509Certificate = socket.getPeerX509Certificate();
|
||||
resolve(x509Certificate);
|
||||
} catch (error) {
|
||||
reject(error);
|
||||
} finally {
|
||||
socket.end();
|
||||
}
|
||||
}
|
||||
);
|
||||
} catch (error) {
|
||||
reject(error);
|
||||
}
|
||||
});
|
||||
const cert = await sslChecker(hostname);
|
||||
return cert;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
export { handleValidationError, handleError, fetchMonitorCertificate };
|
||||
@@ -12,18 +12,14 @@ import {
|
||||
getMonitorStatsByIdQueryValidation,
|
||||
getCertificateParamValidation,
|
||||
} from "../validation/joi.js";
|
||||
import * as tls from "tls";
|
||||
import sslChecker from "ssl-checker";
|
||||
|
||||
const SERVICE_NAME = "monitorController";
|
||||
import { errorMessages, successMessages } from "../utils/messages.js";
|
||||
import jwt from "jsonwebtoken";
|
||||
import { getTokenFromHeaders } from "../utils/utils.js";
|
||||
import logger from "../utils/logger.js";
|
||||
import {
|
||||
handleError,
|
||||
handleValidationError,
|
||||
fetchMonitorCertificate,
|
||||
} from "./controllerUtils.js";
|
||||
import { handleError, handleValidationError } from "./controllerUtils.js";
|
||||
|
||||
/**
|
||||
* Returns all monitors
|
||||
@@ -87,7 +83,7 @@ const getMonitorCertificate = async (req, res, next, fetchMonitorCertificate) =>
|
||||
try {
|
||||
const { monitorId } = req.params;
|
||||
const monitor = await req.db.getMonitorById(monitorId);
|
||||
const certificate = await fetchMonitorCertificate(tls, monitor);
|
||||
const certificate = await fetchMonitorCertificate(sslChecker, monitor);
|
||||
if (certificate && certificate.validTo) {
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
|
||||
Generated
+7
@@ -27,6 +27,7 @@
|
||||
"nodemailer": "^6.9.14",
|
||||
"ping": "0.4.4",
|
||||
"sharp": "0.33.4",
|
||||
"ssl-checker": "2.0.10",
|
||||
"swagger-ui-express": "5.0.1",
|
||||
"winston": "^3.13.0"
|
||||
},
|
||||
@@ -6002,6 +6003,12 @@
|
||||
"memory-pager": "^1.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/ssl-checker": {
|
||||
"version": "2.0.10",
|
||||
"resolved": "https://registry.npmjs.org/ssl-checker/-/ssl-checker-2.0.10.tgz",
|
||||
"integrity": "sha512-SS6rrZocToJWHM1p6iVNb583ybB3UqT1fymCHSWuEdXDUqKA6O1D5Fb8KJVmhj3XKXE82IEWcr+idJrc4jUzFQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/stack-trace": {
|
||||
"version": "0.0.10",
|
||||
"resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz",
|
||||
|
||||
+4
-3
@@ -30,16 +30,17 @@
|
||||
"nodemailer": "^6.9.14",
|
||||
"ping": "0.4.4",
|
||||
"sharp": "0.33.4",
|
||||
"ssl-checker": "2.0.10",
|
||||
"swagger-ui-express": "5.0.1",
|
||||
"winston": "^3.13.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"prettier": "^3.3.3",
|
||||
"chai": "5.1.1",
|
||||
"mocha": "10.7.3",
|
||||
"c8": "10.1.2",
|
||||
"chai": "5.1.1",
|
||||
"esm": "3.2.25",
|
||||
"mocha": "10.7.3",
|
||||
"nodemon": "3.1.0",
|
||||
"prettier": "^3.3.3",
|
||||
"sinon": "19.0.2"
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,9 @@ import {
|
||||
fetchMonitorCertificate,
|
||||
} from "../../controllers/controllerUtils.js";
|
||||
import { expect } from "chai";
|
||||
import sslChecker from "ssl-checker";
|
||||
import { afterEach } from "node:test";
|
||||
import exp from "constants";
|
||||
|
||||
describe("controllerUtils - handleValidationError", () => {
|
||||
it("should set status to 422", () => {
|
||||
@@ -109,102 +112,40 @@ describe("controllerUtils - handleError", () => {
|
||||
});
|
||||
|
||||
describe("controllerUtils - fetchMonitorCertificate", () => {
|
||||
const originalTls = {
|
||||
connect: sinon.stub().callsFake((options, callback) => {
|
||||
// Create socket stub with sinon stubs for all methods
|
||||
socket = {
|
||||
getPeerX509Certificate: sinon.stub().returns({
|
||||
subject: "CN=fake-cert",
|
||||
validTo: "Dec 31 23:59:59 2023 GMT",
|
||||
}),
|
||||
end: sinon.stub(),
|
||||
on: sinon.stub(),
|
||||
};
|
||||
|
||||
// Use process.nextTick to ensure async behavior
|
||||
process.nextTick(() => {
|
||||
callback.call(socket); // Ensure correct 'this' binding
|
||||
});
|
||||
|
||||
return socket;
|
||||
}),
|
||||
};
|
||||
|
||||
let tls, monitor, socket;
|
||||
let sslChecker, monitor;
|
||||
beforeEach(() => {
|
||||
monitor = { url: "https://www.google.com" };
|
||||
tls = {
|
||||
connect: sinon.stub().callsFake((options, callback) => {
|
||||
// Create socket stub with sinon stubs for all methods
|
||||
socket = {
|
||||
getPeerX509Certificate: sinon.stub().returns({
|
||||
subject: "CN=fake-cert",
|
||||
validTo: "Dec 31 23:59:59 2023 GMT",
|
||||
}),
|
||||
end: sinon.stub(),
|
||||
on: sinon.stub(),
|
||||
};
|
||||
|
||||
// Use process.nextTick to ensure async behavior
|
||||
process.nextTick(() => {
|
||||
callback.call(socket); // Ensure correct 'this' binding
|
||||
});
|
||||
|
||||
return socket;
|
||||
}),
|
||||
monitor = {
|
||||
url: "https://www.google.com",
|
||||
};
|
||||
sslChecker = sinon.stub();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
tls = { ...originalTls };
|
||||
sinon.restore();
|
||||
});
|
||||
|
||||
it("should resolve with the certificate when the connection is successful", async () => {
|
||||
const certificate = await fetchMonitorCertificate(tls, monitor);
|
||||
expect(certificate.validTo).to.equal("Dec 31 23:59:59 2023 GMT");
|
||||
expect(socket.end.calledOnce).to.be.true;
|
||||
});
|
||||
|
||||
it("should reject with an error when the connection fails", async () => {
|
||||
tls.connect = sinon.stub().throws(new Error("Connection error"));
|
||||
it("should reject with an error if a URL does not parse", async () => {
|
||||
monitor.url = "invalidurl";
|
||||
try {
|
||||
await fetchMonitorCertificate(tls, monitor);
|
||||
} catch (error) {
|
||||
expect(error.message).to.equal("Connection error");
|
||||
}
|
||||
});
|
||||
|
||||
it("should reject with an error if monitorURL is invalid", async () => {
|
||||
monitor.url = "invalid-url";
|
||||
try {
|
||||
await fetchMonitorCertificate(tls, monitor);
|
||||
await fetchMonitorCertificate(sslChecker, monitor);
|
||||
} catch (error) {
|
||||
expect(error).to.be.an("error");
|
||||
expect(error.message).to.equal("Invalid URL");
|
||||
}
|
||||
});
|
||||
it("should do a thing", async () => {
|
||||
tls = {
|
||||
connect: sinon.stub().callsFake((options, callback) => {
|
||||
// Create socket stub with sinon stubs for all methods
|
||||
socket = {
|
||||
getPeerX509Certificate: sinon.stub().throws(new Error("Certificate error")),
|
||||
end: sinon.stub(),
|
||||
on: sinon.stub(),
|
||||
};
|
||||
|
||||
// Use process.nextTick to ensure async behavior
|
||||
process.nextTick(() => {
|
||||
callback.call(socket); // Ensure correct 'this' binding
|
||||
});
|
||||
|
||||
return socket;
|
||||
}),
|
||||
};
|
||||
it("should reject with an error if sslChecker throws an error", async () => {
|
||||
sslChecker.rejects(new Error("Test error"));
|
||||
try {
|
||||
await fetchMonitorCertificate(tls, monitor);
|
||||
await fetchMonitorCertificate(sslChecker, monitor);
|
||||
} catch (error) {
|
||||
expect(error.message).to.equal("Certificate error");
|
||||
expect(error).to.be.an("error");
|
||||
expect(error.message).to.equal("Test error");
|
||||
}
|
||||
});
|
||||
it("should return a certificate if sslChecker resolves", async () => {
|
||||
sslChecker.resolves({ validTo: "2022-01-01" });
|
||||
const result = await fetchMonitorCertificate(sslChecker, monitor);
|
||||
expect(result).to.deep.equal({ validTo: "2022-01-01" });
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user