oneuptime/Ingestor/Utils/Monitor.ts

180 lines
5.3 KiB
TypeScript

import Hostname from "Common/Types/API/Hostname";
import URL from "Common/Types/API/URL";
import { LIMIT_PER_PROJECT } from "Common/Types/Database/LimitMax";
import Dictionary from "Common/Types/Dictionary";
import { PromiseVoidFunction } from "Common/Types/FunctionTypes";
import IP from "Common/Types/IP/IP";
import { JSONObject } from "Common/Types/JSON";
import JSONFunctions from "Common/Types/JSONFunctions";
import MonitorType from "Common/Types/Monitor/MonitorType";
import MonitorSecretService from "CommonServer/Services/MonitorSecretService";
import VMUtil from "CommonServer/Utils/VM/VMAPI";
import Monitor from "Model/Models/Monitor";
import MonitorSecret from "Model/Models/MonitorSecret";
export default class MonitorUtil {
public static async populateSecrets(monitor: Monitor): Promise<Monitor> {
const isSecretsLoaded: boolean = false;
let monitorSecrets: MonitorSecret[] = [];
const loadSecrets: PromiseVoidFunction = async (): Promise<void> => {
if (isSecretsLoaded) {
return;
}
if (!monitor.id) {
return;
}
const secrets: Array<MonitorSecret> = await MonitorSecretService.findBy({
query: {
monitors: [monitor.id] as any,
},
select: {
secretValue: true,
name: true,
},
limit: LIMIT_PER_PROJECT,
skip: 0,
props: {
isRoot: true,
},
});
monitorSecrets = secrets;
};
if (!monitor.monitorSteps) {
return monitor;
}
if (monitor.monitorType === MonitorType.API) {
for (const monitorStep of monitor.monitorSteps?.data
?.monitorStepsInstanceArray || []) {
if (
monitorStep.data?.requestHeaders &&
this.hasSecrets(
JSONFunctions.toString(monitorStep.data.requestHeaders),
)
) {
await loadSecrets();
monitorStep.data.requestHeaders =
(await MonitorUtil.fillSecretsInStringOrJSON({
secrets: monitorSecrets,
populateSecretsIn: monitorStep.data.requestHeaders,
})) as Dictionary<string>;
} else if (
monitorStep.data?.requestBody &&
this.hasSecrets(JSONFunctions.toString(monitorStep.data.requestBody))
) {
await loadSecrets();
monitorStep.data.requestBody =
(await MonitorUtil.fillSecretsInStringOrJSON({
secrets: monitorSecrets,
populateSecretsIn: monitorStep.data.requestBody,
})) as string;
}
}
}
if (
monitor.monitorType === MonitorType.API ||
monitor.monitorType === MonitorType.IP ||
monitor.monitorType === MonitorType.Ping ||
monitor.monitorType === MonitorType.Port ||
monitor.monitorType === MonitorType.Website ||
monitor.monitorType === MonitorType.SSLCertificate
) {
for (const monitorStep of monitor.monitorSteps?.data
?.monitorStepsInstanceArray || []) {
if (
monitorStep.data?.monitorDestination &&
this.hasSecrets(
JSONFunctions.toString(monitorStep.data.monitorDestination),
)
) {
// replace secret in monitorDestination.
await loadSecrets();
monitorStep.data.monitorDestination =
(await MonitorUtil.fillSecretsInStringOrJSON({
secrets: monitorSecrets,
populateSecretsIn: monitorStep.data.monitorDestination,
})) as URL | Hostname | IP;
}
}
}
if (
monitor.monitorType === MonitorType.SyntheticMonitor ||
monitor.monitorType === MonitorType.CustomJavaScriptCode
) {
for (const monitorStep of monitor.monitorSteps?.data
?.monitorStepsInstanceArray || []) {
if (
monitorStep.data?.customCode &&
this.hasSecrets(JSONFunctions.toString(monitorStep.data.customCode))
) {
// replace secret in script
await loadSecrets();
monitorStep.data.customCode =
(await MonitorUtil.fillSecretsInStringOrJSON({
secrets: monitorSecrets,
populateSecretsIn: monitorStep.data.customCode,
})) as string;
}
}
}
return monitor;
}
private static hasSecrets(prepopulatedString: string): boolean {
return prepopulatedString.includes("monitorSecrets.");
}
private static async fillSecretsInStringOrJSON(data: {
secrets: MonitorSecret[];
populateSecretsIn: string | JSONObject | URL | Hostname | IP;
}): Promise<string | JSONObject | URL | Hostname | IP> {
// get all secrets for this monitor.
const secrets: MonitorSecret[] = data.secrets;
if (secrets.length === 0) {
return data.populateSecretsIn;
}
// replace all secrets in the populateSecretsIn
const storageMap: JSONObject = {
monitorSecrets: {},
};
for (const monitorSecret of secrets) {
if (!monitorSecret.name) {
continue;
}
if (!monitorSecret.secretValue) {
continue;
}
(storageMap["monitorSecrets"] as JSONObject)[
monitorSecret.name as string
] = monitorSecret.secretValue;
}
const isValueJSON: boolean = typeof data.populateSecretsIn === "object";
return VMUtil.replaceValueInPlace(
storageMap,
data.populateSecretsIn as string,
isValueJSON,
);
}
}