mirror of
https://github.com/louislam/uptime-kuma.git
synced 2024-12-26 22:19:43 -08:00
Feat: Add Barebones certificate info display
This commit is contained in:
parent
03b3bb5b30
commit
ccda6f05f5
|
@ -5,7 +5,7 @@ var timezone = require('dayjs/plugin/timezone')
|
||||||
dayjs.extend(utc)
|
dayjs.extend(utc)
|
||||||
dayjs.extend(timezone)
|
dayjs.extend(timezone)
|
||||||
const axios = require("axios");
|
const axios = require("axios");
|
||||||
const {tcping, ping} = require("../util-server");
|
const {tcping, ping, checkCertificate} = require("../util-server");
|
||||||
const {R} = require("redbean-node");
|
const {R} = require("redbean-node");
|
||||||
const {BeanModel} = require("redbean-node/dist/bean-model");
|
const {BeanModel} = require("redbean-node/dist/bean-model");
|
||||||
const {Notification} = require("../notification")
|
const {Notification} = require("../notification")
|
||||||
|
@ -74,6 +74,9 @@ class Monitor extends BeanModel {
|
||||||
})
|
})
|
||||||
bean.msg = `${res.status} - ${res.statusText}`
|
bean.msg = `${res.status} - ${res.statusText}`
|
||||||
bean.ping = dayjs().valueOf() - startTime;
|
bean.ping = dayjs().valueOf() - startTime;
|
||||||
|
if (this.url.startsWith("https")) {
|
||||||
|
Monitor.sendCertInfo(checkCertificate(res), io, this.id, this.user_id);
|
||||||
|
}
|
||||||
|
|
||||||
if (this.type === "http") {
|
if (this.type === "http") {
|
||||||
bean.status = 1;
|
bean.status = 1;
|
||||||
|
@ -189,6 +192,14 @@ class Monitor extends BeanModel {
|
||||||
io.to(userID).emit("avgPing", monitorID, avgPing);
|
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
|
* Uptime with calculation
|
||||||
* Calculation based on:
|
* Calculation based on:
|
||||||
|
|
|
@ -70,3 +70,53 @@ exports.getSettings = async function (type) {
|
||||||
|
|
||||||
return result;
|
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,
|
||||||
|
};
|
||||||
|
}
|
|
@ -25,6 +25,7 @@ export default {
|
||||||
importantHeartbeatList: { },
|
importantHeartbeatList: { },
|
||||||
avgPingList: { },
|
avgPingList: { },
|
||||||
uptimeList: { },
|
uptimeList: { },
|
||||||
|
certInfoList: {},
|
||||||
notificationList: [],
|
notificationList: [],
|
||||||
windowWidth: window.innerWidth,
|
windowWidth: window.innerWidth,
|
||||||
showListMobile: false,
|
showListMobile: false,
|
||||||
|
@ -114,6 +115,10 @@ export default {
|
||||||
this.uptimeList[`${monitorID}_${type}`] = data
|
this.uptimeList[`${monitorID}_${type}`] = data
|
||||||
});
|
});
|
||||||
|
|
||||||
|
socket.on('certInfo', (monitorID, data) => {
|
||||||
|
this.certInfoList[monitorID] = data
|
||||||
|
});
|
||||||
|
|
||||||
socket.on('importantHeartbeatList', (monitorID, data) => {
|
socket.on('importantHeartbeatList', (monitorID, data) => {
|
||||||
if (! (monitorID in this.importantHeartbeatList)) {
|
if (! (monitorID in this.importantHeartbeatList)) {
|
||||||
this.importantHeartbeatList[monitorID] = data;
|
this.importantHeartbeatList[monitorID] = data;
|
||||||
|
|
|
@ -54,6 +54,38 @@
|
||||||
</div>
|
</div>
|
||||||
</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">
|
<div class="shadow-box">
|
||||||
<table class="table table-borderless table-hover">
|
<table class="table table-borderless table-hover">
|
||||||
<thead>
|
<thead>
|
||||||
|
@ -180,6 +212,14 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
certInfo() {
|
||||||
|
if (this.$root.certInfoList[this.monitor.id]) {
|
||||||
|
return this.$root.certInfoList[this.monitor.id]
|
||||||
|
} else {
|
||||||
|
return { }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
displayedRecords() {
|
displayedRecords() {
|
||||||
const startIndex = this.perPage * (this.page - 1);
|
const startIndex = this.perPage * (this.page - 1);
|
||||||
const endIndex = startIndex + this.perPage;
|
const endIndex = startIndex + this.perPage;
|
||||||
|
|
Loading…
Reference in a new issue