From 39b7ebe45d09549decd664b15a23de536dc22344 Mon Sep 17 00:00:00 2001 From: Maxim Palenov Date: Thu, 31 Aug 2023 17:18:57 +0200 Subject: [PATCH] [8.10] [Security Solution] Unskip related integrations tests (#164933) (#165310) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Backport This will backport the following commits from `main` to `8.10`: - [[Security Solution] Unskip related integrations tests (#164933)](https://github.com/elastic/kibana/pull/164933) ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sqren/backport) --- .../components/event_details/helpers.tsx | 1 + .../pages/rule_details/index.tsx | 2 +- .../rule_creation/custom_query_rule.cy.ts | 3 +- .../custom_query_rule_data_view.cy.ts | 3 +- .../event_correlation_rule.cy.ts | 3 +- .../rule_creation/indicator_match_rule.cy.ts | 7 +- .../rule_creation/new_terms_rule.cy.ts | 3 +- .../rule_creation/override.cy.ts | 5 +- .../rule_creation/threshold_rule.cy.ts | 3 +- .../related_integrations.cy.ts | 483 ++++++++++++------ .../endpoint_exceptions.cy.ts | 7 +- .../alerts/building_block_alerts.cy.ts | 6 +- .../fixtures/related_integrations.ndjson | 2 - .../cypress/objects/event.ts | 17 + .../cypress/objects/types.ts | 13 + .../cypress/screens/common/page.ts | 4 +- .../cypress/screens/create_new_rule.ts | 2 - .../cypress/screens/rule_details.ts | 7 +- .../cypress/screens/rule_details_flyout.ts | 11 + .../cypress/tasks/api_calls/elasticsearch.ts | 26 +- .../cypress/tasks/api_calls/prebuilt_rules.ts | 40 +- .../cypress/tasks/common.ts | 13 +- .../cypress/tasks/create_new_rule.ts | 12 - .../cypress/tasks/integrations.ts | 86 +++- .../cypress/tasks/rule_details.ts | 20 +- .../cypress/tasks/rule_details_flyout.ts | 16 + .../cypress/tsconfig.json | 1 + 27 files changed, 549 insertions(+), 247 deletions(-) delete mode 100644 x-pack/test/security_solution_cypress/cypress/fixtures/related_integrations.ndjson create mode 100644 x-pack/test/security_solution_cypress/cypress/objects/event.ts create mode 100644 x-pack/test/security_solution_cypress/cypress/screens/rule_details_flyout.ts create mode 100644 x-pack/test/security_solution_cypress/cypress/tasks/rule_details_flyout.ts diff --git a/x-pack/plugins/security_solution/public/common/components/event_details/helpers.tsx b/x-pack/plugins/security_solution/public/common/components/event_details/helpers.tsx index 711ffc34e49d7..5133faaeb9f4f 100644 --- a/x-pack/plugins/security_solution/public/common/components/event_details/helpers.tsx +++ b/x-pack/plugins/security_solution/public/common/components/event_details/helpers.tsx @@ -32,6 +32,7 @@ export const search = { incremental: true, placeholder: i18n.PLACEHOLDER, schema: true, + 'data-test-subj': 'search-input', }, }; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/index.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/index.tsx index 791db19a92dcd..3c2849ec284ce 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/index.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/index.tsx @@ -527,7 +527,7 @@ const RuleDetailsPageComponent: React.FC = ({ ) : ( { login(); + deleteAlertsAndRules(); }); it('Creates and enables a new custom rule with override option', function () { diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_creation/threshold_rule.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_creation/threshold_rule.cy.ts index 7c29afc4c0abe..b88b61d91f2f0 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_creation/threshold_rule.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_creation/threshold_rule.cy.ts @@ -45,7 +45,7 @@ import { TIMELINE_TEMPLATE_DETAILS, } from '../../../screens/rule_details'; -import { getDetails } from '../../../tasks/rule_details'; +import { getDetails, waitForTheRuleToBeExecuted } from '../../../tasks/rule_details'; import { expectNumberOfRules, goToRuleDetails } from '../../../tasks/alerts_detection_rules'; import { cleanKibana, deleteAlertsAndRules } from '../../../tasks/common'; import { @@ -55,7 +55,6 @@ import { fillScheduleRuleAndContinue, selectThresholdRuleType, waitForAlertsToPopulate, - waitForTheRuleToBeExecuted, } from '../../../tasks/create_new_rule'; import { login, visitWithoutDateRange } from '../../../tasks/login'; diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/related_integrations/related_integrations.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/related_integrations/related_integrations.cy.ts index c13079d1dd134..e0ae69719d7ab 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/related_integrations/related_integrations.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/related_integrations/related_integrations.cy.ts @@ -5,241 +5,406 @@ * 2.0. */ +import { PerformRuleInstallationResponseBody } from '@kbn/security-solution-plugin/common/api/detection_engine'; +import { omit } from 'lodash'; import { tag } from '../../../../tags'; - -import { DETECTIONS_RULE_MANAGEMENT_URL } from '../../../../urls/navigation'; - +import { filterBy, openTable } from '../../../../tasks/rule_details_flyout'; +import { generateEvent } from '../../../../objects/event'; +import { createDocument, deleteDataStream } from '../../../../tasks/api_calls/elasticsearch'; import { FIELD } from '../../../../screens/alerts_details'; -import { INTEGRATIONS, INTEGRATIONS_STATUS } from '../../../../screens/rule_details'; +import { INTEGRATION_LINK, INTEGRATION_STATUS } from '../../../../screens/rule_details'; import { INTEGRATIONS_POPOVER, INTEGRATIONS_POPOVER_TITLE, RULE_NAME, } from '../../../../screens/alerts_detection_rules'; - +import { + installPrebuiltRuleAssets, + installAllPrebuiltRulesRequest, + SAMPLE_PREBUILT_RULE, +} from '../../../../tasks/api_calls/prebuilt_rules'; import { cleanFleet } from '../../../../tasks/api_calls/fleet'; -import { importRule } from '../../../../tasks/api_calls/rules'; import { disableRelatedIntegrations, enableRelatedIntegrations, } from '../../../../tasks/api_calls/kibana_advanced_settings'; - -import { cleanKibana } from '../../../../tasks/common'; -import { login, visit } from '../../../../tasks/login'; +import { deleteAlertsAndRules } from '../../../../tasks/common'; +import { + login, + visitSecurityDetectionRulesPage, + visitWithoutDateRange, +} from '../../../../tasks/login'; import { expandFirstAlert } from '../../../../tasks/alerts'; -import { filterBy, openTable } from '../../../../tasks/alerts_details'; import { waitForAlertsToPopulate } from '../../../../tasks/create_new_rule'; -import { installAwsCloudFrontWithPolicy } from '../../../../tasks/integrations'; import { - enableRule, - goToTheRuleDetailsOf, + installIntegrations, + PackagePolicyWithoutAgentPolicyId, +} from '../../../../tasks/integrations'; +import { + disableAutoRefresh, openIntegrationsPopover, - waitForRulesTableToShow, - waitForRuleToUpdate, } from '../../../../tasks/alerts_detection_rules'; - -/* -Note that the rule we are using for testing purposes has the following characteristics, changing that may affect the coverage. - -- Single-integration - - Package: system -- Multi-integration package - - Package: aws - - Integration: cloudtrail - - Integration: cloudfront -- Not existing package: - - Package: unknown -- Not existing integration & existing package: - - Package: aws - - Integration: unknown -*/ +import { ruleDetailsUrl } from '../../../../urls/navigation'; +import { enablesRule, waitForPageToBeLoaded } from '../../../../tasks/rule_details'; +import { createRuleAssetSavedObject } from '../../../../helpers/rules'; describe('Related integrations', { tags: [tag.ESS, tag.BROKEN_IN_SERVERLESS] }, () => { - before(() => { - cleanKibana(); - login(); - importRule('related_integrations.ndjson'); + const DATA_STREAM_NAME = 'logs-related-integrations-test'; + const PREBUILT_RULE_NAME = 'Prebuilt rule with related integrations'; + const RULE_RELATED_INTEGRATIONS: IntegrationDefinition[] = [ + { + package: 'aws', + version: '1.17.0', + integration: 'cloudfront', + installed: true, + enabled: true, + }, + { + package: 'aws', + version: '1.17.0', + integration: 'cloudtrail', + installed: true, + enabled: false, + }, + { package: 'aws', version: '1.17.0', integration: 'unknown', installed: false, enabled: false }, + { package: 'system', version: '1.17.0', installed: true, enabled: true }, + ]; + const PREBUILT_RULE = createRuleAssetSavedObject({ + name: PREBUILT_RULE_NAME, + index: [DATA_STREAM_NAME], + query: '*:*', + rule_id: 'rule_1', + related_integrations: RULE_RELATED_INTEGRATIONS.map((x) => omit(x, ['installed', 'enabled'])), }); - context('integrations not installed', () => { - const rule = { - name: 'Related integrations rule', - integrations: ['Aws Cloudfront', 'Aws Cloudtrail', 'Aws Unknown', 'System'], - enabledIntegrations: '0', - }; - - before(() => { - cleanFleet(); - }); - - beforeEach(() => { - login(); - visit(DETECTIONS_RULE_MANAGEMENT_URL); - waitForRulesTableToShow(); - }); + beforeEach(() => { + login(); + cleanFleet(); + deleteAlertsAndRules(); + addAndInstallPrebuiltRules([PREBUILT_RULE]); + }); - it('should display a badge with the installed integrations on the rule management page', () => { - cy.get(INTEGRATIONS_POPOVER).should( - 'have.text', - `${rule.enabledIntegrations}/${rule.integrations.length} integrations` - ); - }); + describe('integrations not installed', () => { + describe('rules management table', () => { + beforeEach(() => { + visitSecurityDetectionRulesPage(); + disableAutoRefresh(); + }); - it('should display a popover when clicking the badge with the installed integrations on the rule management page', () => { - openIntegrationsPopover(); + it('should display a badge with the installed integrations', () => { + cy.get(INTEGRATIONS_POPOVER).should( + 'have.text', + `0/${RULE_RELATED_INTEGRATIONS.length} integrations` + ); + }); - cy.get(INTEGRATIONS_POPOVER_TITLE).should( - 'have.text', - `[${rule.integrations.length}] Related integrations available` - ); - cy.get(INTEGRATIONS).should('have.length', rule.integrations.length); - cy.get(INTEGRATIONS_STATUS).should('have.length', rule.integrations.length); + it('should display a popover when clicking the badge with the installed integrations', () => { + openIntegrationsPopover(); - rule.integrations.forEach((integration, index) => { - cy.get(INTEGRATIONS).eq(index).should('contain', integration); - cy.get(INTEGRATIONS_STATUS).eq(index).should('have.text', 'Not installed'); + cy.get(INTEGRATIONS_POPOVER_TITLE).should( + 'have.text', + `[${RULE_RELATED_INTEGRATIONS.length}] Related integrations available` + ); + cy.get(INTEGRATION_LINK).should('have.length', RULE_RELATED_INTEGRATIONS.length); + cy.get(INTEGRATION_STATUS).should('have.length', RULE_RELATED_INTEGRATIONS.length); + + RULE_RELATED_INTEGRATIONS.forEach((integration, index) => { + cy.get(INTEGRATION_LINK).eq(index).contains(getIntegrationName(integration), { + matchCase: false, + }); + cy.get(INTEGRATION_STATUS).eq(index).should('have.text', 'Not installed'); + }); }); }); - it('should display the integrations on the definition section', () => { - goToTheRuleDetailsOf(rule.name); + describe('rule details', () => { + beforeEach(() => { + visitFirstInstalledPrebuiltRuleDetailsPage(); + }); - cy.get(INTEGRATIONS).should('have.length', rule.integrations.length); - cy.get(INTEGRATIONS_STATUS).should('have.length', rule.integrations.length); + it('should display the integrations in the definition section', () => { + cy.get(INTEGRATION_LINK).should('have.length', RULE_RELATED_INTEGRATIONS.length); + cy.get(INTEGRATION_STATUS).should('have.length', RULE_RELATED_INTEGRATIONS.length); - rule.integrations.forEach((integration, index) => { - cy.get(INTEGRATIONS).eq(index).should('contain', integration); - cy.get(INTEGRATIONS_STATUS).eq(index).should('have.text', 'Not installed'); + RULE_RELATED_INTEGRATIONS.forEach((integration, index) => { + cy.get(INTEGRATION_LINK).eq(index).contains(getIntegrationName(integration), { + matchCase: false, + }); + cy.get(INTEGRATION_STATUS).eq(index).should('have.text', 'Not installed'); + }); }); }); }); - context.skip( - 'installed integrations: Amazon CloudFront, AWS CloudTrail, System, enabled integrations: Amazon CloudFront, Aws Cloudfront, System', - () => { - const rule = { - name: 'Related integrations rule', - integrations: [ - { name: 'AWS Cloudfront', installed: true, enabled: true }, - { name: 'AWS CloudTrail', installed: true, enabled: false }, - { name: 'Aws Unknown', installed: false, enabled: false }, - { name: 'System', installed: true, enabled: true }, + describe('integrations installed (AWS CloudFront (enabled), AWS CloudTrail (disabled), System (enabled))', () => { + beforeEach(() => { + installIntegrations({ + packages: [ + { name: 'aws', version: '1.17.0' }, + { name: 'system', version: '1.17.0' }, ], - enabledIntegrations: '2', - }; - - before(() => { - cleanFleet().then(() => { - installAwsCloudFrontWithPolicy(); - }); + agentPolicy: { + name: 'Agent policy', + namespace: 'default', + monitoring_enabled: ['logs'], + inactivity_timeout: 1209600, + }, + packagePolicy: AWS_PACKAGE_POLICY, }); + }); + describe('rules management table', () => { beforeEach(() => { - login(); - visit(DETECTIONS_RULE_MANAGEMENT_URL); - waitForRulesTableToShow(); + visitSecurityDetectionRulesPage(); + disableAutoRefresh(); }); - it('should display a badge with the installed integrations on the rule management page', () => { + it('should display a badge with the installed integrations', () => { + const enabledIntegrations = RULE_RELATED_INTEGRATIONS.filter((x) => x.enabled).length; + const totalIntegrations = RULE_RELATED_INTEGRATIONS.length; + cy.get(INTEGRATIONS_POPOVER).should( 'have.text', - `${rule.enabledIntegrations}/${rule.integrations.length} integrations` + `${enabledIntegrations}/${totalIntegrations} integrations` ); }); - it('should display a popover when clicking the badge with the installed integrations on the rule management page', () => { + it('should display a popover when clicking the badge with the installed integrations', () => { openIntegrationsPopover(); cy.get(INTEGRATIONS_POPOVER_TITLE).should( 'have.text', - `[${rule.integrations.length}] Related integrations available` + `[${RULE_RELATED_INTEGRATIONS.length}] Related integrations available` ); - cy.get(INTEGRATIONS).should('have.length', rule.integrations.length); - cy.get(INTEGRATIONS_STATUS).should('have.length', rule.integrations.length); - - rule.integrations.forEach((integration, index) => { - let expectedStatus = integration.installed ? 'Installed' : 'Not installed'; - if (integration.enabled) expectedStatus += ': enabled'; - - cy.get(INTEGRATIONS).eq(index).should('contain', integration.name); - cy.get(INTEGRATIONS_STATUS).eq(index).should('have.text', expectedStatus); + cy.get(INTEGRATION_LINK).should('have.length', RULE_RELATED_INTEGRATIONS.length); + cy.get(INTEGRATION_STATUS).should('have.length', RULE_RELATED_INTEGRATIONS.length); + + RULE_RELATED_INTEGRATIONS.forEach((integration, index) => { + cy.get(INTEGRATION_LINK).eq(index).contains(getIntegrationName(integration), { + matchCase: false, + }); + cy.get(INTEGRATION_STATUS) + .eq(index) + .should('have.text', getIntegrationStatus(integration)); }); }); + }); - it('should display the integrations on the definition section', () => { - goToTheRuleDetailsOf(rule.name); - - cy.get(INTEGRATIONS).should('have.length', rule.integrations.length); - cy.get(INTEGRATIONS_STATUS).should('have.length', rule.integrations.length); - - rule.integrations.forEach((integration, index) => { - let expectedStatus = integration.installed ? 'Installed' : 'Not installed'; - if (integration.enabled) expectedStatus += ': enabled'; + describe('rule details', () => { + beforeEach(() => { + visitFirstInstalledPrebuiltRuleDetailsPage(); + }); - cy.get(INTEGRATIONS).eq(index).should('contain', integration.name); - cy.get(INTEGRATIONS_STATUS).eq(index).should('have.text', expectedStatus); + it('should display the integrations in the definition section', () => { + cy.get(INTEGRATION_LINK).should('have.length', RULE_RELATED_INTEGRATIONS.length); + cy.get(INTEGRATION_STATUS).should('have.length', RULE_RELATED_INTEGRATIONS.length); + + RULE_RELATED_INTEGRATIONS.forEach((integration, index) => { + cy.get(INTEGRATION_LINK).eq(index).contains(getIntegrationName(integration), { + matchCase: false, + }); + cy.get(INTEGRATION_STATUS) + .eq(index) + .should('have.text', getIntegrationStatus(integration)); }); }); it('the alerts generated should have a "kibana.alert.rule.parameters.related_integrations" field containing the integrations', () => { - const firstRule = 0; - const relatedIntegrationsField = 'kibana.alert.rule.parameters.related_integrations'; - const expectedRelatedIntegrationsText = - '{"package":"system","version":"1.17.0"}{"package":"aws","integration":"cloudtrail","version":"1.17.0"}{"package":"aws","integration":"cloudfront","version":"1.17.0"}{"package":"aws","integration":"unknown","version":"1.17.0"}'; - - enableRule(firstRule); - waitForRuleToUpdate(); - goToTheRuleDetailsOf(rule.name); + const RELATED_INTEGRATION_FIELD = 'kibana.alert.rule.parameters.related_integrations'; + + deleteDataStream(DATA_STREAM_NAME); + createDocument(DATA_STREAM_NAME, generateEvent()); + + waitForPageToBeLoaded(PREBUILT_RULE_NAME); + enablesRule(); waitForAlertsToPopulate(); expandFirstAlert(); openTable(); - filterBy(relatedIntegrationsField); - cy.get(FIELD(relatedIntegrationsField)).should( - 'have.text', - expectedRelatedIntegrationsText - ); + filterBy(RELATED_INTEGRATION_FIELD); + + RULE_RELATED_INTEGRATIONS.forEach((integration) => { + cy.contains( + FIELD(RELATED_INTEGRATION_FIELD), + `{"package":"${integration.package}"${ + integration.integration ? `,"integration":"${integration.integration}"` : '' + },"version":"${integration.version}"}` + ); + }); }); - } - ); - - context('related Integrations Advanced Setting is disabled', () => { - const rule = { - name: 'Related integrations rule', - integrations: ['Aws Cloudfront', 'Aws Cloudtrail', 'Aws Unknown', 'System'], - enabledIntegrations: '0', - }; + }); + }); + describe('related Integrations Advanced Setting is disabled', () => { before(() => { - cleanFleet().then(() => { - disableRelatedIntegrations(); - }); + disableRelatedIntegrations(); }); after(() => { enableRelatedIntegrations(); }); - beforeEach(() => { - login(); - visit(DETECTIONS_RULE_MANAGEMENT_URL); - waitForRulesTableToShow(); - }); + describe('rules management table', () => { + beforeEach(() => { + visitSecurityDetectionRulesPage(); + disableAutoRefresh(); + }); - it('should not display a badge with the installed integrations on the rule management page', () => { - cy.get(RULE_NAME).should('have.text', rule.name); - cy.get(INTEGRATIONS).should('not.exist'); + it('should not display a badge with the installed integrations', () => { + cy.get(RULE_NAME).should('have.text', PREBUILT_RULE_NAME); + cy.get(INTEGRATION_LINK).should('not.exist'); + }); }); - it('should display the integrations on the definition section', () => { - goToTheRuleDetailsOf(rule.name); + describe('rule details', () => { + beforeEach(() => { + visitFirstInstalledPrebuiltRuleDetailsPage(); + }); - cy.get(INTEGRATIONS).should('have.length', rule.integrations.length); - cy.get(INTEGRATIONS_STATUS).should('have.length', rule.integrations.length); + it('should display the integrations in the definition section', () => { + cy.get(INTEGRATION_LINK).should('have.length', RULE_RELATED_INTEGRATIONS.length); + cy.get(INTEGRATION_STATUS).should('have.length', RULE_RELATED_INTEGRATIONS.length); - rule.integrations.forEach((integration, index) => { - cy.get(INTEGRATIONS).eq(index).should('contain', integration); - cy.get(INTEGRATIONS_STATUS).eq(index).should('have.text', 'Not installed'); + RULE_RELATED_INTEGRATIONS.forEach((integration, index) => { + cy.get(INTEGRATION_LINK).eq(index).contains(getIntegrationName(integration), { + matchCase: false, + }); + cy.get(INTEGRATION_STATUS).eq(index).should('have.text', 'Not installed'); + }); }); }); }); }); + +const INSTALLED_PREBUILT_RULES_RESPONSE_ALIAS = 'prebuiltRules'; + +function addAndInstallPrebuiltRules(rules: Array): void { + installPrebuiltRuleAssets(rules); + installAllPrebuiltRulesRequest().as(INSTALLED_PREBUILT_RULES_RESPONSE_ALIAS); +} + +function visitFirstInstalledPrebuiltRuleDetailsPage(): void { + cy.get>( + `@${INSTALLED_PREBUILT_RULES_RESPONSE_ALIAS}` + ).then((response) => visitWithoutDateRange(ruleDetailsUrl(response.body.results.created[0].id))); +} + +interface IntegrationDefinition { + package: string; + version: string; + installed: boolean; + enabled: boolean; + integration?: string; +} + +function getIntegrationName(integration: IntegrationDefinition): string { + return `${integration.package} ${integration.integration ?? ''}`.trim(); +} + +function getIntegrationStatus(integration: IntegrationDefinition): string { + return `${integration.installed ? 'Installed' : 'Not installed'}${ + integration.enabled ? ': enabled' : '' + }`.trim(); +} + +/** + * AWS package policy has been generated by Kibana. Instead of copying the whole output the policy below + * contains only required for testing inputs. + */ +const AWS_PACKAGE_POLICY: PackagePolicyWithoutAgentPolicyId = { + package: { + name: 'aws', + version: '1.17.0', + }, + name: 'aws-1', + namespace: 'default', + inputs: { + 'cloudtrail-aws-s3': { + enabled: false, + streams: { + 'aws.cloudtrail': { + enabled: true, + vars: { + fips_enabled: false, + tags: ['forwarded', 'aws-cloudtrail'], + preserve_original_event: false, + cloudtrail_regex: '/CloudTrail/', + cloudtrail_digest_regex: '/CloudTrail-Digest/', + cloudtrail_insight_regex: '/CloudTrail-Insight/', + max_number_of_messages: 5, + }, + }, + }, + }, + 'elb-aws-s3': { + enabled: false, + streams: { + 'aws.elb_logs': { + enabled: true, + vars: { + fips_enabled: false, + tags: ['forwarded', 'aws-elb-logs'], + preserve_original_event: false, + max_number_of_messages: 5, + }, + }, + }, + }, + 'firewall-aws-s3': { + enabled: false, + streams: { + 'aws.firewall_logs': { + enabled: true, + vars: { + fips_enabled: false, + tags: ['forwarded', 'aws-firewall-logs'], + preserve_original_event: false, + max_number_of_messages: 5, + }, + }, + }, + }, + 's3-aws-s3': { + enabled: false, + streams: { + 'aws.s3access': { + enabled: true, + vars: { + fips_enabled: false, + tags: ['forwarded', 'aws-s3access'], + preserve_original_event: false, + max_number_of_messages: 5, + }, + }, + }, + }, + 'waf-aws-s3': { + enabled: false, + streams: { + 'aws.waf': { + enabled: true, + vars: { + fips_enabled: false, + tags: ['forwarded', 'aws-waf'], + preserve_original_event: false, + max_number_of_messages: 5, + }, + }, + }, + }, + 'cloudfront-aws-s3': { + enabled: true, + streams: { + 'aws.cloudfront_logs': { + enabled: true, + vars: { + queue_url: 'https://example.com', + fips_enabled: false, + tags: ['forwarded', 'aws-cloudfront'], + preserve_original_event: false, + max_number_of_messages: 5, + }, + }, + }, + }, + }, +}; diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/alerts_table_flow/endpoint_exceptions.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/alerts_table_flow/endpoint_exceptions.cy.ts index a0449e93a8212..25f7a3c119946 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/alerts_table_flow/endpoint_exceptions.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/alerts_table_flow/endpoint_exceptions.cy.ts @@ -19,10 +19,7 @@ import { login, visitWithoutDateRange } from '../../../tasks/login'; import { getEndpointRule } from '../../../objects/rule'; import { goToRuleDetails } from '../../../tasks/alerts_detection_rules'; import { createRule } from '../../../tasks/api_calls/rules'; -import { - waitForAlertsToPopulate, - waitForTheRuleToBeExecuted, -} from '../../../tasks/create_new_rule'; +import { waitForAlertsToPopulate } from '../../../tasks/create_new_rule'; import { DETECTIONS_RULE_MANAGEMENT_URL } from '../../../urls/navigation'; import { addExceptionEntryFieldValueAndSelectSuggestion, @@ -40,7 +37,7 @@ import { EXCEPTION_CARD_ITEM_NAME, EXCEPTION_ITEM_VIEWER_CONTAINER, } from '../../../screens/exceptions'; -import { goToEndpointExceptionsTab } from '../../../tasks/rule_details'; +import { goToEndpointExceptionsTab, waitForTheRuleToBeExecuted } from '../../../tasks/rule_details'; // See https://github.com/elastic/kibana/issues/163967 describe.skip( diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/building_block_alerts.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/building_block_alerts.cy.ts index 7bca339234663..49acdb99b659c 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/building_block_alerts.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/building_block_alerts.cy.ts @@ -13,11 +13,9 @@ import { OVERVIEW } from '../../../screens/security_header'; import { goToRuleDetails } from '../../../tasks/alerts_detection_rules'; import { createRule } from '../../../tasks/api_calls/rules'; import { cleanKibana } from '../../../tasks/common'; -import { - waitForAlertsToPopulate, - waitForTheRuleToBeExecuted, -} from '../../../tasks/create_new_rule'; +import { waitForAlertsToPopulate } from '../../../tasks/create_new_rule'; import { login, visitWithoutDateRange } from '../../../tasks/login'; +import { waitForTheRuleToBeExecuted } from '../../../tasks/rule_details'; import { navigateFromHeaderTo } from '../../../tasks/security_header'; import { DETECTIONS_RULE_MANAGEMENT_URL } from '../../../urls/navigation'; diff --git a/x-pack/test/security_solution_cypress/cypress/fixtures/related_integrations.ndjson b/x-pack/test/security_solution_cypress/cypress/fixtures/related_integrations.ndjson deleted file mode 100644 index f121d07f4610f..0000000000000 --- a/x-pack/test/security_solution_cypress/cypress/fixtures/related_integrations.ndjson +++ /dev/null @@ -1,2 +0,0 @@ -{"id":"6cc39c80-da3a-11ec-9fce-65c1a0bee904","updated_at":"2022-05-23T01:48:23.422Z","updated_by":"elastic","created_at":"2022-05-23T01:48:20.940Z","created_by":"elastic","name":"Related integrations rule","tags":["Elastic","Endpoint Security"],"interval":"5m","enabled":false,"description":"Generates a detection alert each time an Elastic Endpoint Security alert is received. Enabling this rule allows you to immediately begin investigating your Endpoint alerts.","risk_score":47,"severity":"medium","license":"Elastic License v2","output_index":".siem-signals-default","meta":{"from":"5m"},"rule_name_override":"message","timestamp_override":"event.ingested","author":["Elastic"],"false_positives":[],"from":"now-50000h","rule_id":"2c66bf23-6ae9-4eb2-859e-446bea181ae9","max_signals":10000,"risk_score_mapping":[{"field":"event.risk_score","operator":"equals","value":""}],"severity_mapping":[{"field":"event.severity","operator":"equals","severity":"low","value":"21"},{"field":"event.severity","operator":"equals","severity":"medium","value":"47"},{"field":"event.severity","operator":"equals","severity":"high","value":"73"},{"field":"event.severity","operator":"equals","severity":"critical","value":"99"}],"threat":[],"to":"now","references":[],"version":7,"exceptions_list":[{"id":"endpoint_list","list_id":"endpoint_list","namespace_type":"agnostic","type":"endpoint"}],"immutable":false,"related_integrations":[{"package":"system","version":"1.17.0"},{"package":"aws","integration":"cloudtrail","version":"1.17.0"},{"package":"aws","integration":"cloudfront","version":"1.17.0"},{"package":"aws","integration":"unknown","version":"1.17.0"}],"type":"query","language":"kuery","index":["auditbeat-*"],"query":"*:*","filters":[],"throttle":"no_actions","actions":[]} -{"exported_count":1,"exported_rules_count":1,"missing_rules":[],"missing_rules_count":0,"exported_exception_list_count":0,"exported_exception_list_item_count":0,"missing_exception_list_item_count":0,"missing_exception_list_items":[],"missing_exception_lists":[],"missing_exception_lists_count":0} diff --git a/x-pack/test/security_solution_cypress/cypress/objects/event.ts b/x-pack/test/security_solution_cypress/cypress/objects/event.ts new file mode 100644 index 0000000000000..ea7a61f222eec --- /dev/null +++ b/x-pack/test/security_solution_cypress/cypress/objects/event.ts @@ -0,0 +1,17 @@ +/* + * 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 { SecurityEvent } from './types'; + +export function generateEvent(extra: Record = {}): SecurityEvent { + return { + '@timestamp': Date.now(), + ecs: { version: '1.4.0' }, + event: { kind: 'event', category: 'process', type: 'start' }, + ...extra, + }; +} diff --git a/x-pack/test/security_solution_cypress/cypress/objects/types.ts b/x-pack/test/security_solution_cypress/cypress/objects/types.ts index b61580dd0287d..7050a97de91c4 100644 --- a/x-pack/test/security_solution_cypress/cypress/objects/types.ts +++ b/x-pack/test/security_solution_cypress/cypress/objects/types.ts @@ -12,3 +12,16 @@ export type CreateRulePropsRewrites = Partial { rootRequest({ method: 'DELETE', - url: `${Cypress.env('ELASTICSEARCH_URL')}/${index}`, + url: `${Cypress.env('ELASTICSEARCH_URL')}/${index}?refresh=wait_for`, headers: { 'kbn-xsrf': 'cypress-creds', 'x-elastic-internal-origin': 'security-solution' }, failOnStatusCode: false, }); }; +export const deleteDataStream = (dataStreamName: string) => { + rootRequest({ + method: 'DELETE', + url: `${Cypress.env('ELASTICSEARCH_URL')}/_data_stream/${dataStreamName}`, + headers: { 'kbn-xsrf': 'cypress-creds', 'x-elastic-internal-origin': 'security-solution' }, + failOnStatusCode: false, + }); +}; + +export const deleteAllDocuments = (target: string) => + rootRequest({ + method: 'POST', + url: `${Cypress.env( + 'ELASTICSEARCH_URL' + )}/${target}/_delete_by_query?conflicts=proceed&scroll_size=10000&refresh`, + body: { + query: { + match_all: {}, + }, + }, + }); + export const createIndex = (indexName: string, properties: Record) => rootRequest({ method: 'PUT', @@ -29,7 +51,7 @@ export const createIndex = (indexName: string, properties: Record) => rootRequest({ method: 'POST', - url: `${Cypress.env('ELASTICSEARCH_URL')}/${indexName}/_doc`, + url: `${Cypress.env('ELASTICSEARCH_URL')}/${indexName}/_doc?refresh=wait_for`, body: document, }); diff --git a/x-pack/test/security_solution_cypress/cypress/tasks/api_calls/prebuilt_rules.ts b/x-pack/test/security_solution_cypress/cypress/tasks/api_calls/prebuilt_rules.ts index 665c062b58096..91bd4765f2e6e 100644 --- a/x-pack/test/security_solution_cypress/cypress/tasks/api_calls/prebuilt_rules.ts +++ b/x-pack/test/security_solution_cypress/cypress/tasks/api_calls/prebuilt_rules.ts @@ -5,6 +5,10 @@ * 2.0. */ +import { + PerformRuleInstallationResponseBody, + PERFORM_RULE_INSTALLATION_URL, +} from '@kbn/security-solution-plugin/common/api/detection_engine'; import { ELASTIC_SECURITY_RULE_ID } from '@kbn/security-solution-plugin/common/detection_engine/constants'; import type { PrePackagedRulesStatusResponse } from '@kbn/security-solution-plugin/public/detection_engine/rule_management/logic/types'; import { getPrebuiltRuleWithExceptionsMock } from '@kbn/security-solution-plugin/server/lib/detection_engine/prebuilt_rules/mocks'; @@ -30,16 +34,15 @@ export const SAMPLE_PREBUILT_RULE = createRuleAssetSavedObject({ * `createNewRuleAsset` to create mocked prebuilt rules and install only those * instead of all rules available in the `security_detection_engine` package */ -export const installAllPrebuiltRulesRequest = () => { - return cy.request({ +export const installAllPrebuiltRulesRequest = () => + cy.request({ method: 'POST', - url: 'internal/detection_engine/prebuilt_rules/installation/_perform', + url: PERFORM_RULE_INSTALLATION_URL, headers: { 'kbn-xsrf': 'cypress-creds', 'x-elastic-internal-origin': 'security-solution' }, body: { mode: 'ALL_RULES', }, }); -}; export const getAvailablePrebuiltRulesCount = () => { cy.log('Get prebuilt rules count'); @@ -187,6 +190,24 @@ export const preventPrebuiltRulesPackageInstallation = () => { cy.intercept('POST', '/api/fleet/epm/packages/security_detection_engine/*', {}); }; +/** + * Install prebuilt rule assets. After installing these assets become available to be installed + * as prebuilt rules. Prebuilt rule assets can be generated via `createRuleAssetSavedObject()` helper function. + * + * It's also important to take into account that business logic tries to fetch prebuilt rules Fleet package + * and you need to add `preventPrebuiltRulesPackageInstallation()` to `beforeEach` section (before visit commands) + * to avoid actually pulling a real Fleet package and have only provided prebuilt rule assets for testing. + */ +export const installPrebuiltRuleAssets = (ruleAssets: Array): void => { + cy.log('Create mocked available to install prebuilt rules', ruleAssets.length); + preventPrebuiltRulesPackageInstallation(); + // TODO: use this bulk method once the issue with Cypress is fixed + // bulkCreateRuleAssets({ rules }); + ruleAssets.forEach((rule) => { + createNewRuleAsset({ rule }); + }); +}; + /** * Prevent the installation of the `security_detection_engine` package from Fleet. * The create a `security-rule` asset for each rule provided in the `rules` array. @@ -199,21 +220,16 @@ export const preventPrebuiltRulesPackageInstallation = () => { * * @param {string} installToKibana - Flag to decide whether to install the rules as 'alerts' SO. Defaults to true. */ export const createAndInstallMockedPrebuiltRules = ({ - rules, + rules: ruleAssets, installToKibana = true, }: { rules: Array; installToKibana?: boolean; }) => { - cy.log('Install prebuilt rules', rules?.length); - preventPrebuiltRulesPackageInstallation(); - // TODO: use this bulk method once the issue with Cypress is fixed - // bulkCreateRuleAssets({ rules }); - rules.forEach((rule) => { - createNewRuleAsset({ rule }); - }); + installPrebuiltRuleAssets(ruleAssets); if (installToKibana) { + cy.log('Install prebuilt rules', ruleAssets.length); return installAllPrebuiltRulesRequest(); } }; diff --git a/x-pack/test/security_solution_cypress/cypress/tasks/common.ts b/x-pack/test/security_solution_cypress/cypress/tasks/common.ts index c9a4c4ccad8d6..a34fb5fb1057e 100644 --- a/x-pack/test/security_solution_cypress/cypress/tasks/common.ts +++ b/x-pack/test/security_solution_cypress/cypress/tasks/common.ts @@ -9,6 +9,7 @@ import { DATA_VIEW_PATH, INITIAL_REST_VERSION } from '@kbn/data-views-plugin/ser 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'; const primaryButton = 0; @@ -130,17 +131,7 @@ export const deleteAlertsAndRules = () => { }, }); - rootRequest({ - method: 'POST', - url: `${Cypress.env( - 'ELASTICSEARCH_URL' - )}/.lists-*,.items-*,.alerts-security.alerts-*/_delete_by_query?conflicts=proceed&scroll_size=10000&refresh`, - body: { - query: { - match_all: {}, - }, - }, - }); + deleteAllDocuments('.lists-*,.items-*,.alerts-security.alerts-*'); }; export const deleteTimelines = () => { diff --git a/x-pack/test/security_solution_cypress/cypress/tasks/create_new_rule.ts b/x-pack/test/security_solution_cypress/cypress/tasks/create_new_rule.ts index dabd0b89e4fb1..3286291ae325d 100644 --- a/x-pack/test/security_solution_cypress/cypress/tasks/create_new_rule.ts +++ b/x-pack/test/security_solution_cypress/cypress/tasks/create_new_rule.ts @@ -69,13 +69,11 @@ import { MITRE_TACTIC, QUERY_BAR, REFERENCE_URLS_INPUT, - REFRESH_BUTTON, RISK_MAPPING_OVERRIDE_OPTION, RISK_OVERRIDE, RULE_DESCRIPTION_INPUT, RULE_NAME_INPUT, RULE_NAME_OVERRIDE, - RULE_STATUS, RULE_TIMESTAMP_OVERRIDE, RULES_CREATION_FORM, RULES_CREATION_PREVIEW_BUTTON, @@ -696,16 +694,6 @@ export const waitForAlertsToPopulate = (alertCountThreshold = 1) => { waitForAlerts(); }; -export const waitForTheRuleToBeExecuted = () => { - cy.waitUntil(() => { - cy.get(REFRESH_BUTTON).click({ force: true }); - return cy - .get(RULE_STATUS) - .invoke('text') - .then((ruleStatus) => ruleStatus === 'succeeded'); - }); -}; - export const selectAndLoadSavedQuery = (queryName: string, queryValue: string) => { cy.get(QUERY_BAR).find(SHOW_QUERY_BAR_BUTTON).click(); diff --git a/x-pack/test/security_solution_cypress/cypress/tasks/integrations.ts b/x-pack/test/security_solution_cypress/cypress/tasks/integrations.ts index e7c487971fba3..c7da263d42f42 100644 --- a/x-pack/test/security_solution_cypress/cypress/tasks/integrations.ts +++ b/x-pack/test/security_solution_cypress/cypress/tasks/integrations.ts @@ -5,23 +5,77 @@ * 2.0. */ +import { TypeOf } from '@kbn/config-schema'; import { - ADD_INTEGRATION_BTN, - INTEGRATION_ADDED_POP_UP, - QUEUE_URL, - SAVE_AND_CONTINUE_BTN, - SKIP_AGENT_INSTALLATION_BTN, -} from '../screens/integrations'; + AGENT_POLICY_API_ROUTES, + CreateAgentPolicyResponse, + EPM_API_ROUTES, + PACKAGE_POLICY_API_ROUTES, +} from '@kbn/fleet-plugin/common'; +import { + NewAgentPolicySchema, + SimplifiedCreatePackagePolicyRequestBodySchema, +} from '@kbn/fleet-plugin/server/types'; +import { rootRequest } from './common'; + +interface Package { + name: string; + version: string; +} -import { visit } from './login'; +export type AgentPolicy = TypeOf; +export type PackagePolicy = TypeOf; +export type PackagePolicyWithoutAgentPolicyId = Omit; + +/** + * Installs provided integrations by installing provided packages, creating an agent policy and adding a package policy. + * An agent policy is created with System integration enabled (with `?sys_monitoring=true` query param). + * + * Agent and package policies can be generated in Kibana by opening Fleet UI e.g. for AWS CloudFront the steps are following + * + * - open `app/integrations/detail/aws-1.17.0/overview?integration=cloudfront` + * - click the button `Add Amazon CloudFront` + * - fill in `Queue URL` + * - press `Preview API request` at the bottom + * - copy shown policies + */ +export function installIntegrations({ + packages, + agentPolicy, + packagePolicy, +}: { + packages: Package[]; + agentPolicy: AgentPolicy; + packagePolicy: Omit; +}): void { + // Bulk install provided packages + rootRequest({ + method: 'POST', + url: EPM_API_ROUTES.BULK_INSTALL_PATTERN, + body: { + packages, + force: true, + }, + headers: { 'kbn-xsrf': 'cypress-creds', 'x-elastic-internal-origin': 'security-solution' }, + }); -export const installAwsCloudFrontWithPolicy = () => { - visit('app/integrations/detail/aws-1.17.0/overview?integration=cloudfront'); - cy.get(ADD_INTEGRATION_BTN).click(); - cy.get(SKIP_AGENT_INSTALLATION_BTN).click(); - cy.get(QUEUE_URL).type('http://www.example.com'); + // Install agent and package policies + rootRequest({ + 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' }, + }).then((response) => { + const packagePolicyWithAgentPolicyId: PackagePolicy = { + ...packagePolicy, + policy_id: response.body.item.id, + }; - // Fleet installs an integration very slowly, so we have to increase the timeout here. - cy.get(SAVE_AND_CONTINUE_BTN).click(); - cy.get(INTEGRATION_ADDED_POP_UP, { timeout: 120000 }).should('exist'); -}; + rootRequest({ + method: 'POST', + url: PACKAGE_POLICY_API_ROUTES.CREATE_PATTERN, + body: packagePolicyWithAgentPolicyId, + headers: { 'kbn-xsrf': 'cypress-creds', 'x-elastic-internal-origin': 'security-solution' }, + }); + }); +} diff --git a/x-pack/test/security_solution_cypress/cypress/tasks/rule_details.ts b/x-pack/test/security_solution_cypress/cypress/tasks/rule_details.ts index e40f8c375e83a..871cbcb82ab7a 100644 --- a/x-pack/test/security_solution_cypress/cypress/tasks/rule_details.ts +++ b/x-pack/test/security_solution_cypress/cypress/tasks/rule_details.ts @@ -6,6 +6,7 @@ */ import type { Exception } from '../objects/exception'; +import { PAGE_CONTENT_SPINNER } from '../screens/common/page'; import { RULE_STATUS } from '../screens/create_new_rule'; import { ADD_EXCEPTIONS_BTN_FROM_EMPTY_PROMPT_BTN, @@ -17,7 +18,7 @@ import { ALERTS_TAB, EXCEPTIONS_TAB, FIELDS_BROWSER_BTN, - REFRESH_BUTTON, + LAST_EXECUTION_STATUS_REFRESH_BUTTON, REMOVE_EXCEPTION_BTN, RULE_SWITCH, DEFINITION_DETAILS, @@ -31,6 +32,7 @@ import { BACK_TO_RULES_TABLE, EXCEPTIONS_TAB_EXPIRED_FILTER, EXCEPTIONS_TAB_ACTIVE_FILTER, + RULE_NAME_HEADER, } from '../screens/rule_details'; import { addExceptionConditions, @@ -114,10 +116,22 @@ export const removeException = () => { cy.get(REMOVE_EXCEPTION_BTN).click(); }; +/** + * Waits for rule details page to be loaded + * + * @param ruleName rule's name + */ +export const waitForPageToBeLoaded = (ruleName: string): void => { + cy.get(PAGE_CONTENT_SPINNER).should('be.visible'); + cy.contains(RULE_NAME_HEADER, ruleName).should('be.visible'); + cy.get(PAGE_CONTENT_SPINNER).should('not.exist'); +}; + export const waitForTheRuleToBeExecuted = () => { cy.waitUntil(() => { - cy.log('Wating for the rule to be executed'); - cy.get(REFRESH_BUTTON).click({ force: true }); + cy.log('Waiting for the rule to be executed'); + cy.get(LAST_EXECUTION_STATUS_REFRESH_BUTTON).click(); + return cy .get(RULE_STATUS) .invoke('text') diff --git a/x-pack/test/security_solution_cypress/cypress/tasks/rule_details_flyout.ts b/x-pack/test/security_solution_cypress/cypress/tasks/rule_details_flyout.ts new file mode 100644 index 0000000000000..b684ccf6cdfe7 --- /dev/null +++ b/x-pack/test/security_solution_cypress/cypress/tasks/rule_details_flyout.ts @@ -0,0 +1,16 @@ +/* + * 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 { FILTER_INPUT, TABLE_TAB } from '../screens/rule_details_flyout'; + +export const openTable = (): void => { + cy.get(TABLE_TAB).click(); +}; + +export const filterBy = (value: string): void => { + cy.get(FILTER_INPUT).type(value); +}; diff --git a/x-pack/test/security_solution_cypress/cypress/tsconfig.json b/x-pack/test/security_solution_cypress/cypress/tsconfig.json index 30634b2af8052..46b8a6f12f492 100644 --- a/x-pack/test/security_solution_cypress/cypress/tsconfig.json +++ b/x-pack/test/security_solution_cypress/cypress/tsconfig.json @@ -44,5 +44,6 @@ "@kbn/cases-components", "@kbn/security-solution-plugin", "@kbn/expandable-flyout", + "@kbn/config-schema", ] }