Skip to content

Commit

Permalink
Feat: Add Barebones certificate info display
Browse files Browse the repository at this point in the history
  • Loading branch information
cch-aecomhk committed Jul 22, 2021
1 parent 03b3bb5 commit ccda6f0
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 1 deletion.
13 changes: 12 additions & 1 deletion server/model/monitor.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ var timezone = require('dayjs/plugin/timezone')
dayjs.extend(utc)
dayjs.extend(timezone)
const axios = require("axios");
const {tcping, ping} = require("../util-server");
const {tcping, ping, checkCertificate} = require("../util-server");
const {R} = require("redbean-node");
const {BeanModel} = require("redbean-node/dist/bean-model");
const {Notification} = require("../notification")
Expand Down Expand Up @@ -74,6 +74,9 @@ class Monitor extends BeanModel {
})
bean.msg = `${res.status} - ${res.statusText}`
bean.ping = dayjs().valueOf() - startTime;
if (this.url.startsWith("https")) {
Monitor.sendCertInfo(checkCertificate(res), io, this.id, this.user_id);
}

if (this.type === "http") {
bean.status = 1;
Expand Down Expand Up @@ -189,6 +192,14 @@ class Monitor extends BeanModel {
io.to(userID).emit("avgPing", monitorID, avgPing);
}

/**
*
* @param checkCertificateResult : Object return result of checkCertificate
*/
static async sendCertInfo(checkCertificateResult, io, monitorID, userID) {
io.to(userID).emit("certInfo", monitorID, checkCertificateResult);
}

/**
* Uptime with calculation
* Calculation based on:
Expand Down
50 changes: 50 additions & 0 deletions server/util-server.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,3 +70,53 @@ exports.getSettings = async function (type) {

return result;
}


// ssl-checker by @dyaa
// param: res - response object from axios
// return an object containing the certificate information

const getDaysBetween = (validFrom, validTo) =>
Math.round(Math.abs(+validFrom - +validTo) / 8.64e7);

const getDaysRemaining = (validFrom, validTo) => {
const daysRemaining = getDaysBetween(validFrom, validTo);
if (new Date(validTo).getTime() < new Date().getTime()) {
return -daysRemaining;
}
return daysRemaining;
};

exports.checkCertificate = function (res) {
const {
valid_from,
valid_to,
subjectaltname,
issuer,
fingerprint,
} = res.request.res.socket.getPeerCertificate(false);

if (!valid_from || !valid_to || !subjectaltname) {
reject(new Error('No certificate'));
return;
}

const valid = res.request.res.socket.authorized || false;

const validTo = new Date(valid_to);

const validFor = subjectaltname
.replace(/DNS:|IP Address:/g, "")
.split(", ");

const daysRemaining = getDaysRemaining(new Date(), validTo);

return {
valid,
validFor,
validTo,
daysRemaining,
issuer,
fingerprint,
};
}
5 changes: 5 additions & 0 deletions src/mixins/socket.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export default {
importantHeartbeatList: { },
avgPingList: { },
uptimeList: { },
certInfoList: {},
notificationList: [],
windowWidth: window.innerWidth,
showListMobile: false,
Expand Down Expand Up @@ -114,6 +115,10 @@ export default {
this.uptimeList[`${monitorID}_${type}`] = data
});

socket.on('certInfo', (monitorID, data) => {
this.certInfoList[monitorID] = data
});

socket.on('importantHeartbeatList', (monitorID, data) => {
if (! (monitorID in this.importantHeartbeatList)) {
this.importantHeartbeatList[monitorID] = data;
Expand Down
40 changes: 40 additions & 0 deletions src/pages/Details.vue
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,38 @@
</div>
</div>

<div class="shadow-box big-padding text-center stats" v-if="monitor.type === 'http' && monitor.url.startsWith('https') && certInfo != null">
<div class="row">
<div class="col">
<h4>Certificate Info</h4>
<table class="text-start">
<tbody>
<tr class="my-3">
<td class="px-3">Valid: </td>
<td>{{ certInfo.valid }}</td>
</tr>
<tr class="my-3">
<td class="px-3">Valid To: </td>
<td>{{ certInfo.validTo ? new Date(certInfo.validTo).toLocaleString() : "" }}</td>
</tr>
<tr class="my-3">
<td class="px-3">Days Remaining: </td>
<td>{{ certInfo.daysRemaining }}</td>
</tr>
<tr class="my-3">
<td class="px-3">Issuer: </td>
<td>{{ certInfo.issuer }}</td>
</tr>
<tr class="my-3">
<td class="px-3">Fingerprint: </td>
<td>{{ certInfo.fingerprint }}</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>

<div class="shadow-box">
<table class="table table-borderless table-hover">
<thead>
Expand Down Expand Up @@ -180,6 +212,14 @@ export default {
}
},
certInfo() {
if (this.$root.certInfoList[this.monitor.id]) {
return this.$root.certInfoList[this.monitor.id]
} else {
return { }
}
},
displayedRecords() {
const startIndex = this.perPage * (this.page - 1);
const endIndex = startIndex + this.perPage;
Expand Down

0 comments on commit ccda6f0

Please sign in to comment.