mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
[Security Solution] Unskip related integrations Cypress tests in ESS (#166659)
**Related to: https://github.com/elastic/kibana/issues/165359** **Resolves: https://github.com/elastic/kibana/issues/165504** ## Summary This PR unskips skipped rule integrations ESS tests. ## Details Besides just unskipping ESS tests this PR simplifies the test by fetching alert data from the ES directly instead of using multiple steps in UI to validate an expected field has an expected value. ## Flaky test runner ESS [related_integrations.cy.ts 100 runs](https://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/3199) 🟢
This commit is contained in:
parent
884bcb2625
commit
f52ca02a3d
4 changed files with 109 additions and 39 deletions
|
@ -7,11 +7,9 @@
|
|||
|
||||
import { omit } from 'lodash';
|
||||
import { PerformRuleInstallationResponseBody } from '@kbn/security-solution-plugin/common/api/detection_engine';
|
||||
import { filterBy, openTable } from '../../../../tasks/rule_details_flyout';
|
||||
import { generateEvent } from '../../../../objects/event';
|
||||
import { createDocument, deleteDataStream } from '../../../../tasks/api_calls/elasticsearch';
|
||||
import { createRuleAssetSavedObject } from '../../../../helpers/rules';
|
||||
import { FIELD } from '../../../../screens/alerts_details';
|
||||
import { INTEGRATION_LINK, INTEGRATION_STATUS } from '../../../../screens/rule_details';
|
||||
import {
|
||||
INTEGRATIONS_POPOVER,
|
||||
|
@ -34,7 +32,6 @@ import {
|
|||
visitSecurityDetectionRulesPage,
|
||||
visitWithoutDateRange,
|
||||
} from '../../../../tasks/login';
|
||||
import { expandFirstAlert } from '../../../../tasks/alerts';
|
||||
import { waitForAlertsToPopulate } from '../../../../tasks/create_new_rule';
|
||||
import {
|
||||
installIntegrations,
|
||||
|
@ -46,6 +43,7 @@ import {
|
|||
} from '../../../../tasks/alerts_detection_rules';
|
||||
import { ruleDetailsUrl } from '../../../../urls/navigation';
|
||||
import { enablesRule, waitForPageToBeLoaded } from '../../../../tasks/rule_details';
|
||||
import { fetchRuleAlerts } from '../../../../tasks/api_calls/alerts';
|
||||
|
||||
// TODO: https://github.com/elastic/kibana/issues/161540
|
||||
describe('Related integrations', { tags: ['@ess', '@serverless', '@brokenInServerless'] }, () => {
|
||||
|
@ -190,12 +188,10 @@ describe('Related integrations', { tags: ['@ess', '@serverless', '@brokenInServe
|
|||
});
|
||||
});
|
||||
|
||||
// TODO: https://github.com/elastic/kibana/issues/161540
|
||||
// Flaky in serverless tests
|
||||
// @brokenInServerless tag is not working so a skip was needed
|
||||
describe.skip('rule details', { tags: ['@brokenInServerless'] }, () => {
|
||||
describe('rule details', () => {
|
||||
beforeEach(() => {
|
||||
visitFirstInstalledPrebuiltRuleDetailsPage();
|
||||
waitForPageToBeLoaded(PREBUILT_RULE_NAME);
|
||||
});
|
||||
|
||||
it('should display the integrations in the definition section', () => {
|
||||
|
@ -212,42 +208,26 @@ describe('Related integrations', { tags: ['@ess', '@serverless', '@brokenInServe
|
|||
});
|
||||
});
|
||||
|
||||
it('the alerts generated should have a "kibana.alert.rule.parameters.related_integrations" field containing the integrations', () => {
|
||||
const RELATED_INTEGRATION_FIELD = 'kibana.alert.rule.parameters.related_integrations';
|
||||
const RELATED_INTEGRATION_FIELD = 'kibana.alert.rule.parameters.related_integrations';
|
||||
|
||||
it(`the alerts generated should have a "${RELATED_INTEGRATION_FIELD}" field containing the integrations`, () => {
|
||||
deleteDataStream(DATA_STREAM_NAME);
|
||||
createDocument(DATA_STREAM_NAME, generateEvent());
|
||||
|
||||
waitForPageToBeLoaded(PREBUILT_RULE_NAME);
|
||||
enablesRule();
|
||||
waitForAlertsToPopulate();
|
||||
expandFirstAlert();
|
||||
openTable();
|
||||
filterBy(RELATED_INTEGRATION_FIELD);
|
||||
|
||||
cy.get(FIELD(RELATED_INTEGRATION_FIELD))
|
||||
.invoke('text')
|
||||
.then((stringValue) => {
|
||||
// Integrations are displayed in the flyout as a string with a format like so:
|
||||
// '{"package":"aws","version":"1.17.0","integration":"unknown"}{"package":"mock","version":"1.1.0"}{"package":"system","version":"1.17.0"}'
|
||||
// We need to parse it to an array of valid objects before we can compare it to the expected value
|
||||
// Otherwise, the test might fail because of the order of the properties in the objects in the string
|
||||
const jsonStringArray = stringValue.split('}{');
|
||||
|
||||
const validJsonStringArray = createValidJsonStringArray(jsonStringArray);
|
||||
|
||||
const parsedIntegrations = validJsonStringArray.map((jsonString) =>
|
||||
JSON.parse(jsonString)
|
||||
);
|
||||
|
||||
RULE_RELATED_INTEGRATIONS.forEach((integration) => {
|
||||
expect(parsedIntegrations).to.deep.include({
|
||||
package: integration.package,
|
||||
version: integration.version,
|
||||
...(integration.integration ? { integration: integration.integration } : {}),
|
||||
});
|
||||
});
|
||||
fetchRuleAlerts({
|
||||
ruleId: 'rule_1',
|
||||
fields: [RELATED_INTEGRATION_FIELD],
|
||||
size: 1,
|
||||
}).then((alertsResponse) => {
|
||||
expect(alertsResponse.body.hits.hits[0].fields).to.deep.equal({
|
||||
[RELATED_INTEGRATION_FIELD]: RULE_RELATED_INTEGRATIONS.map((x) =>
|
||||
omit(x, ['installed', 'enabled'])
|
||||
),
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import {
|
||||
RuleObjectId,
|
||||
RuleSignatureId,
|
||||
} from '@kbn/security-solution-plugin/common/api/detection_engine';
|
||||
import { rootRequest } from '../common';
|
||||
|
||||
export const DEFAULT_ALERTS_INDEX_PATTERN = '.alerts-security.alerts-*';
|
||||
|
||||
interface FetchRuleAlertsParams {
|
||||
ruleId: RuleObjectId | RuleSignatureId;
|
||||
fields: string[];
|
||||
size?: number;
|
||||
}
|
||||
|
||||
interface AlertFields {
|
||||
fields: Record<string, unknown>;
|
||||
}
|
||||
|
||||
interface AlertsResponse {
|
||||
hits: {
|
||||
total: {
|
||||
value: number;
|
||||
};
|
||||
hits: AlertFields[];
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns rule's generated alerts
|
||||
*
|
||||
* @param ruleId a rule id representing either RuleObjectId (Saved Object id) or RuleSignatureId (rule_id)
|
||||
* @param fields fields to fetch (fetch only fields you need to do assertions on)
|
||||
* @param size a number of alerts to fetch
|
||||
*
|
||||
* @returns rule's generated alerts
|
||||
*/
|
||||
export function fetchRuleAlerts({
|
||||
ruleId,
|
||||
fields,
|
||||
size,
|
||||
}: FetchRuleAlertsParams): Cypress.Chainable<Cypress.Response<AlertsResponse>> {
|
||||
return rootRequest<AlertsResponse>({
|
||||
method: 'GET',
|
||||
url: `${Cypress.env('ELASTICSEARCH_URL')}/${DEFAULT_ALERTS_INDEX_PATTERN}/_search`,
|
||||
body: {
|
||||
query: {
|
||||
bool: {
|
||||
should: [
|
||||
{
|
||||
term: {
|
||||
'kibana.alert.rule.rule_id': ruleId,
|
||||
},
|
||||
},
|
||||
{
|
||||
term: {
|
||||
'kibana.alert.rule.uuid': ruleId,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
fields,
|
||||
sort: {
|
||||
'@timestamp': 'desc',
|
||||
},
|
||||
size,
|
||||
_source: false,
|
||||
},
|
||||
});
|
||||
}
|
|
@ -10,6 +10,7 @@ import { ELASTIC_HTTP_VERSION_HEADER } from '@kbn/core-http-common';
|
|||
import { KIBANA_LOADING_ICON } from '../screens/security_header';
|
||||
import { EUI_BASIC_TABLE_LOADING } from '../screens/common/controls';
|
||||
import { deleteAllDocuments } from './api_calls/elasticsearch';
|
||||
import { DEFAULT_ALERTS_INDEX_PATTERN } from './api_calls/alerts';
|
||||
|
||||
const primaryButton = 0;
|
||||
|
||||
|
@ -135,7 +136,7 @@ export const deleteAlertsAndRules = () => {
|
|||
},
|
||||
});
|
||||
|
||||
deleteAllDocuments('.lists-*,.items-*,.alerts-security.alerts-*');
|
||||
deleteAllDocuments(`.lists-*,.items-*,${DEFAULT_ALERTS_INDEX_PATTERN}`);
|
||||
};
|
||||
|
||||
export const deleteTimelines = () => {
|
||||
|
|
|
@ -56,7 +56,11 @@ export function installIntegrations({
|
|||
packages,
|
||||
force: true,
|
||||
},
|
||||
headers: { 'kbn-xsrf': 'cypress-creds', 'x-elastic-internal-origin': 'security-solution' },
|
||||
headers: {
|
||||
'kbn-xsrf': 'cypress-creds',
|
||||
'x-elastic-internal-origin': 'security-solution',
|
||||
'elastic-api-version': '2023-10-31',
|
||||
},
|
||||
});
|
||||
|
||||
// Install agent and package policies
|
||||
|
@ -64,7 +68,11 @@ export function installIntegrations({
|
|||
method: 'POST',
|
||||
url: `${AGENT_POLICY_API_ROUTES.CREATE_PATTERN}?sys_monitoring=true`,
|
||||
body: agentPolicy,
|
||||
headers: { 'kbn-xsrf': 'cypress-creds', 'x-elastic-internal-origin': 'security-solution' },
|
||||
headers: {
|
||||
'kbn-xsrf': 'cypress-creds',
|
||||
'x-elastic-internal-origin': 'security-solution',
|
||||
'elastic-api-version': '2023-10-31',
|
||||
},
|
||||
}).then((response) => {
|
||||
const packagePolicyWithAgentPolicyId: PackagePolicy = {
|
||||
...packagePolicy,
|
||||
|
@ -75,7 +83,11 @@ export function installIntegrations({
|
|||
method: 'POST',
|
||||
url: PACKAGE_POLICY_API_ROUTES.CREATE_PATTERN,
|
||||
body: packagePolicyWithAgentPolicyId,
|
||||
headers: { 'kbn-xsrf': 'cypress-creds', 'x-elastic-internal-origin': 'security-solution' },
|
||||
headers: {
|
||||
'kbn-xsrf': 'cypress-creds',
|
||||
'x-elastic-internal-origin': 'security-solution',
|
||||
'elastic-api-version': '2023-10-31',
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue