mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
[Security Solution] [Detections] Adds metrics to some warning messages written to rule execution logger (#167551)
## Summary Ref: https://github.com/elastic/kibana/issues/166971 Warning messages such as "max signals reached" or "rule may not have read access to these indices" can now write metrics (if available) to the rule execution logger. Warning message: <img width="1124" alt="warning_no_access_to_logs_index" src="70b63a47
-3e54-45b1-ba49-da531595e47e"> Metrics: <img width="1669" alt="metrics_no_access_to_logs_index" src="eac91dff
-316a-4587-bab9-c816947be00e">
This commit is contained in:
parent
1980beecf3
commit
5364b9f887
2 changed files with 55 additions and 20 deletions
|
@ -182,6 +182,7 @@ export const createSecurityRuleTypeWrapper: CreateSecurityRuleTypeWrapper =
|
|||
|
||||
let result = createResultObject(state);
|
||||
let wroteWarningStatus = false;
|
||||
let warningMessage;
|
||||
let hasError = false;
|
||||
|
||||
const primaryTimestamp = timestampOverride ?? TIMESTAMP;
|
||||
|
@ -250,11 +251,15 @@ export const createSecurityRuleTypeWrapper: CreateSecurityRuleTypeWrapper =
|
|||
if (!isMachineLearningParams(params)) {
|
||||
const privileges = await checkPrivilegesFromEsClient(esClient, inputIndex);
|
||||
|
||||
wroteWarningStatus = await hasReadIndexPrivileges({
|
||||
privileges,
|
||||
ruleExecutionLogger,
|
||||
uiSettingsClient,
|
||||
});
|
||||
const { wroteWarningMessage, warningStatusMessage: readIndexWarningMessage } =
|
||||
await hasReadIndexPrivileges({
|
||||
privileges,
|
||||
ruleExecutionLogger,
|
||||
uiSettingsClient,
|
||||
});
|
||||
|
||||
wroteWarningStatus = wroteWarningMessage;
|
||||
warningMessage = readIndexWarningMessage;
|
||||
|
||||
if (!wroteWarningStatus) {
|
||||
const timestampFieldCaps = await withSecuritySpan('fieldCaps', () =>
|
||||
|
@ -272,14 +277,18 @@ export const createSecurityRuleTypeWrapper: CreateSecurityRuleTypeWrapper =
|
|||
)
|
||||
);
|
||||
|
||||
const { wroteWarningStatus: wroteWarningStatusResult, foundNoIndices } =
|
||||
await hasTimestampFields({
|
||||
timestampField: primaryTimestamp,
|
||||
timestampFieldCapsResponse: timestampFieldCaps,
|
||||
inputIndices: inputIndex,
|
||||
ruleExecutionLogger,
|
||||
});
|
||||
const {
|
||||
wroteWarningStatus: wroteWarningStatusResult,
|
||||
foundNoIndices,
|
||||
warningMessage: warningMissingTimestampFieldsMessage,
|
||||
} = await hasTimestampFields({
|
||||
timestampField: primaryTimestamp,
|
||||
timestampFieldCapsResponse: timestampFieldCaps,
|
||||
inputIndices: inputIndex,
|
||||
ruleExecutionLogger,
|
||||
});
|
||||
wroteWarningStatus = wroteWarningStatusResult;
|
||||
warningMessage = warningMissingTimestampFieldsMessage;
|
||||
skipExecution = foundNoIndices;
|
||||
}
|
||||
}
|
||||
|
@ -447,6 +456,11 @@ export const createSecurityRuleTypeWrapper: CreateSecurityRuleTypeWrapper =
|
|||
await ruleExecutionLogger.logStatusChange({
|
||||
newStatus: RuleExecutionStatus['partial failure'],
|
||||
message: truncateList(result.warningMessages).join(),
|
||||
metrics: {
|
||||
searchDurations: result.searchAfterTimes,
|
||||
indexingDurations: result.bulkCreateTimes,
|
||||
enrichmentDurations: result.enrichmentTimes,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -474,6 +488,16 @@ export const createSecurityRuleTypeWrapper: CreateSecurityRuleTypeWrapper =
|
|||
enrichmentDurations: result.enrichmentTimes,
|
||||
},
|
||||
});
|
||||
} else if (wroteWarningStatus && !hasError && !result.warning) {
|
||||
await ruleExecutionLogger.logStatusChange({
|
||||
newStatus: RuleExecutionStatus['partial failure'],
|
||||
message: warningMessage,
|
||||
metrics: {
|
||||
searchDurations: result.searchAfterTimes,
|
||||
indexingDurations: result.bulkCreateTimes,
|
||||
enrichmentDurations: result.enrichmentTimes,
|
||||
},
|
||||
});
|
||||
}
|
||||
} else {
|
||||
await ruleExecutionLogger.logStatusChange({
|
||||
|
|
|
@ -71,7 +71,7 @@ export const hasReadIndexPrivileges = async (args: {
|
|||
privileges: Privilege;
|
||||
ruleExecutionLogger: IRuleExecutionLogForExecutors;
|
||||
uiSettingsClient: IUiSettingsClient;
|
||||
}): Promise<boolean> => {
|
||||
}): Promise<{ wroteWarningMessage: boolean; warningStatusMessage: string | undefined }> => {
|
||||
const { privileges, ruleExecutionLogger, uiSettingsClient } = args;
|
||||
|
||||
const isCcsPermissionWarningEnabled = await uiSettingsClient.get(ENABLE_CCS_READ_WARNING_SETTING);
|
||||
|
@ -86,17 +86,20 @@ export const hasReadIndexPrivileges = async (args: {
|
|||
(indexName) => privileges.index[indexName].read
|
||||
);
|
||||
|
||||
let warningStatusMessage;
|
||||
|
||||
// Some indices have read privileges others do not.
|
||||
if (indexesWithNoReadPrivileges.length > 0) {
|
||||
const indexesString = JSON.stringify(indexesWithNoReadPrivileges);
|
||||
warningStatusMessage = `This rule may not have the required read privileges to the following index patterns: ${indexesString}`;
|
||||
await ruleExecutionLogger.logStatusChange({
|
||||
newStatus: RuleExecutionStatus['partial failure'],
|
||||
message: `This rule may not have the required read privileges to the following index patterns: ${indexesString}`,
|
||||
message: warningStatusMessage,
|
||||
});
|
||||
return true;
|
||||
return { wroteWarningMessage: true, warningStatusMessage };
|
||||
}
|
||||
|
||||
return false;
|
||||
return { wroteWarningMessage: false, warningStatusMessage };
|
||||
};
|
||||
|
||||
export const hasTimestampFields = async (args: {
|
||||
|
@ -107,7 +110,11 @@ export const hasTimestampFields = async (args: {
|
|||
timestampFieldCapsResponse: TransportResult<Record<string, any>, unknown>;
|
||||
inputIndices: string[];
|
||||
ruleExecutionLogger: IRuleExecutionLogForExecutors;
|
||||
}): Promise<{ wroteWarningStatus: boolean; foundNoIndices: boolean }> => {
|
||||
}): Promise<{
|
||||
wroteWarningStatus: boolean;
|
||||
foundNoIndices: boolean;
|
||||
warningMessage: string | undefined;
|
||||
}> => {
|
||||
const { timestampField, timestampFieldCapsResponse, inputIndices, ruleExecutionLogger } = args;
|
||||
const { ruleName } = ruleExecutionLogger.context;
|
||||
|
||||
|
@ -125,7 +132,11 @@ export const hasTimestampFields = async (args: {
|
|||
message: errorString.trimEnd(),
|
||||
});
|
||||
|
||||
return { wroteWarningStatus: true, foundNoIndices: true };
|
||||
return {
|
||||
wroteWarningStatus: true,
|
||||
foundNoIndices: true,
|
||||
warningMessage: errorString.trimEnd(),
|
||||
};
|
||||
} else if (
|
||||
isEmpty(timestampFieldCapsResponse.body.fields) ||
|
||||
timestampFieldCapsResponse.body.fields[timestampField] == null ||
|
||||
|
@ -149,10 +160,10 @@ export const hasTimestampFields = async (args: {
|
|||
message: errorString,
|
||||
});
|
||||
|
||||
return { wroteWarningStatus: true, foundNoIndices: false };
|
||||
return { wroteWarningStatus: true, foundNoIndices: false, warningMessage: errorString };
|
||||
}
|
||||
|
||||
return { wroteWarningStatus: false, foundNoIndices: false };
|
||||
return { wroteWarningStatus: false, foundNoIndices: false, warningMessage: undefined };
|
||||
};
|
||||
|
||||
export const checkPrivileges = async (
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue