Skip to content

[Entity Analytics] New API endpoint to configure risk engine saved object#194545

Closed
abhishekbhatia1710 wants to merge 8 commits intoelastic:mainfrom
abhishekbhatia1710:ea-new-api-to-allow-user-to-configure-SO
Closed

[Entity Analytics] New API endpoint to configure risk engine saved object#194545
abhishekbhatia1710 wants to merge 8 commits intoelastic:mainfrom
abhishekbhatia1710:ea-new-api-to-allow-user-to-configure-SO

Conversation

@abhishekbhatia1710
Copy link
Copy Markdown
Contributor

@abhishekbhatia1710 abhishekbhatia1710 commented Oct 1, 2024

Summary

The changes in the PR includes a new API endpoint to allow user to configure the risk engine saved object themselves.

Unit and integration tests are added considering the spaces as well.

Examples :

Risk Engine enabled for the first time :

024-10-09T14:18:49.302+05:30][INFO ][plugins.securitySolution] [task risk_engine:risk_scoring:default:0.0.1]: Starting Risk Engine with configuration:
[2024-10-09T14:18:49.401+05:30][INFO ][plugins.securitySolution] [task risk_engine:risk_scoring:default:0.0.1]: 

{"dataViewId":".alerts-security.alerts-default","enabled":true,"filter":{},"interval":"1h","pageSize":3500,"range":{"start":"now-30d","end":"now"}}

Risk Engine disabled, SO is updated and risk engine is enabled again :

2024-10-09T14:19:49.404+05:30][INFO ][plugins.securitySolution] [task risk_engine:risk_scoring:default:0.0.1]: Starting Risk Engine with configuration:
[2024-10-09T14:19:49.408+05:30][INFO ][plugins.securitySolution] [task risk_engine:risk_scoring:default:0.0.1]: 

{"dataViewId":".alerts-security.alerts-default","enabled":true,"filter":{},"interval":"1h","pageSize":3500,"range":{"start":"now-30d","end":"now"},"excludeAlertStatuses":["closed"],"excludeAlertTags":["False Positive"]}

Risk Engine disabled, SO is updated and risk engine is enabled again :

[2024-10-09T14:21:44.834+05:30][INFO ][plugins.securitySolution] [task risk_engine:risk_scoring:default:0.0.1]: Starting Risk Engine with configuration:
[2024-10-09T14:21:44.838+05:30][INFO ][plugins.securitySolution] [task risk_engine:risk_scoring:default:0.0.1]: 

{"dataViewId":".alerts-security.alerts-default","enabled":true,"filter":{},"interval":"1h","pageSize":3500,"range":{"start":"now-30d","end":"now"},"excludeAlertStatuses":["closed","open"],"excludeAlertTags":["False Positive"]}

Checklist

Delete any items that are not applicable to this PR.

For maintainers

@abhishekbhatia1710 abhishekbhatia1710 self-assigned this Oct 1, 2024
@kibana-ci
Copy link
Copy Markdown

kibana-ci commented Oct 1, 2024

💔 Build Failed

Failed CI Steps

Test Failures

  • [job] [logs] x-pack/test_serverless/functional/test_suites/security/common_configs/config.group6.ts / discover/esql discover esql view switch modal should not show switch modal when switching to a data view while a saved search is open

Metrics [docs]

✅ unchanged

History

To update your PR or re-run it, just comment with:
@elasticmachine merge upstream

cc @abhishekbhatia1710

@abhishekbhatia1710 abhishekbhatia1710 changed the title [Entity Analytics] Adding changes to include a public API endpoint to configure risk engine saved object [Entity Analytics] New API endpoint to configure risk engine saved object Oct 7, 2024
@abhishekbhatia1710 abhishekbhatia1710 added release_note:enhancement backport This PR is a backport of another PR Team: SecuritySolution Security Solutions Team working on SIEM, Endpoint, Timeline, Resolver, etc. Team:Entity Analytics Security Entity Analytics Team labels Oct 9, 2024
@abhishekbhatia1710 abhishekbhatia1710 marked this pull request as ready for review October 9, 2024 11:51
@abhishekbhatia1710 abhishekbhatia1710 requested review from a team as code owners October 9, 2024 11:51
@elasticmachine
Copy link
Copy Markdown
Contributor

Pinging @elastic/security-solution (Team: SecuritySolution)

@elasticmachine
Copy link
Copy Markdown
Contributor

Pinging @elastic/security-entity-analytics (Team:Entity Analytics)

@elasticmachine
Copy link
Copy Markdown
Contributor

elasticmachine commented Oct 9, 2024

💔 Build Failed

Failed CI Steps

Test Failures

  • [job] [logs] Jest Tests #12 / RiskEngineDataClient using aliases for alert indices updateSavedObjectConfiguration should update the risk engine saved object configuration in the respective namespace
  • [job] [logs] Jest Tests #12 / RiskEngineDataClient using aliases for alert indices updateSavedObjectConfiguration should update the risk engine saved object configuration in the respective namespace
  • [job] [logs] Jest Tests #12 / RiskEngineDataClient using data streams for alert indices updateSavedObjectConfiguration should update the risk engine saved object configuration in the respective namespace
  • [job] [logs] Jest Tests #12 / RiskEngineDataClient using data streams for alert indices updateSavedObjectConfiguration should update the risk engine saved object configuration in the respective namespace

Metrics [docs]

✅ unchanged

History

cc @abhishekbhatia1710

Comment on lines +421 to +453
riskEngineDataClient = new RiskEngineDataClient(options);
const attributes = {
enabled: true,
excludeAlertStatuses: ['closed'],
excludeAlertTags: ['Duplicate'],
};
mockSavedObjectClient.find.mockResolvedValueOnce(getSavedObjectConfiguration());

mockSavedObjectClient.update.mockResolvedValueOnce({
attributes,
} as unknown as SavedObject<RiskEngineConfiguration>);

const result = await riskEngineDataClient.updateSavedObjectConfiguration({ attributes });
expect(result.attributes).toEqual(attributes);

// Check for the saved object configuration in the non-default space

options.namespace = namespaces.custom;
const riskEngineDataClient2 = new RiskEngineDataClient(options);
const attributes2 = {
enabled: true,
excludeAlertStatuses: ['open', 'closed'],
excludeAlertTags: ['False Positive', 'Duplicate'],
};
mockSavedObjectClient.find.mockResolvedValueOnce(getSavedObjectConfiguration());
mockSavedObjectClient.update.mockResolvedValueOnce({
attributes,
} as unknown as SavedObject<RiskEngineConfiguration>);

const result2 = await riskEngineDataClient2.updateSavedObjectConfiguration({
attributes: attributes2,
});
expect(result2.attributes).toEqual(attributes2);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you split it into 2 different tests?

Comment on lines +45 to +57
enabled?: boolean;
dataViewId?: string;
filter?: object;
identifierType?: string;
interval?: string;
pageSize?: number;
alertSampleSizePerShard?: number;
range?: {
start?: string;
end?: string;
};
excludeAlertStatuses?: Array<'open' | 'closed' | 'in-progress' | 'acknowledged'>;
excludeAlertTags?: Array<'Duplicate' | 'False Positive' | 'Futher investigation required'>;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please reuse the RiskEngineConfiguration type as much as possible so we have a single source of truth.

Comment on lines +29 to +71
type: riskEngineConfigurationTypeName,
space: spaceName,
});
if (soId.saved_objects.length !== 0) {
await kibanaServer.savedObjects.delete({
type: riskEngineConfigurationTypeName,
space: spaceName,
id: soId.saved_objects[0].id,
});
}
const soId2 = await kibanaServer.savedObjects.find({
type: riskEngineConfigurationTypeName,
});
if (soId2.saved_objects.length !== 0) {
await kibanaServer.savedObjects.delete({
type: riskEngineConfigurationTypeName,
id: soId2.saved_objects[0].id,
});
}
await esArchiver.load('x-pack/test/functional/es_archives/security_solution/ecs_compliant');
});

after(async () => {
const soId = await kibanaServer.savedObjects.find({
type: riskEngineConfigurationTypeName,
space: spaceName,
});
if (soId.saved_objects.length !== 0) {
await kibanaServer.savedObjects.delete({
type: riskEngineConfigurationTypeName,
space: spaceName,
id: soId.saved_objects[0].id,
});
}
const soId2 = await kibanaServer.savedObjects.find({
type: riskEngineConfigurationTypeName,
});
if (soId2.saved_objects.length !== 0) {
await kibanaServer.savedObjects.delete({
type: riskEngineConfigurationTypeName,
id: soId2.saved_objects[0].id,
});
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please simplify this duplicated code? Maybe extracting a helper is enough to clarify it.

Comment on lines +76 to +107
await riskEngineRoutes.init();
await waitForRiskEngineRun;

const currentSoConfig = await getRiskEngineConfigSO({ kibanaServer });

expect(currentSoConfig.attributes).to.not.have.property('excludeAlertTags');
expect(currentSoConfig.attributes).to.not.have.property('excludeAlertStatuses');

const updatedSoBody = {
excludeAlertTags: ['False Positive'],
excludeAlertStatuses: ['open'],
};

await riskEngineRoutes.soConfig(updatedSoBody, 200);
const currentSoConfig2 = await getRiskEngineConfigSO({ kibanaServer });

expect(currentSoConfig2.attributes).to.have.property('excludeAlertTags');
expect(currentSoConfig2.attributes).to.have.property('excludeAlertStatuses');

await riskEngineRoutes.disable();
await waitForRiskEngineTaskToBeGone;

updatedSoBody.excludeAlertStatuses = [];

await riskEngineRoutes.soConfig(updatedSoBody, 200);

await riskEngineRoutes.enable();
await waitForRiskEngineRun;

const currentSoConfig3 = await getRiskEngineConfigSO({ kibanaServer });
expect(JSON.stringify(currentSoConfig3.attributes.excludeAlertStatuses)).to.equal(
JSON.stringify(updatedSoBody.excludeAlertStatuses)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here, you are doing several tests inside the "it" block, and the test name is generic, which makes It hard to follow.
Could you break it down into several tests?
If you can't break down the test into small logical steps like the GIVEN - WHEN - THEN pattern. Please leave comments explaining the test intention.

Why did you install, disable and then enable the risk engine?


it('should include the right keys as per the update', async () => {
await riskEngineRoutes.init();
await waitForRiskEngineRun;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't wait because you are calling the function
.

Suggested change
await waitForRiskEngineRun;
await waitForRiskEngineRun({ log, supertest });

Copy link
Copy Markdown
Contributor

@CAWilson94 CAWilson94 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good! Thanks for adding :D

@abhishekbhatia1710
Copy link
Copy Markdown
Contributor Author

Closing this as it is a duplicate of : #201344

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backport This PR is a backport of another PR release_note:enhancement Team:Entity Analytics Security Entity Analytics Team Team: SecuritySolution Security Solutions Team working on SIEM, Endpoint, Timeline, Resolver, etc.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants