mirror of
https://github.com/OneUptime/oneuptime
synced 2024-11-22 23:30:10 +00:00
189 lines
6.6 KiB
TypeScript
189 lines
6.6 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 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
|
||
|
);
|
||
|
}
|
||
|
}
|