oneuptime/Ingestor/Utils/Monitor.ts

189 lines
6.6 KiB
TypeScript
Raw Normal View History

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 QueryHelper from 'CommonServer/Types/Database/QueryHelper';
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: QueryHelper.in([monitor.id]),
},
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
);
}
}